[GPU] Document tiled texture address bits

Will be useful for calculating memory extents more precisely in the future.
This commit is contained in:
Triang3l
2026-01-06 17:47:19 +03:00
parent cbbaae8ead
commit 28b69c21be
157 changed files with 121197 additions and 128800 deletions

View File

@@ -14,6 +14,7 @@
#include "xenia/base/assert.h"
#include "xenia/base/math.h"
#include "xenia/gpu/texture_address.h"
namespace xe {
namespace gpu {
@@ -414,10 +415,10 @@ TextureGuestLayout GetGuestTextureLayout(
uint32_t bytes_per_block_log2 = xe::log2_floor(bytes_per_block);
if (dimension == xenos::DataDimension::k3D) {
level_layout.array_slice_data_extent_bytes =
GetTiledAddressUpperBound3D(
uint32_t(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);
level_layout.z_slice_stride_block_rows, bytes_per_block_log2));
} else {
level_layout.array_slice_data_extent_bytes =
GetTiledAddressUpperBound2D(
@@ -447,62 +448,17 @@ TextureGuestLayout GetGuestTextureLayout(
return layout;
}
int32_t GetTiledOffset2D(int32_t x, int32_t y, uint32_t pitch,
uint32_t bytes_per_block_log2) {
// https://github.com/gildor2/UModel/blob/de8fbd3bc922427ea056b7340202dcdcc19ccff5/Unreal/UnTexture.cpp#L489
pitch = xe::align(pitch, xenos::kTextureTileWidthHeight);
// Top bits of coordinates.
int32_t macro = ((x >> 5) + (y >> 5) * int32_t(pitch >> 5))
<< (bytes_per_block_log2 + 7);
// Lower bits of coordinates (result is 6-bit value).
int32_t micro = ((x & 7) + ((y & 0xE) << 2)) << bytes_per_block_log2;
// Mix micro/macro + add few remaining x/y bits.
int32_t offset =
macro + ((micro & ~0xF) << 1) + (micro & 0xF) + ((y & 1) << 4);
// Mix bits again.
return ((offset & ~0x1FF) << 3) + ((y & 16) << 7) + ((offset & 0x1C0) << 2) +
(((((y & 8) >> 2) + (x >> 3)) & 3) << 6) + (offset & 0x3F);
}
int32_t GetTiledOffset3D(int32_t x, int32_t y, int32_t z, uint32_t pitch,
uint32_t height, uint32_t bytes_per_block_log2) {
// Reconstructed from disassembly of XGRAPHICS::TileVolume.
pitch = xe::align(pitch, xenos::kTextureTileWidthHeight);
height = xe::align(height, xenos::kTextureTileWidthHeight);
int32_t macro_outer =
((y >> 4) + (z >> 2) * int32_t(height >> 4)) * int32_t(pitch >> 5);
int32_t macro =
((((x >> 5) + macro_outer) << (bytes_per_block_log2 + 6)) & 0xFFFFFFF)
<< 1;
int32_t micro =
(((x & 7) + ((y & 6) << 2)) << (bytes_per_block_log2 + 6)) >> 6;
int32_t offset_outer = ((y >> 3) + (z >> 2)) & 1;
int32_t offset1 =
offset_outer + ((((x >> 3) + (offset_outer << 1)) & 3) << 1);
int32_t offset2 = ((macro + (micro & ~15)) << 1) + (micro & 15) +
((z & 3) << (bytes_per_block_log2 + 6)) + ((y & 1) << 4);
int32_t address = (offset1 & 1) << 3;
address += (offset2 >> 6) & 7;
address <<= 3;
address += offset1 & ~1;
address <<= 2;
address += offset2 & ~511;
address <<= 3;
address += offset2 & 63;
return address;
}
uint32_t GetTiledAddressUpperBound2D(uint32_t right, uint32_t bottom,
uint32_t pitch,
uint32_t pitch_aligned,
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(
uint32_t upper_bound = uint32_t(texture_address::Tiled2D(
int32_t((right - 1) & ~(xenos::kTextureTileWidthHeight - 1)),
int32_t((bottom - 1) & ~(xenos::kTextureTileWidthHeight - 1)), pitch,
bytes_per_block_log2));
int32_t((bottom - 1) & ~(xenos::kTextureTileWidthHeight - 1)),
pitch_aligned, bytes_per_block_log2));
switch (bytes_per_block_log2) {
case 0:
// Independent addressing within 128x128 portions, but the extent is 0xA00
@@ -521,20 +477,19 @@ uint32_t GetTiledAddressUpperBound2D(uint32_t right, uint32_t bottom,
return upper_bound;
}
uint32_t GetTiledAddressUpperBound3D(uint32_t right, uint32_t bottom,
uint32_t back, uint32_t pitch,
uint32_t height,
uint64_t GetTiledAddressUpperBound3D(uint32_t right, uint32_t bottom,
uint32_t back, uint32_t pitch_aligned,
uint32_t height_aligned,
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(
uint64_t upper_bound = uint64_t(texture_address::Tiled3D(
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);
int32_t((back - 1) & ~(xenos::kTextureTileDepth - 1)), pitch_aligned,
height_aligned, bytes_per_block_log2));
switch (bytes_per_block_log2) {
case 0:
// 64x32x8 portions have independent addressing.