TextureInfo: PrepareResolve, Reorganize source, add better documentation

This commit is contained in:
Dr. Chat 2017-03-14 22:46:47 -05:00
parent 581875b339
commit 4a815e62cb
3 changed files with 119 additions and 85 deletions

View File

@ -145,29 +145,66 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
} }
// Must be called here when we know the format. // Must be called here when we know the format.
info.input_length = 0; // Populated below.
info.output_length = 0;
switch (info.dimension) { switch (info.dimension) {
case Dimension::k1D: case Dimension::k1D: {
info.CalculateTextureSizes1D(fetch); info.CalculateTextureSizes1D(fetch.size_1d.width + 1);
break; } break;
case Dimension::k2D: case Dimension::k2D: {
info.CalculateTextureSizes2D(fetch); info.CalculateTextureSizes2D(fetch.size_2d.width + 1,
break; fetch.size_2d.height + 1);
case Dimension::k3D:
// 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;
assert_true(info.size_2d.input_pitch ==
(bytes_per_block * fetch.pitch << 5) /
info.format_info->block_width);
} break;
case Dimension::k3D: {
// TODO(benvanik): calculate size. // TODO(benvanik): calculate size.
return false; return false;
case Dimension::kCube: }
info.CalculateTextureSizesCube(fetch); case Dimension::kCube: {
break; info.CalculateTextureSizesCube(fetch.size_stack.width + 1,
fetch.size_stack.height + 1,
fetch.size_stack.depth + 1);
} break;
} }
return true; return true;
} }
void TextureInfo::CalculateTextureSizes1D(const xe_gpu_texture_fetch_t& fetch) { bool TextureInfo::PrepareResolve(uint32_t physical_address,
TextureFormat texture_format, Endian endian,
uint32_t width, uint32_t height,
TextureInfo* out_info) {
std::memset(out_info, 0, sizeof(TextureInfo));
auto& info = *out_info;
info.guest_address = 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.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) {
assert_true("Unsupported texture format");
return false;
}
info.CalculateTextureSizes2D(width, height);
return true;
}
void TextureInfo::CalculateTextureSizes1D(uint32_t width) {
// ? // ?
size_1d.logical_width = 1 + fetch.size_1d.width; size_1d.logical_width = width;
uint32_t block_width = uint32_t block_width =
xe::round_up(size_1d.logical_width, format_info->block_width) / xe::round_up(size_1d.logical_width, format_info->block_width) /
@ -186,25 +223,24 @@ void TextureInfo::CalculateTextureSizes1D(const xe_gpu_texture_fetch_t& fetch) {
} }
size_1d.input_width = tile_width * 32 * format_info->block_width; size_1d.input_width = tile_width * 32 * format_info->block_width;
size_1d.output_width = block_width * format_info->block_width;
size_1d.input_pitch = byte_pitch; size_1d.input_pitch = byte_pitch;
size_1d.output_pitch = block_width * bytes_per_block;
input_length = size_1d.input_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_pitch = block_width * bytes_per_block;
output_length = size_1d.output_pitch; output_length = size_1d.output_pitch;
} }
void TextureInfo::CalculateTextureSizes2D(const xe_gpu_texture_fetch_t& fetch) { void TextureInfo::CalculateTextureSizes2D(uint32_t width, uint32_t height) {
size_2d.logical_width = 1 + fetch.size_2d.width; size_2d.logical_width = width;
size_2d.logical_height = 1 + fetch.size_2d.height; size_2d.logical_height = height;
// Here be dragons. The values here are used in texture_cache.cc to copy // Here be dragons. The values here are used in texture_cache.cc to copy
// images and create GL textures. Changes here will impact that code. // images and create GL textures. Changes here will impact that code.
// TODO(benvanik): generic texture copying utility. // TODO(benvanik): generic texture copying utility.
// w/h in blocks must be a multiple of block size. // w/h in blocks.
uint32_t block_width = uint32_t block_width =
xe::round_up(size_2d.logical_width, format_info->block_width) / xe::round_up(size_2d.logical_width, format_info->block_width) /
format_info->block_width; format_info->block_width;
@ -212,15 +248,11 @@ void TextureInfo::CalculateTextureSizes2D(const xe_gpu_texture_fetch_t& fetch) {
xe::round_up(size_2d.logical_height, format_info->block_height) / xe::round_up(size_2d.logical_height, format_info->block_height) /
format_info->block_height; format_info->block_height;
// Tiles are 32x32 blocks. All textures must be multiples of tile dimensions. // Tiles are 32x32 blocks. The pitch of all textures must a multiple of tile
// ...except textures don't seem to need a multiple of 32 for height. // dimensions.
uint32_t tile_width = uint32_t(std::ceil(block_width / 32.0f)); uint32_t tile_width = uint32_t(std::ceil(block_width / 32.0f));
uint32_t tile_height = uint32_t(std::ceil(block_height / 32.0f));
size_2d.block_width = tile_width * 32; size_2d.block_width = tile_width * 32;
size_2d.block_height = size_2d.block_height = block_height;
/*format_info->type == FormatType::kCompressed
? tile_height * 32
:*/ block_height;
uint32_t bytes_per_block = format_info->block_width * uint32_t bytes_per_block = format_info->block_width *
format_info->block_height * format_info->block_height *
@ -234,22 +266,23 @@ void TextureInfo::CalculateTextureSizes2D(const xe_gpu_texture_fetch_t& fetch) {
size_2d.input_width = size_2d.block_width * format_info->block_width; 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_height = size_2d.block_height * format_info->block_height;
size_2d.output_width = block_width * format_info->block_width;
size_2d.output_height = block_height * format_info->block_height;
size_2d.input_pitch = byte_pitch; size_2d.input_pitch = byte_pitch;
size_2d.output_pitch = block_width * bytes_per_block;
input_length = size_2d.input_pitch * size_2d.block_height; 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_pitch = block_width * bytes_per_block;
output_length = size_2d.output_pitch * block_height; output_length = size_2d.output_pitch * block_height;
} }
void TextureInfo::CalculateTextureSizesCube( void TextureInfo::CalculateTextureSizesCube(uint32_t width, uint32_t height,
const xe_gpu_texture_fetch_t& fetch) { uint32_t depth) {
assert_true(fetch.size_stack.depth + 1 == 6); assert_true(depth == 6);
size_cube.logical_width = 1 + fetch.size_stack.width; size_cube.logical_width = width;
size_cube.logical_height = 1 + fetch.size_stack.height; size_cube.logical_height = height;
// w/h in blocks must be a multiple of block size. // w/h in blocks must be a multiple of block size.
uint32_t block_width = uint32_t block_width =
@ -268,23 +301,24 @@ void TextureInfo::CalculateTextureSizesCube(
uint32_t bytes_per_block = format_info->block_width * uint32_t bytes_per_block = format_info->block_width *
format_info->block_height * format_info->block_height *
format_info->bits_per_pixel / 8; format_info->bits_per_pixel / 8;
uint32_t byte_pitch = tile_width * 32 * bytes_per_block; uint32_t byte_pitch = size_cube.block_width * bytes_per_block;
if (!is_tiled) { if (!is_tiled) {
// Each row must be a multiple of 256 in linear textures. // Each row must be a multiple of 256 in linear textures.
byte_pitch = xe::round_up(byte_pitch, 256); byte_pitch = xe::round_up(byte_pitch, 256);
} }
size_cube.input_width = tile_width * 32 * format_info->block_width; size_cube.input_width = size_cube.block_width * format_info->block_width;
size_cube.input_height = tile_height * 32 * format_info->block_height; size_cube.input_height = size_cube.block_height * format_info->block_height;
size_cube.output_width = block_width * format_info->block_width;
size_cube.output_height = block_height * format_info->block_height;
size_cube.input_pitch = byte_pitch; size_cube.input_pitch = byte_pitch;
size_cube.output_pitch = block_width * bytes_per_block;
size_cube.input_face_length = size_cube.input_pitch * size_cube.block_height; size_cube.input_face_length = size_cube.input_pitch * size_cube.block_height;
input_length = size_cube.input_face_length * 6; 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_pitch = block_width * bytes_per_block;
size_cube.output_face_length = size_cube.output_pitch * block_height; size_cube.output_face_length = size_cube.output_pitch * block_height;
output_length = size_cube.output_face_length * 6; output_length = size_cube.output_face_length * 6;
} }
@ -346,7 +380,7 @@ bool TextureInfo::GetPackedTileOffset(const TextureInfo& texture_info,
return true; return true;
} }
// https://code.google.com/p/crunch/source/browse/trunk/inc/crn_decomp.h#4104 // https://github.com/BinomialLLC/crunch/blob/ea9b8d8c00c8329791256adafa8cf11e4e7942a2/inc/crn_decomp.h#L4108
uint32_t TextureInfo::TiledOffset2DOuter(uint32_t y, uint32_t width, uint32_t TextureInfo::TiledOffset2DOuter(uint32_t y, uint32_t width,
uint32_t log_bpp) { uint32_t log_bpp) {
uint32_t macro = ((y >> 5) * (width >> 5)) << (log_bpp + 7); uint32_t macro = ((y >> 5) * (width >> 5)) << (log_bpp + 7);

View File

@ -34,7 +34,7 @@ enum class TextureFormat : uint32_t {
k_8_8 = 10, k_8_8 = 10,
k_Cr_Y1_Cb_Y0 = 11, k_Cr_Y1_Cb_Y0 = 11,
k_Y1_Cr_Y0_Cb = 12, k_Y1_Cr_Y0_Cb = 12,
// ? hole k_Shadow = 13,
k_8_8_8_8_A = 14, k_8_8_8_8_A = 14,
k_4_4_4_4 = 15, k_4_4_4_4 = 15,
k_10_11_11 = 16, k_10_11_11 = 16,
@ -42,7 +42,7 @@ enum class TextureFormat : uint32_t {
k_DXT1 = 18, k_DXT1 = 18,
k_DXT2_3 = 19, k_DXT2_3 = 19,
k_DXT4_5 = 20, k_DXT4_5 = 20,
// ? hole k_DXV = 21,
k_24_8 = 22, k_24_8 = 22,
k_24_8_FLOAT = 23, k_24_8_FLOAT = 23,
k_16 = 24, k_16 = 24,
@ -233,20 +233,24 @@ struct TextureInfo {
union { union {
struct { struct {
uint32_t logical_width; uint32_t logical_width;
uint32_t block_width; uint32_t block_width; // # of horizontal blocks
uint32_t input_width; uint32_t input_width; // pixel pitch
uint32_t input_pitch; uint32_t input_pitch; // pitch in bytes
// DEPRECATED: Do not use.
uint32_t output_width; uint32_t output_width;
uint32_t output_pitch; uint32_t output_pitch;
} size_1d; } size_1d;
struct { struct {
uint32_t logical_width; uint32_t logical_width;
uint32_t logical_height; uint32_t logical_height;
uint32_t block_width; uint32_t block_width; // # of horizontal blocks
uint32_t block_height; uint32_t block_height; // # of vertical blocks
uint32_t input_width; uint32_t input_width; // pixel pitch
uint32_t input_height; uint32_t input_height; // pixel height
uint32_t input_pitch; uint32_t input_pitch; // pitch in bytes
// DEPRECATED: Do not use.
uint32_t output_width; uint32_t output_width;
uint32_t output_height; uint32_t output_height;
uint32_t output_pitch; uint32_t output_pitch;
@ -256,15 +260,17 @@ struct TextureInfo {
struct { struct {
uint32_t logical_width; uint32_t logical_width;
uint32_t logical_height; uint32_t logical_height;
uint32_t block_width; uint32_t block_width; // # of horizontal blocks
uint32_t block_height; uint32_t block_height; // # of vertical blocks
uint32_t input_width; uint32_t input_width; // pixel pitch
uint32_t input_height; uint32_t input_height; // pixel height
uint32_t input_pitch; uint32_t input_pitch; // pitch in bytes
uint32_t input_face_length; // pitch of face in bytes
// DEPRECATED: Do not use.
uint32_t output_width; uint32_t output_width;
uint32_t output_height; uint32_t output_height;
uint32_t output_pitch; uint32_t output_pitch;
uint32_t input_face_length;
uint32_t output_face_length; uint32_t output_face_length;
} size_cube; } size_cube;
}; };
@ -272,6 +278,11 @@ struct TextureInfo {
static bool Prepare(const xenos::xe_gpu_texture_fetch_t& fetch, static bool Prepare(const xenos::xe_gpu_texture_fetch_t& fetch,
TextureInfo* out_info); TextureInfo* out_info);
static bool PrepareResolve(uint32_t physical_address,
TextureFormat texture_format, Endian endian,
uint32_t width, uint32_t height,
TextureInfo* out_info);
static bool GetPackedTileOffset(const TextureInfo& texture_info, static bool GetPackedTileOffset(const TextureInfo& texture_info,
uint32_t* out_offset_x, uint32_t* out_offset_x,
uint32_t* out_offset_y); uint32_t* out_offset_y);
@ -286,9 +297,10 @@ struct TextureInfo {
} }
private: private:
void CalculateTextureSizes1D(const xenos::xe_gpu_texture_fetch_t& fetch); void CalculateTextureSizes1D(uint32_t width);
void CalculateTextureSizes2D(const xenos::xe_gpu_texture_fetch_t& fetch); void CalculateTextureSizes2D(uint32_t width, uint32_t height);
void CalculateTextureSizesCube(const xenos::xe_gpu_texture_fetch_t& fetch); void CalculateTextureSizesCube(uint32_t width, uint32_t height,
uint32_t depth);
}; };
} // namespace gpu } // namespace gpu

View File

@ -945,23 +945,11 @@ bool VulkanCommandProcessor::IssueCopy() {
} }
// Demand a resolve texture from the texture cache. // Demand a resolve texture from the texture cache.
TextureInfo tex_info = {}; TextureInfo tex_info;
tex_info.guest_address = copy_dest_base; TextureInfo::PrepareResolve(copy_dest_base, copy_dest_format, Endian::k8in32,
tex_info.width = dest_logical_width - 1; dest_logical_width, dest_logical_height,
tex_info.height = dest_logical_height - 1; &tex_info);
tex_info.dimension = gpu::Dimension::k2D;
tex_info.input_length =
dest_block_width * dest_block_height * dest_texel_size;
tex_info.format_info = FormatInfo::Get(uint32_t(copy_dest_format));
tex_info.endianness = Endian::k8in32;
tex_info.is_tiled = true;
tex_info.size_2d.logical_width = dest_logical_width;
tex_info.size_2d.logical_height = dest_logical_height;
tex_info.size_2d.block_width = dest_block_width;
tex_info.size_2d.block_height = dest_block_height;
tex_info.size_2d.input_width = dest_block_width;
tex_info.size_2d.input_height = dest_block_height;
tex_info.size_2d.input_pitch = copy_dest_pitch * dest_texel_size;
auto texture = auto texture =
texture_cache_->DemandResolveTexture(tex_info, copy_dest_format, nullptr); texture_cache_->DemandResolveTexture(tex_info, copy_dest_format, nullptr);
assert_not_null(texture); assert_not_null(texture);