diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp index 0e7e3e92f..d0ca4e553 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp @@ -182,6 +182,10 @@ bool depthPassThrough(std::uint32_t depthControl) { return (stencil || depth) && passThroughDepth && passThroughStencil; } +std::uint32_t effectiveDepthControl(std::uint32_t depthControl) { + return (depthControl & 3u) == 0 ? depthControl & ~4u : depthControl; +} + bool colorControlSupported(std::uint32_t colorControl, bool hasColorTarget) { return colorControl == 0xcc0010u || (!hasColorTarget && (colorControl & ~0x70u) == 0xcc0000u); } @@ -416,7 +420,7 @@ State DecodeState(const QueueState& queue) { std::fprintf(stderr, "[gpu] depth/stencil tests are ignored (APS5_IGNORE_DEPTH_TEST; DB_DEPTH_CONTROL=0x%08x)\n", depthControl); } } else { - zero(cx, 0x200, DepthControlMask, "depth, stencil or conditional color writes"); + if ((effectiveDepthControl(depthControl) & DepthControlMask) != 0) zero(cx, 0x200, DepthControlMask, "depth, stencil or conditional color writes"); } Require((depthControl & 0xc0000008u) == 0, "depth bounds or depth-conditional color writes are unsupported"); } @@ -643,7 +647,7 @@ std::string DrawRejection(const QueueState& queue, bool indexed) { if (auto reason = nonzero(cx, 0x207, ~LayerExports, "clip distances, layer, viewport or auxiliary vertex exports"); !reason.empty()) return reason; if (value(cx, 0x200, word)) { const bool surface = (word & 3u) != 0 && depthSurfaceBound(cx); - if (!surface && !depthPassThrough(word) && !IgnoreDepthTest() && (word & DepthControlMask) != 0) return zeroMessage(0x200, word, "depth, stencil or conditional color writes"); + if (!surface && !depthPassThrough(word) && !IgnoreDepthTest() && (effectiveDepthControl(word) & DepthControlMask) != 0) return zeroMessage(0x200, word, "depth, stencil or conditional color writes"); if (auto reason = require((word & 0xc0000008u) == 0, "depth bounds or depth-conditional color writes are unsupported"); !reason.empty()) return reason; } if (auto reason = nonzero(cx, 0x203, ShaderControlMask, "depth export, shader coverage or ordered fragment execution"); !reason.empty()) return reason; diff --git a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp index 682136b6e..4e5ac73df 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp @@ -127,6 +127,15 @@ void stateTests() { queue.context[0x200] = 2; expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "depth"); queue = makeState(); + queue.context[0x200] = 0x007007b4; + queue.context[0x1b3] = 2; + queue.context[0x1b4] = 2; + (void)AgcDriver::Graphics::DecodeState(queue); + Require(AgcDriver::Graphics::DrawRejection(queue, false).empty(), "a depth write without the depth test was rejected"); + queue = makeState(); + queue.context[0x200] = 0x007007b6; + expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "depth"); + queue = makeState(); queue.context[0x10f] = 0x7fc00000; expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "non-finite"); // The register facade: every register the decoders read is in DrawKeyRegisters (a wrong hit of