fix(agc): retain cross-block R_X coordinate XORs

This commit is contained in:
MarcZX100 2026-10-11 11:23:47 +00:00
parent 0f863c1022
commit a6cb65e481
3 changed files with 18 additions and 1 deletions

View File

@ -9,6 +9,8 @@
namespace AgcDriver::Graphics {
struct TextureSwizzleEquation;
enum class ColorTileMode : std::uint32_t {
Linear = 0,
Standard4KB = 5,
@ -57,6 +59,7 @@ private:
// The XOR swizzle is linear over GF(2), so a block offset is xOffsets[x] ^ yOffsets[y].
const std::uint32_t* xOffsets = nullptr;
const std::uint32_t* yOffsets = nullptr;
const TextureSwizzleEquation* equation = nullptr;
};
class CmaskLayout {

View File

@ -123,6 +123,7 @@ ColorTargetLayout::ColorTargetLayout(std::uint32_t width, std::uint32_t height,
const auto& tables = equationTables(mode, bytesPerElement, blockWidth, blockHeight);
xOffsets = tables.x.data();
yOffsets = tables.y.data();
if (mode == ColorTileMode::RenderTarget) equation = FindTextureSwizzleEquation(static_cast<std::uint32_t>(mode), bytesPerElement);
break;
}
case ColorTileMode::Standard4KB:
@ -149,7 +150,16 @@ ColorTargetLayout::ColorTargetLayout(std::uint32_t width, std::uint32_t height,
std::size_t ColorTargetLayout::offset(std::uint32_t x, std::uint32_t y) const {
if (mode == ColorTileMode::Linear) return (static_cast<std::size_t>(y) * pitch + x) * elementBytes;
const auto block = static_cast<std::size_t>(y / blockHeight) * (pitch / blockWidth) + x / blockWidth;
return block * Alignment() + (xOffsets[x % blockWidth] ^ yOffsets[y % blockHeight] ^ pipeBankXor);
auto inBlock = xOffsets[x % blockWidth] ^ yOffsets[y % blockHeight];
if (equation != nullptr) {
const auto highX = (x & ~(blockWidth - 1u)) & 0xfffu;
const auto highY = ((y & ~(blockHeight - 1u)) << 12u) & 0xfff000u;
for (std::uint32_t bit = 0; bit < 16u; ++bit) {
const auto coordinates = (highX & equation->bits[bit]) ^ (highY & equation->bits[bit]);
inBlock |= (parity(coordinates) << bit);
}
}
return block * Alignment() + (inBlock ^ pipeBankXor);
}
std::size_t ColorTargetLayout::Offset(std::uint32_t x, std::uint32_t y) const {

View File

@ -51,6 +51,10 @@ void RunColorTargetLayoutTests() {
Require(layout.Offset(128, 0) == 65536 && layout.Offset(0, 128) == 3 * 65536, "block raster order is incorrect");
Require(layout.Offset(16, 0) == 0x2200 && layout.Offset(0, 8) == 0x1100, "render-target XOR addressing is incorrect");
Require(layout.Offset(256, 0) == 2 * 65536, "third block address is incorrect");
const ColorTargetLayout r64(33, 65, ColorTileMode::RenderTarget, 8);
const ColorTargetLayout r128(129, 67, ColorTileMode::RenderTarget, 16);
Require(r64.Offset(0, 64) == 67584, "64 bpp SW_64KB_R_X dropped a cross-block y-coordinate XOR bit");
Require(r128.Offset(64, 0) == 66560, "128 bpp SW_64KB_R_X dropped a cross-block x-coordinate XOR bit");
Require(DecodeColorTileMode(0x4dc14000) == ColorTileMode::Standard4KB, "4 KiB standard color descriptor was rejected");
const ColorTargetLayout standard(256, 256, ColorTileMode::Standard4KB);
Require(standard.Bytes() == ComputeSurfaceSize(ComputeElementMipLayout(TextureTileMode::kStandard4KB, 4, 256, 256, 1), 1) && standard.Alignment() == 4096, "4 KiB standard color layout differs from the texture layout");