Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental
This commit is contained in:
@@ -265,10 +265,9 @@ TextureGuestLayout GetGuestTextureLayout(
|
||||
}
|
||||
layout.mips_total_extent_bytes = 0;
|
||||
|
||||
const FormatInfo* const format_info = FormatInfo::Get(format);
|
||||
const uint32_t bytes_per_block = format_info->bytes_per_block();
|
||||
const unsigned char block_width_sh = FormatInfo::GetWidthShift(format);
|
||||
const unsigned char block_height_sh = FormatInfo::GetHeightShift(format);
|
||||
const FormatInfo* format_info = FormatInfo::Get(format);
|
||||
uint32_t bytes_per_block = format_info->bytes_per_block();
|
||||
|
||||
// The loop counter can mean two things depending on whether the packed mip
|
||||
// tail is stored as mip 0, because in this case, it would be ambiguous since
|
||||
// both the base and the mips would be on "level 0", but stored separately and
|
||||
@@ -313,13 +312,10 @@ TextureGuestLayout GetGuestTextureLayout(
|
||||
z_slice_stride_texel_rows_unaligned =
|
||||
std::max(xe::next_pow2(height_texels) >> level, uint32_t(1));
|
||||
}
|
||||
// maybe do 1 << block_width_sh instead of format_info->block_width, since
|
||||
// we'll have cl loaded with the shift anyway
|
||||
uint32_t row_pitch_blocks_tile_aligned =
|
||||
xe::align(xe::align<uint32_t>(row_pitch_texels_unaligned,
|
||||
format_info->block_width) >>
|
||||
block_width_sh,
|
||||
xenos::kTextureTileWidthHeight);
|
||||
uint32_t row_pitch_blocks_tile_aligned = xe::align(
|
||||
xe::align(row_pitch_texels_unaligned, format_info->block_width) /
|
||||
format_info->block_width,
|
||||
xenos::kTextureTileWidthHeight);
|
||||
level_layout.row_pitch_bytes =
|
||||
row_pitch_blocks_tile_aligned * bytes_per_block;
|
||||
// Assuming the provided pitch is already 256-byte-aligned for linear, but
|
||||
@@ -331,11 +327,10 @@ TextureGuestLayout GetGuestTextureLayout(
|
||||
}
|
||||
level_layout.z_slice_stride_block_rows =
|
||||
dimension != xenos::DataDimension::k1D
|
||||
? xe::align<uint32_t>(
|
||||
xe::align<uint32_t>(z_slice_stride_texel_rows_unaligned,
|
||||
format_info->block_height) >>
|
||||
block_height_sh,
|
||||
xenos::kTextureTileWidthHeight)
|
||||
? xe::align(xe::align(z_slice_stride_texel_rows_unaligned,
|
||||
format_info->block_height) /
|
||||
format_info->block_height,
|
||||
xenos::kTextureTileWidthHeight)
|
||||
: 1;
|
||||
level_layout.array_slice_stride_bytes =
|
||||
level_layout.row_pitch_bytes * level_layout.z_slice_stride_block_rows;
|
||||
@@ -352,90 +347,76 @@ TextureGuestLayout GetGuestTextureLayout(
|
||||
// be smaller (especially in the 1280x720 linear k_8_8_8_8 case in 4E4D083E,
|
||||
// for which memory exactly for 1280x720 is allocated, and aligning the
|
||||
// height to 32 would cause access of an unallocated page) or bigger than
|
||||
// the stride. For tiled textures, this is the dimensions aligned to 32x32x4
|
||||
// blocks (or x1 for the missing dimensions).
|
||||
uint32_t level_width_blocks =
|
||||
xe::align<uint32_t>(std::max(width_texels >> level, uint32_t(1)),
|
||||
format_info->block_width) >>
|
||||
block_width_sh;
|
||||
uint32_t level_height_blocks =
|
||||
xe::align<uint32_t>(std::max(height_texels >> level, uint32_t(1)),
|
||||
format_info->block_height) >>
|
||||
block_height_sh;
|
||||
uint32_t level_depth = std::max(depth >> level, uint32_t(1));
|
||||
if (is_tiled) {
|
||||
// the stride.
|
||||
if (level == layout.packed_level) {
|
||||
// Calculate the portion of the mip tail actually used by the needed mips.
|
||||
// The actually used region may be significantly smaller than the full
|
||||
// 32x32-texel-aligned (and, for mips, calculated from the base dimensions
|
||||
// rounded to powers of two - 58410A7A has an 80x260 tiled texture with
|
||||
// packed mips at level 3 containing a mip ending at Y = 36, while
|
||||
// 260 >> 3 == 32, but 512 >> 3 == 64) tail. A 2x2 texture (for example,
|
||||
// in 494707D4, there's a 2x2 k_8_8_8_8 linear texture with packed mips),
|
||||
// for instance, would have its 2x2 base at (16, 0) and its 1x1 mip at
|
||||
// (8, 0) - and we need 2 or 1 rows in these cases, not 32 - the 32 rows
|
||||
// in a linear texture (with 256-byte pitch alignment) would span two 4 KB
|
||||
// pages rather than one.
|
||||
level_layout.x_extent_blocks = 0;
|
||||
level_layout.y_extent_blocks = 0;
|
||||
level_layout.z_extent = 0;
|
||||
uint32_t packed_sublevel_last = is_base ? 0 : max_level;
|
||||
for (uint32_t packed_sublevel = layout.packed_level;
|
||||
packed_sublevel <= packed_sublevel_last; ++packed_sublevel) {
|
||||
uint32_t packed_sublevel_x_blocks;
|
||||
uint32_t packed_sublevel_y_blocks;
|
||||
uint32_t packed_sublevel_z;
|
||||
GetPackedMipOffset(width_texels, height_texels, depth, format,
|
||||
packed_sublevel, packed_sublevel_x_blocks,
|
||||
packed_sublevel_y_blocks, packed_sublevel_z);
|
||||
level_layout.x_extent_blocks = std::max(
|
||||
level_layout.x_extent_blocks,
|
||||
packed_sublevel_x_blocks +
|
||||
xe::align(
|
||||
std::max(width_texels >> packed_sublevel, uint32_t(1)),
|
||||
format_info->block_width) /
|
||||
format_info->block_width);
|
||||
level_layout.y_extent_blocks = std::max(
|
||||
level_layout.y_extent_blocks,
|
||||
packed_sublevel_y_blocks +
|
||||
xe::align(
|
||||
std::max(height_texels >> packed_sublevel, uint32_t(1)),
|
||||
format_info->block_height) /
|
||||
format_info->block_height);
|
||||
level_layout.z_extent =
|
||||
std::max(level_layout.z_extent,
|
||||
packed_sublevel_z +
|
||||
std::max(depth >> packed_sublevel, uint32_t(1)));
|
||||
}
|
||||
} else {
|
||||
level_layout.x_extent_blocks =
|
||||
xe::align(level_width_blocks, xenos::kTextureTileWidthHeight);
|
||||
xe::align(std::max(width_texels >> level, uint32_t(1)),
|
||||
format_info->block_width) /
|
||||
format_info->block_width;
|
||||
level_layout.y_extent_blocks =
|
||||
xe::align(level_height_blocks, xenos::kTextureTileWidthHeight);
|
||||
xe::align(std::max(height_texels >> level, uint32_t(1)),
|
||||
format_info->block_height) /
|
||||
format_info->block_height;
|
||||
level_layout.z_extent = std::max(depth >> level, uint32_t(1));
|
||||
}
|
||||
if (is_tiled) {
|
||||
uint32_t bytes_per_block_log2 = xe::log2_floor(bytes_per_block);
|
||||
if (dimension == xenos::DataDimension::k3D) {
|
||||
level_layout.z_extent =
|
||||
xe::align(level_depth, xenos::kTextureTileDepth);
|
||||
// 32-block-row x 4 slice portions laid out sequentially (4-slice-major,
|
||||
// 32-block-row-minor), address extent within a 32x32x4 tile depends on
|
||||
// the pitch. Origins of 32x32x4 tiles grow monotonically, first along
|
||||
// Z, then along Y, then along X.
|
||||
level_layout.array_slice_data_extent_bytes =
|
||||
GetTiledAddressUpperBound3D(
|
||||
level_layout.x_extent_blocks, level_layout.y_extent_blocks,
|
||||
level_layout.z_extent, row_pitch_blocks_tile_aligned,
|
||||
level_layout.y_extent_blocks, bytes_per_block_log2);
|
||||
} else {
|
||||
level_layout.z_extent = 1;
|
||||
// Origins of 32x32 tiles grow monotonically, first along Y, then along
|
||||
// X.
|
||||
level_layout.array_slice_data_extent_bytes =
|
||||
GetTiledAddressUpperBound2D(
|
||||
level_layout.x_extent_blocks, level_layout.y_extent_blocks,
|
||||
row_pitch_blocks_tile_aligned, bytes_per_block_log2);
|
||||
}
|
||||
} else {
|
||||
if (level == layout.packed_level) {
|
||||
// Calculate the portion of the mip tail actually used by the needed
|
||||
// mips. The actually used region may be significantly smaller than the
|
||||
// full 32x32-texel-aligned tail. A 2x2 texture (for example, in
|
||||
// 494707D4, there's a 2x2 k_8_8_8_8 linear texture with packed mips),
|
||||
// for instance, would have its 2x2 base at (16, 0) and its 1x1 mip at
|
||||
// (8, 0) - and we need 2 or 1 rows in these cases, not 32 - the 32 rows
|
||||
// would span two 4 KB pages rather than one, taking the 256-byte pitch
|
||||
// alignment in linear textures into account.
|
||||
level_layout.x_extent_blocks = 0;
|
||||
level_layout.y_extent_blocks = 0;
|
||||
level_layout.z_extent = 0;
|
||||
uint32_t packed_sublevel_last = is_base ? 0 : max_level;
|
||||
for (uint32_t packed_sublevel = layout.packed_level;
|
||||
packed_sublevel <= packed_sublevel_last; ++packed_sublevel) {
|
||||
uint32_t packed_sublevel_x_blocks;
|
||||
uint32_t packed_sublevel_y_blocks;
|
||||
uint32_t packed_sublevel_z;
|
||||
GetPackedMipOffset(width_texels, height_texels, depth, format,
|
||||
packed_sublevel, packed_sublevel_x_blocks,
|
||||
packed_sublevel_y_blocks, packed_sublevel_z);
|
||||
level_layout.x_extent_blocks = std::max<uint32_t>(
|
||||
level_layout.x_extent_blocks,
|
||||
packed_sublevel_x_blocks +
|
||||
(xe::align<uint32_t>(
|
||||
std::max(width_texels >> packed_sublevel, uint32_t(1)),
|
||||
format_info->block_width) >>
|
||||
block_width_sh));
|
||||
level_layout.y_extent_blocks = std::max<uint32_t>(
|
||||
level_layout.y_extent_blocks,
|
||||
packed_sublevel_y_blocks +
|
||||
(xe::align<uint32_t>(
|
||||
std::max(height_texels >> packed_sublevel, uint32_t(1)),
|
||||
format_info->block_height) >>
|
||||
block_height_sh));
|
||||
level_layout.z_extent =
|
||||
std::max(level_layout.z_extent,
|
||||
packed_sublevel_z +
|
||||
std::max(depth >> packed_sublevel, uint32_t(1)));
|
||||
}
|
||||
} else {
|
||||
level_layout.x_extent_blocks = level_width_blocks;
|
||||
level_layout.y_extent_blocks = level_height_blocks;
|
||||
level_layout.z_extent = level_depth;
|
||||
}
|
||||
level_layout.array_slice_data_extent_bytes =
|
||||
z_stride_bytes * (level_layout.z_extent - 1) +
|
||||
level_layout.row_pitch_bytes * (level_layout.y_extent_blocks - 1) +
|
||||
|
||||
Reference in New Issue
Block a user