From ce8bee69809daab196087ed5b4c5f4d89e22b3b6 Mon Sep 17 00:00:00 2001 From: AlxcBTW <187763517+AlxcBTW@users.noreply.github.com> Date: Sat, 10 Oct 2026 04:02:48 +0200 Subject: [PATCH] fix(agc): render into one slice of a 2D array color target DecodeColorTileMode rejected 2D color targets with a nonzero MIP0_DEPTH, so an array target could only be rendered into through a view of a surface that declares one slice. radeonsi sets CB_COLOR_ATTRIB3.MIP0_DEPTH to the last layer of an array target (si_state.c, ac_descriptors.c), and Mesa-built homebrew emits such targets. The view's slice already moves the target by one slice size; it is now also checked against MIP0_DEPTH. --- .../prx/libSceAgcDriver/Graphics/src/ColorTargetLayout.cpp | 2 +- core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp | 2 ++ core/libs/prx/libSceAgcDriver/tests/ColorTargetLayout.cpp | 2 +- core/libs/prx/libSceAgcDriver/tests/Graphics.cpp | 5 +++++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/ColorTargetLayout.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/ColorTargetLayout.cpp index e9c5fe3bc3..7c27f92c6e 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/ColorTargetLayout.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/ColorTargetLayout.cpp @@ -43,7 +43,7 @@ std::uint32_t standard64Extra(std::uint32_t x, std::uint32_t y, std::uint32_t el ColorTileMode DecodeColorTileMode(std::uint32_t attrib3) { const auto resourceType = (attrib3 >> 24u) & 3u; - require((attrib3 & 0x80002000u) == 0 && ((resourceType <= 1 && (attrib3 & 0x1fffu) == 0) || resourceType == 2) && ((attrib3 >> 27u) & 7u) == 1, "AGC graphics: unsupported color depth, dimension, resource level or metadata mode"); + require((attrib3 & 0x80002000u) == 0 && ((resourceType == 0 && (attrib3 & 0x1fffu) == 0) || resourceType == 1 || resourceType == 2) && ((attrib3 >> 27u) & 7u) == 1, "AGC graphics: unsupported color depth, dimension, resource level or metadata mode"); const auto mode = (attrib3 >> 14u) & 0x1fu; const auto fmaskMode = (attrib3 >> 19u) & 0x1fu; require(fmaskMode == 0 || fmaskMode == 0x18, "AGC graphics: unsupported color FMASK swizzle mode"); diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp index 843d9de329..6f1f3e14d6 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp @@ -815,6 +815,8 @@ ColorTarget DecodeColorBuffer(const Registers& cx, std::uint32_t slot) { Require(maxMip == 0 && (info & 0x10000000u) == 0, "mipmapped or DCC 3D color targets are unsupported"); Require(slice < color.depth, "the color view slice is beyond the 3D surface"); color.depthSlice = slice; + } else if ((attrib3 & 0x1fffu) != 0) { + Require(slice <= (attrib3 & 0x1fffu), "the color view slice is beyond the array surface"); } color.extent = {((attrib2 >> 14u) & 0x3fffu) + 1u, (attrib2 & 0x3fffu) + 1u}; color.elementBytes = decoded.elementBytes; diff --git a/core/libs/prx/libSceAgcDriver/tests/ColorTargetLayout.cpp b/core/libs/prx/libSceAgcDriver/tests/ColorTargetLayout.cpp index 5d02bebda1..636bc574fd 100644 --- a/core/libs/prx/libSceAgcDriver/tests/ColorTargetLayout.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/ColorTargetLayout.cpp @@ -25,7 +25,7 @@ void reject(TAction action) { void RunColorTargetLayoutTests() { Require(DecodeColorTileMode(0x4dc6c000) == ColorTileMode::RenderTarget, "logged color descriptor was rejected"); Require(DecodeColorTileMode(0x09000000) == ColorTileMode::Linear, "linear descriptor changed"); - reject([] { DecodeColorTileMode(0x4dc6c001); }); + Require(DecodeColorTileMode(0x4dc6c001) == ColorTileMode::RenderTarget, "2D array color descriptor with MIP0_DEPTH 1 was rejected"); reject([] { DecodeColorTileMode(0x4dc6e000); }); reject([] { DecodeColorTileMode(0xcdc6c000); }); reject([] { DecodeColorTileMode(0x09004000); }); diff --git a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp index c908a3a41d..ad7975db7a 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp @@ -916,6 +916,11 @@ void DepthStencilTests() { queue.context[0x31b] = 1u | (1u << 13u); const auto slice = AgcDriver::Graphics::DecodeState(queue); Require(slice.color.address == sliced + 1024u && slice.color.bytes == 1024u, "a color view of one slice did not move the target by one slice"); + queue.context[0x3b8] = 0x09000001; + const auto arraySlice = AgcDriver::Graphics::DecodeState(queue); + Require(arraySlice.color.address == sliced + 1024u && arraySlice.color.bytes == 1024u && arraySlice.color.depth == 1u, "a color view of one slice of a 2D array target did not move the target by one slice"); + queue.context[0x31b] = 2u | (2u << 13u); + expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "beyond the array surface"); queue.context[0x3b8] = 0x0a000003; queue.context[0x31b] = 2u | (2u << 13u); const auto volume = AgcDriver::Graphics::DecodeState(queue);