TextureInfo: Store the texture format, not a pointer to texture format info.

This commit is contained in:
Dr. Chat 2017-04-07 15:10:35 -05:00
parent 59f9a19d30
commit b40d75aa3d
4 changed files with 122 additions and 80 deletions

View File

@ -714,8 +714,7 @@ bool TextureCache::UploadTexture1D(GLuint texture,
const auto host_address =
memory_->TranslatePhysical(texture_info.guest_address);
const auto& config =
texture_configs[uint32_t(texture_info.format_info->format)];
const auto& config = texture_configs[uint32_t(texture_info.texture_format)];
if (config.format == GL_INVALID_ENUM) {
assert_always("Unhandled texture format");
return false;
@ -771,7 +770,7 @@ bool TextureCache::UploadTexture2D(GLuint texture,
memory_->TranslatePhysical(texture_info.guest_address);
const auto& config =
texture_configs[uint32_t(texture_info.format_info->format)];
texture_configs[uint32_t(texture_info.format_info()->format)];
if (config.format == GL_INVALID_ENUM) {
assert_always("Unhandled texture format");
return false;
@ -788,9 +787,9 @@ bool TextureCache::UploadTexture2D(GLuint texture,
uint32_t offset_x, offset_y;
if (texture_info.has_packed_mips &&
TextureInfo::GetPackedTileOffset(texture_info, &offset_x, &offset_y)) {
uint32_t bytes_per_block = texture_info.format_info->block_width *
texture_info.format_info->block_height *
texture_info.format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = texture_info.format_info()->block_width *
texture_info.format_info()->block_height *
texture_info.format_info()->bits_per_pixel / 8;
const uint8_t* src = host_address;
// TODO(gibbed): this needs checking
src += offset_y * texture_info.size_2d.input_pitch;
@ -833,9 +832,9 @@ bool TextureCache::UploadTexture2D(GLuint texture,
// TODO(benvanik): optimize this inner loop (or work by tiles).
const uint8_t* src = host_address;
uint8_t* dest = reinterpret_cast<uint8_t*>(allocation.host_ptr);
uint32_t bytes_per_block = texture_info.format_info->block_width *
texture_info.format_info->block_height *
texture_info.format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = texture_info.format_info()->block_width *
texture_info.format_info()->block_height *
texture_info.format_info()->bits_per_pixel / 8;
// Tiled textures can be packed; get the offset into the packed texture.
uint32_t offset_x;
@ -849,8 +848,9 @@ bool TextureCache::UploadTexture2D(GLuint texture,
texture_info.size_2d.logical_height);
y++, output_base_offset += texture_info.size_2d.output_pitch) {
auto input_base_offset = TextureInfo::TiledOffset2DOuter(
offset_y + y, (texture_info.size_2d.input_width /
texture_info.format_info->block_width),
offset_y + y,
(texture_info.size_2d.input_width /
texture_info.format_info()->block_width),
bpp);
for (uint32_t x = 0, output_offset = output_base_offset;
x < texture_info.size_2d.block_width;
@ -899,7 +899,7 @@ bool TextureCache::UploadTextureCube(GLuint texture,
memory_->TranslatePhysical(texture_info.guest_address);
const auto& config =
texture_configs[uint32_t(texture_info.format_info->format)];
texture_configs[uint32_t(texture_info.format_info()->format)];
if (config.format == GL_INVALID_ENUM) {
assert_always("Unhandled texture format");
return false;
@ -937,9 +937,9 @@ bool TextureCache::UploadTextureCube(GLuint texture,
// TODO(benvanik): optimize this inner loop (or work by tiles).
const uint8_t* src = host_address;
uint8_t* dest = reinterpret_cast<uint8_t*>(allocation.host_ptr);
uint32_t bytes_per_block = texture_info.format_info->block_width *
texture_info.format_info->block_height *
texture_info.format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = texture_info.format_info()->block_width *
texture_info.format_info()->block_height *
texture_info.format_info()->bits_per_pixel / 8;
// Tiled textures can be packed; get the offset into the packed texture.
uint32_t offset_x;
uint32_t offset_y;
@ -951,8 +951,9 @@ bool TextureCache::UploadTextureCube(GLuint texture,
y < texture_info.size_cube.block_height;
y++, output_base_offset += texture_info.size_cube.output_pitch) {
auto input_base_offset = TextureInfo::TiledOffset2DOuter(
offset_y + y, (texture_info.size_cube.input_width /
texture_info.format_info->block_width),
offset_y + y,
(texture_info.size_cube.input_width /
texture_info.format_info()->block_width),
bpp);
for (uint32_t x = 0, output_offset = output_base_offset;
x < texture_info.size_cube.block_width;

View File

@ -132,14 +132,14 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
info.depth = fetch.size_stack.depth;
break;
}
info.format_info = FormatInfo::Get(fetch.format);
info.texture_format = static_cast<TextureFormat>(fetch.format);
info.endianness = static_cast<Endian>(fetch.endianness);
info.is_tiled = fetch.tiled;
info.has_packed_mips = fetch.packed_mips;
info.input_length = 0; // Populated below.
info.output_length = 0;
if (info.format_info->format == TextureFormat::kUnknown) {
if (info.format_info()->format == TextureFormat::kUnknown) {
assert_true("Unsupported texture format");
return false;
}
@ -154,13 +154,13 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
fetch.size_2d.height + 1);
// DEBUG: Make sure our calculated pitch is equal to the fetch pitch.
uint32_t bytes_per_block = info.format_info->block_width *
info.format_info->block_height *
info.format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = info.format_info()->block_width *
info.format_info()->block_height *
info.format_info()->bits_per_pixel / 8;
assert_true(info.size_2d.input_pitch ==
(bytes_per_block * fetch.pitch << 5) /
info.format_info->block_width);
info.format_info()->block_width);
} break;
case Dimension::k3D: {
// TODO(benvanik): calculate size.
@ -186,14 +186,14 @@ bool TextureInfo::PrepareResolve(uint32_t physical_address,
info.dimension = Dimension::k2D;
info.width = width - 1;
info.height = height - 1;
info.format_info = FormatInfo::Get(static_cast<uint32_t>(texture_format));
info.texture_format = texture_format;
info.endianness = endian;
info.is_tiled = true;
info.has_packed_mips = false;
info.input_length = 0;
info.output_length = 0;
if (info.format_info->format == TextureFormat::kUnknown) {
if (info.format_info()->format == TextureFormat::kUnknown) {
assert_true("Unsupported texture format");
return false;
}
@ -206,15 +206,16 @@ void TextureInfo::CalculateTextureSizes1D(uint32_t width) {
// ?
size_1d.logical_width = width;
auto format = format_info();
uint32_t block_width =
xe::round_up(size_1d.logical_width, format_info->block_width) /
format_info->block_width;
xe::round_up(size_1d.logical_width, format->block_width) /
format->block_width;
uint32_t tile_width = xe::round_up(block_width, 32) / 32;
size_1d.block_width = tile_width * 32;
uint32_t bytes_per_block =
format_info->block_width * format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = format->block_width * format->bits_per_pixel / 8;
uint32_t byte_pitch = tile_width * 32 * bytes_per_block;
if (!is_tiled) {
@ -222,12 +223,12 @@ void TextureInfo::CalculateTextureSizes1D(uint32_t width) {
byte_pitch = xe::round_up(byte_pitch, 256);
}
size_1d.input_width = tile_width * 32 * format_info->block_width;
size_1d.input_width = tile_width * 32 * format->block_width;
size_1d.input_pitch = byte_pitch;
input_length = size_1d.input_pitch;
// TODO(DrChat): Remove this, leave it up to the backend.
size_1d.output_width = block_width * format_info->block_width;
size_1d.output_width = block_width * format->block_width;
size_1d.output_pitch = block_width * bytes_per_block;
output_length = size_1d.output_pitch;
}
@ -240,13 +241,15 @@ void TextureInfo::CalculateTextureSizes2D(uint32_t width, uint32_t height) {
// images and create GL textures. Changes here will impact that code.
// TODO(benvanik): generic texture copying utility.
auto format = format_info();
// w/h in blocks.
uint32_t block_width =
xe::round_up(size_2d.logical_width, format_info->block_width) /
format_info->block_width;
xe::round_up(size_2d.logical_width, format->block_width) /
format->block_width;
uint32_t block_height =
xe::round_up(size_2d.logical_height, format_info->block_height) /
format_info->block_height;
xe::round_up(size_2d.logical_height, format->block_height) /
format->block_height;
// Tiles are 32x32 blocks. The pitch of all textures must a multiple of tile
// dimensions.
@ -254,9 +257,8 @@ void TextureInfo::CalculateTextureSizes2D(uint32_t width, uint32_t height) {
size_2d.block_width = tile_width * 32;
size_2d.block_height = block_height;
uint32_t bytes_per_block = format_info->block_width *
format_info->block_height *
format_info->bits_per_pixel / 8;
uint32_t bytes_per_block =
format->block_width * format->block_height * format->bits_per_pixel / 8;
uint32_t byte_pitch = size_2d.block_width * bytes_per_block;
if (!is_tiled) {
@ -264,15 +266,15 @@ void TextureInfo::CalculateTextureSizes2D(uint32_t width, uint32_t height) {
byte_pitch = xe::round_up(byte_pitch, 256);
}
size_2d.input_width = size_2d.block_width * format_info->block_width;
size_2d.input_height = size_2d.block_height * format_info->block_height;
size_2d.input_width = size_2d.block_width * format->block_width;
size_2d.input_height = size_2d.block_height * format->block_height;
size_2d.input_pitch = byte_pitch;
input_length = size_2d.input_pitch * size_2d.block_height;
// TODO(DrChat): Remove this, leave it up to the backend.
size_2d.output_width = block_width * format_info->block_width;
size_2d.output_height = block_height * format_info->block_height;
size_2d.output_width = block_width * format->block_width;
size_2d.output_height = block_height * format->block_height;
size_2d.output_pitch = block_width * bytes_per_block;
output_length = size_2d.output_pitch * block_height;
@ -284,13 +286,15 @@ void TextureInfo::CalculateTextureSizesCube(uint32_t width, uint32_t height,
size_cube.logical_width = width;
size_cube.logical_height = height;
auto format = format_info();
// w/h in blocks must be a multiple of block size.
uint32_t block_width =
xe::round_up(size_cube.logical_width, format_info->block_width) /
format_info->block_width;
xe::round_up(size_cube.logical_width, format->block_width) /
format->block_width;
uint32_t block_height =
xe::round_up(size_cube.logical_height, format_info->block_height) /
format_info->block_height;
xe::round_up(size_cube.logical_height, format->block_height) /
format->block_height;
// Tiles are 32x32 blocks. All textures must be multiples of tile dimensions.
uint32_t tile_width = xe::round_up(block_width, 32) / 32;
@ -298,25 +302,24 @@ void TextureInfo::CalculateTextureSizesCube(uint32_t width, uint32_t height,
size_cube.block_width = tile_width * 32;
size_cube.block_height = tile_height * 32;
uint32_t bytes_per_block = format_info->block_width *
format_info->block_height *
format_info->bits_per_pixel / 8;
uint32_t bytes_per_block =
format->block_width * format->block_height * format->bits_per_pixel / 8;
uint32_t byte_pitch = size_cube.block_width * bytes_per_block;
if (!is_tiled) {
// Each row must be a multiple of 256 in linear textures.
byte_pitch = xe::round_up(byte_pitch, 256);
}
size_cube.input_width = size_cube.block_width * format_info->block_width;
size_cube.input_height = size_cube.block_height * format_info->block_height;
size_cube.input_width = size_cube.block_width * format->block_width;
size_cube.input_height = size_cube.block_height * format->block_height;
size_cube.input_pitch = byte_pitch;
size_cube.input_face_length = size_cube.input_pitch * size_cube.block_height;
input_length = size_cube.input_face_length * 6;
// TODO(DrChat): Remove this, leave it up to the backend.
size_cube.output_width = block_width * format_info->block_width;
size_cube.output_height = block_height * format_info->block_height;
size_cube.output_width = block_width * format->block_width;
size_cube.output_height = block_height * format->block_height;
size_cube.output_pitch = block_width * bytes_per_block;
size_cube.output_face_length = size_cube.output_pitch * block_height;
@ -375,8 +378,8 @@ bool TextureInfo::GetPackedTileOffset(const TextureInfo& texture_info,
*out_offset_x = 16;
*out_offset_y = 0;
}
*out_offset_x /= texture_info.format_info->block_width;
*out_offset_y /= texture_info.format_info->block_height;
*out_offset_x /= texture_info.format_info()->block_width;
*out_offset_y /= texture_info.format_info()->block_height;
return true;
}

View File

@ -88,6 +88,38 @@ enum class TextureFormat : uint32_t {
kUnknown = 0xFFFFFFFFu,
};
inline TextureFormat GetBaseFormat(TextureFormat texture_format) {
// These formats are used for resampling textures / gamma control.
switch (texture_format) {
case TextureFormat::k_16_EXPAND:
return TextureFormat::k_16;
case TextureFormat::k_16_16_EXPAND:
return TextureFormat::k_16_16;
case TextureFormat::k_16_16_16_16_EXPAND:
return TextureFormat::k_16_16_16_16;
case TextureFormat::k_8_8_8_8_AS_16_16_16_16:
return TextureFormat::k_8_8_8_8;
case TextureFormat::k_DXT1_AS_16_16_16_16:
return TextureFormat::k_DXT1;
case TextureFormat::k_DXT2_3_AS_16_16_16_16:
return TextureFormat::k_DXT2_3;
case TextureFormat::k_DXT4_5_AS_16_16_16_16:
return TextureFormat::k_DXT4_5;
case TextureFormat::k_2_10_10_10_AS_16_16_16_16:
return TextureFormat::k_2_10_10_10;
case TextureFormat::k_10_11_11_AS_16_16_16_16:
return TextureFormat::k_10_11_11;
case TextureFormat::k_11_11_10_AS_16_16_16_16:
return TextureFormat::k_11_11_10;
case TextureFormat::k_DXT3A_AS_1_1_1_1:
return TextureFormat::k_DXT3A;
default:
break;
}
return texture_format;
}
inline size_t GetTexelSize(TextureFormat format) {
switch (format) {
case TextureFormat::k_1_5_5_5:
@ -215,19 +247,23 @@ struct FormatInfo {
struct TextureInfo {
uint32_t guest_address;
TextureFormat texture_format;
Dimension dimension;
uint32_t width;
uint32_t height;
uint32_t depth;
const FormatInfo* format_info;
Endian endianness;
bool is_tiled;
bool has_packed_mips;
uint32_t input_length;
uint32_t output_length;
const FormatInfo* format_info() const {
return FormatInfo::Get(static_cast<uint32_t>(texture_format));
}
bool is_compressed() const {
return format_info->type == FormatType::kCompressed;
return format_info()->type == FormatType::kCompressed;
}
union {

View File

@ -334,8 +334,8 @@ TextureCache::Texture* TextureCache::AllocateTexture(
return nullptr;
}
assert_not_null(texture_info.format_info);
auto& config = texture_configs[int(texture_info.format_info->format)];
assert_not_null(texture_info.format_info());
auto& config = texture_configs[int(texture_info.format_info()->format)];
VkFormat format = config.host_format != VK_FORMAT_UNDEFINED
? config.host_format
: VK_FORMAT_R8G8B8A8_UNORM;
@ -517,6 +517,18 @@ TextureCache::Texture* TextureCache::Demand(const TextureInfo& texture_info,
return nullptr;
}
// Though we didn't find an exact match, that doesn't mean we're out of the
// woods yet. This texture could either be a portion of another texture or
// vice versa. Copy any overlapping textures into this texture.
// TODO: Byte count -> pixel count (on x and y axes)
VkOffset2D offset;
auto collide_tex = LookupAddress(
texture_info.guest_address, texture_info.width + 1,
texture_info.height + 1, texture_info.format_info()->format, &offset);
if (collide_tex != nullptr) {
// assert_always();
}
trace_writer_->WriteMemoryRead(texture_info.guest_address,
texture_info.input_length);
@ -555,16 +567,6 @@ TextureCache::Texture* TextureCache::Demand(const TextureInfo& texture_info,
"0x%.8X - 0x%.8X", texture_info.guest_address,
texture_info.guest_address + texture_info.output_length));
// Though we didn't find an exact match, that doesn't mean we're out of the
// woods yet. This texture could either be a portion of another texture or
// vice versa. Copy any overlapping textures into this texture.
// TODO: Byte count -> pixel count (on x and y axes)
/*
for (auto it = textures_.begin(); it != textures_.end(); ++it) {
// TODO(DrChat)
}
*/
// Okay. Now that the texture is uploaded from system memory, put a writewatch
// on it to tell us if it's been modified from the guest.
texture->access_watch_handle = memory_->AddPhysicalAccessWatch(
@ -915,9 +917,9 @@ void TextureCache::ConvertTexture2D(uint8_t* dest, const TextureInfo& src) {
uint32_t offset_x, offset_y;
if (src.has_packed_mips &&
TextureInfo::GetPackedTileOffset(src, &offset_x, &offset_y)) {
uint32_t bytes_per_block = src.format_info->block_width *
src.format_info->block_height *
src.format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = src.format_info()->block_width *
src.format_info()->block_height *
src.format_info()->bits_per_pixel / 8;
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
src_mem += offset_y * src.size_2d.input_pitch;
@ -955,9 +957,9 @@ void TextureCache::ConvertTexture2D(uint8_t* dest, const TextureInfo& src) {
// TODO(benvanik): optimize this inner loop (or work by tiles).
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
uint32_t bytes_per_block = src.format_info->block_width *
src.format_info->block_height *
src.format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = src.format_info()->block_width *
src.format_info()->block_height *
src.format_info()->bits_per_pixel / 8;
// Tiled textures can be packed; get the offset into the packed texture.
uint32_t offset_x;
@ -970,7 +972,7 @@ void TextureCache::ConvertTexture2D(uint8_t* dest, const TextureInfo& src) {
y++, output_base_offset += src.size_2d.output_pitch) {
auto input_base_offset = TextureInfo::TiledOffset2DOuter(
offset_y + y,
(src.size_2d.input_width / src.format_info->block_width), bpp);
(src.size_2d.input_width / src.format_info()->block_width), bpp);
for (uint32_t x = 0, output_offset = output_base_offset;
x < src.size_2d.block_width; x++, output_offset += bytes_per_block) {
auto input_offset =
@ -1008,9 +1010,9 @@ void TextureCache::ConvertTextureCube(uint8_t* dest, const TextureInfo& src) {
} else {
// TODO(benvanik): optimize this inner loop (or work by tiles).
const uint8_t* src_mem = reinterpret_cast<const uint8_t*>(host_address);
uint32_t bytes_per_block = src.format_info->block_width *
src.format_info->block_height *
src.format_info->bits_per_pixel / 8;
uint32_t bytes_per_block = src.format_info()->block_width *
src.format_info()->block_height *
src.format_info()->bits_per_pixel / 8;
// Tiled textures can be packed; get the offset into the packed texture.
uint32_t offset_x;
uint32_t offset_y;
@ -1023,7 +1025,7 @@ void TextureCache::ConvertTextureCube(uint8_t* dest, const TextureInfo& src) {
y++, output_base_offset += src.size_cube.output_pitch) {
auto input_base_offset = TextureInfo::TiledOffset2DOuter(
offset_y + y,
(src.size_cube.input_width / src.format_info->block_width), bpp);
(src.size_cube.input_width / src.format_info()->block_width), bpp);
for (uint32_t x = 0, output_offset = output_base_offset;
x < src.size_cube.block_width;
x++, output_offset += bytes_per_block) {