[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

@@ -12,43 +12,43 @@
#include "../../ui/shaders/xesl.xesli"
int XeTextureTiledOffset2D(int2_xe p, uint pitch_aligned, uint bpb_log2) {
// https://github.com/gildor2/UModel/blob/de8fbd3bc922427ea056b7340202dcdcc19ccff5/Unreal/UnTexture.cpp#L489
// Top bits of coordinates.
int macro =
((p.x >> 5) + (p.y >> 5) * int(pitch_aligned >> 5u)) << (bpb_log2 + 7);
// Lower bits of coordinates (result is 6-bit value).
int micro = ((p.x & 7) + ((p.y & 0xE) << 2)) << bpb_log2;
// Mix micro/macro + add few remaining x/y bits.
int offset = macro + ((micro & ~0xF) << 1) + (micro & 0xF) + ((p.y & 1) << 4);
// Mix bits again.
return ((offset & ~0x1FF) << 3) + // Upper bits (offset bits [*-9]).
((p.y & 16) << 7) + // Next 1 bit.
((offset & 0x1C0) << 2) + // Next 3 bits (offset bits [8-6]).
(((((p.y & 8) >> 2) + (p.x >> 3)) & 3) << 6) + // Next 2 bits.
(offset & 0x3F); // Lower 6 bits (offset bits [5-0]).
int XenosTextureAddressTiledCombine(const int outer_inner_bytes, const int bank,
const int pipe, const int y_lsb) {
return (y_lsb << 4) | (pipe << 6) | (bank << 11) | (outer_inner_bytes & 0xF) |
(((outer_inner_bytes >> 4) & 0x1) << 5) |
(((outer_inner_bytes >> 5) & 0x7) << 8) |
(outer_inner_bytes >> 8 << 12);
}
int XeTextureTiledOffset3D(int3_xe p, uint pitch_aligned, uint height_aligned,
uint bpb_log2) {
// Reconstructed from disassembly of XGRAPHICS::TileVolume.
int macro_outer = ((p.y >> 4) + (p.z >> 2) * int(height_aligned >> 4u)) *
int(pitch_aligned >> 5u);
int macro = ((((p.x >> 5) + macro_outer) << (bpb_log2 + 6)) & 0xFFFFFFF) << 1;
int micro = (((p.x & 7) + ((p.y & 6) << 2)) << (bpb_log2 + 6)) >> 6;
int offset_outer = ((p.y >> 3) + (p.z >> 2)) & 1;
int offset1 = offset_outer + ((((p.x >> 3) + (offset_outer << 1)) & 3) << 1);
int offset2 = ((macro + (micro & ~15)) << 1) + (micro & 15) +
((p.z & 3) << (bpb_log2 + 6)) + ((p.y & 1) << 4);
int 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;
int XenosTextureAddressTiled2D(const int2_xe p, const uint pitch_aligned_shr5,
const uint bytes_per_element_log2) {
const int outer_elements =
((p.y >> 5) * int(pitch_aligned_shr5) + (p.x >> 5)) << 6;
const int inner_elements = (((p.y >> 1) & 0x7) << 3) | (p.x & 0x7);
const int outer_inner_bytes =
(outer_elements | inner_elements) << bytes_per_element_log2;
const int bank = (p.y >> 4) & 0x1;
const int pipe = ((p.x >> 3) & 0x3) ^ (((p.y >> 3) & 0x1) << 1);
return XenosTextureAddressTiledCombine(outer_inner_bytes, bank, pipe,
p.y & 1);
}
int XenosTextureAddressTiled3D(const int3_xe p, const uint pitch_aligned_shr5,
const uint height_aligned_shr4,
const uint bytes_per_element_log2) {
const int outer_elements =
((((p.z >> 2) * int(height_aligned_shr4) + (p.y >> 4)) *
int(pitch_aligned_shr5)) +
(p.x >> 5))
<< 7;
const int inner_elements =
((p.z & 0x3) << 5) | (((p.y >> 1) & 0x3) << 3) | (p.x & 0x7);
const int outer_inner_bytes =
(outer_elements | inner_elements) << bytes_per_element_log2;
const int bank = ((p.y >> 3) ^ (p.z >> 2)) & 0x1;
const int pipe = ((p.x >> 3) & 0x3) ^ (bank << 1);
return XenosTextureAddressTiledCombine(outer_inner_bytes, bank, pipe,
p.y & 1);
}
// Log2 of the number of blocks always laid out consecutively in memory along
@@ -89,8 +89,8 @@ uint XeTextureTiledOddConsecutiveBlocksOffset(uint bpb_log2) {
// This function is used only for non-negative positions within a texture, so
// for simplicity, especially of the division involved, assuming everything is
// unsigned.
uint XeTextureScaledTiledOffset(bool is_3d, uint3_xe p, uint pitch_aligned,
uint height_aligned, uint bpb_log2,
uint XeTextureScaledTiledOffset(bool is_3d, uint3_xe p, uint pitch_aligned_shr5,
uint height_aligned_shr4, uint bpb_log2,
uint2_xe scale) {
uint unit_width_log2 = XeTextureTiledConsecutiveBlocksLog2(bpb_log2);
// Global host X coordinate in host Nx1 sub-units.
@@ -103,13 +103,12 @@ uint XeTextureScaledTiledOffset(bool is_3d, uint3_xe p, uint pitch_aligned,
// Global guest linear address of the beginning of Nx1 unit in bytes.
uint unit_guest_address;
dont_flatten_xe if (is_3d) {
unit_guest_address =
uint(XeTextureTiledOffset3D(int3_xe(unit_guest_origin), pitch_aligned,
height_aligned, bpb_log2));
unit_guest_address = uint(XenosTextureAddressTiled3D(
int3_xe(unit_guest_origin), pitch_aligned_shr5, height_aligned_shr4,
bpb_log2));
} else {
unit_guest_address =
uint(XeTextureTiledOffset2D(int2_xe(unit_guest_origin.xy),
pitch_aligned, bpb_log2));
unit_guest_address = uint(XenosTextureAddressTiled2D(
int2_xe(unit_guest_origin.xy), pitch_aligned_shr5, bpb_log2));
}
// Unit-local host XY index of the host Nx1 sub-unit.
// Also see XeTextureScaledRightSubUnitOffsetInConsecutivePair for common