[GPU] Fix resolve destination offset and extent calculation
This commit is contained in:
@@ -380,60 +380,19 @@ TextureGuestLayout GetGuestTextureLayout(
|
||||
// 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 = uint32_t(GetTiledOffset3D(
|
||||
int32_t(level_layout.x_extent_blocks -
|
||||
xenos::kTextureTileWidthHeight),
|
||||
int32_t(level_layout.y_extent_blocks -
|
||||
xenos::kTextureTileWidthHeight),
|
||||
int32_t(level_layout.z_extent - xenos::kTextureTileDepth),
|
||||
row_pitch_blocks_tile_aligned, level_layout.y_extent_blocks,
|
||||
bytes_per_block_log2));
|
||||
switch (bytes_per_block_log2) {
|
||||
case 0:
|
||||
// 64x32x8 portions have independent addressing.
|
||||
// Extent relative to the 32x32x4 tile origin:
|
||||
// - Pitch = 32, 96, 160...: (Pitch / 64) * 0x1000 + 0x1000
|
||||
// - Pitch = 64, 128, 192...: (Pitch / 64) * 0x1000 + 0xC00
|
||||
level_layout.array_slice_data_extent_bytes +=
|
||||
((row_pitch_blocks_tile_aligned >> 6) << 12) + 0xC00 +
|
||||
((row_pitch_blocks_tile_aligned & (1 << 5)) << (10 - 5));
|
||||
break;
|
||||
default:
|
||||
// 32x32x8 portions have independent addressing.
|
||||
// Extent: ((Pitch / 32) * 0x1000 + 0x1000) * (BPB / 2)
|
||||
// Or: ((Pitch / 32) * 0x1000 / 2 + 0x1000 / 2) * BPB
|
||||
level_layout.array_slice_data_extent_bytes +=
|
||||
((row_pitch_blocks_tile_aligned << (12 - 5 - 1)) +
|
||||
(0x1000 >> 1))
|
||||
<< bytes_per_block_log2;
|
||||
break;
|
||||
}
|
||||
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 = uint32_t(GetTiledOffset2D(
|
||||
int32_t(level_layout.x_extent_blocks -
|
||||
xenos::kTextureTileWidthHeight),
|
||||
int32_t(level_layout.y_extent_blocks -
|
||||
xenos::kTextureTileWidthHeight),
|
||||
row_pitch_blocks_tile_aligned, bytes_per_block_log2));
|
||||
switch (bytes_per_block_log2) {
|
||||
case 0:
|
||||
// Independent addressing within 128x128 portions, but the extent is
|
||||
// 0xA00 bytes from the 32x32 tile origin.
|
||||
level_layout.array_slice_data_extent_bytes += 0xA00;
|
||||
break;
|
||||
case 1:
|
||||
// Independent addressing within 64x64 portions, but the extent is
|
||||
// 0xC00 bytes from the 32x32 tile origin.
|
||||
level_layout.array_slice_data_extent_bytes += 0xC00;
|
||||
break;
|
||||
default:
|
||||
level_layout.array_slice_data_extent_bytes +=
|
||||
UINT32_C(0x400) << bytes_per_block_log2;
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
@@ -548,6 +507,69 @@ int32_t GetTiledOffset3D(int32_t x, int32_t y, int32_t z, uint32_t pitch,
|
||||
return address;
|
||||
}
|
||||
|
||||
uint32_t GetTiledAddressUpperBound2D(uint32_t right, uint32_t bottom,
|
||||
uint32_t pitch,
|
||||
uint32_t bytes_per_block_log2) {
|
||||
if (!right || !bottom) {
|
||||
return 0;
|
||||
}
|
||||
// Get the origin of the 32x32 tile containing the last texel.
|
||||
uint32_t upper_bound = uint32_t(GetTiledOffset2D(
|
||||
int32_t((right - 1) & ~(xenos::kTextureTileWidthHeight - 1)),
|
||||
int32_t((bottom - 1) & ~(xenos::kTextureTileWidthHeight - 1)), pitch,
|
||||
bytes_per_block_log2));
|
||||
switch (bytes_per_block_log2) {
|
||||
case 0:
|
||||
// Independent addressing within 128x128 portions, but the extent is 0xA00
|
||||
// bytes from the 32x32 tile origin.
|
||||
upper_bound += 0xA00;
|
||||
break;
|
||||
case 1:
|
||||
// Independent addressing within 64x64 portions, but the extent is 0xC00
|
||||
// bytes from the 32x32 tile origin.
|
||||
upper_bound += 0xC00;
|
||||
break;
|
||||
default:
|
||||
upper_bound += UINT32_C(0x400) << bytes_per_block_log2;
|
||||
break;
|
||||
}
|
||||
return upper_bound;
|
||||
}
|
||||
|
||||
uint32_t GetTiledAddressUpperBound3D(uint32_t right, uint32_t bottom,
|
||||
uint32_t back, uint32_t pitch,
|
||||
uint32_t height,
|
||||
uint32_t bytes_per_block_log2) {
|
||||
if (!right || !bottom || !back) {
|
||||
return 0;
|
||||
}
|
||||
// Get the origin of the 32x32x4 tile containing the last texel.
|
||||
uint32_t upper_bound = uint32_t(GetTiledOffset3D(
|
||||
int32_t((right - 1) & ~(xenos::kTextureTileWidthHeight - 1)),
|
||||
int32_t((bottom - 1) & ~(xenos::kTextureTileWidthHeight - 1)),
|
||||
int32_t((back - 1) & ~(xenos::kTextureTileDepth - 1)), pitch, height,
|
||||
bytes_per_block_log2));
|
||||
uint32_t pitch_aligned = xe::align(pitch, xenos::kTextureTileWidthHeight);
|
||||
switch (bytes_per_block_log2) {
|
||||
case 0:
|
||||
// 64x32x8 portions have independent addressing.
|
||||
// Extent relative to the 32x32x4 tile origin:
|
||||
// - Pitch = 32, 96, 160...: (Pitch / 64) * 0x1000 + 0x1000
|
||||
// - Pitch = 64, 128, 192...: (Pitch / 64) * 0x1000 + 0xC00
|
||||
upper_bound += ((pitch_aligned >> 6) << 12) + 0xC00 +
|
||||
((pitch_aligned & (1 << 5)) << (10 - 5));
|
||||
break;
|
||||
default:
|
||||
// 32x32x8 portions have independent addressing.
|
||||
// Extent: ((Pitch / 32) * 0x1000 + 0x1000) * (BPB / 2)
|
||||
// Or: ((Pitch / 32) * 0x1000 / 2 + 0x1000 / 2) * BPB
|
||||
upper_bound += ((pitch_aligned << (12 - 5 - 1)) + (0x1000 >> 1))
|
||||
<< bytes_per_block_log2;
|
||||
break;
|
||||
}
|
||||
return upper_bound;
|
||||
}
|
||||
|
||||
uint8_t SwizzleSigns(const xenos::xe_gpu_texture_fetch_t& fetch) {
|
||||
uint8_t signs = 0;
|
||||
bool any_not_signed = false, any_signed = false;
|
||||
|
||||
Reference in New Issue
Block a user