diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp index 8a07f6bc8..5dc730e10 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp @@ -893,11 +893,10 @@ State DecodeState(const QueueState& queue, bool vertexWorkgroup) { for (std::uint32_t component = 0; component < 4; ++component) { if (((exportedMask >> ((mapping >> (2u * component)) & 3u)) & 1u) != 0) state.colorWriteMask |= 1u << component; } - state.blendEnable = (blend >> 30u) & 1u; + state.blendEnable = ((blend >> 30u) & 1u) != 0 && (read(cx, 0x31c + slot * 0xfu) & 0x10000u) == 0; if (state.blendEnable && (mapping == 0x1bu || mapping == 0x93u)) throw std::runtime_error("AGC graphics: blending into a color target with a reversed component order is not implemented"); Require(!state.blendEnable || !color.uintExport, "blending into an unsigned integer target is unsupported"); if (state.blendEnable) { - Require((read(cx, 0x31c + slot * 0xfu) & 0x10000u) == 0, "blend bypass conflicts with enabled blending"); state.srcColorBlendFactor = blendFactor(blend & 0x1fu); state.dstColorBlendFactor = blendFactor((blend >> 8u) & 0x1fu); state.colorBlendOp = blendOp((blend >> 5u) & 7u); diff --git a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp index 4589213eb..b8a5f04e4 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp @@ -1030,6 +1030,16 @@ void PixelInputLayoutTests() { Require(!readsBuiltin(read, spv::BuiltInFragCoord) && !readsBuiltin(read, spv::BuiltInBaryCoordKHR), "an ADDR-only centroid pair was loaded"); } +void BlendBypassTests() { + auto queue = makeState(); + for (std::uint32_t constant = 0x105; constant < 0x109; ++constant) queue.context[constant] = 0; + queue.context[0x1e0] = (1u << 30u) | 4u | (5u << 8u); + Require(AgcDriver::Graphics::DecodeState(queue).blends.at(0).blendEnable, "enabled blending was not decoded"); + queue.context[0x31c] |= 0x10000u; + const auto bypassed = AgcDriver::Graphics::DecodeState(queue); + Require(!bypassed.blends.at(0).blendEnable && bypassed.blends.at(0).colorWriteMask != 0, "a target with BLEND_BYPASS still blends"); +} + void OpaqueDestinationAlphaTests() { auto queue = makeState(); for (std::uint32_t constant = 0x105; constant < 0x109; ++constant) queue.context[constant] = 0; @@ -5710,6 +5720,7 @@ int main(int argc, char** argv) { DisabledColorTests(); OpaqueDestinationAlphaTests(); Color1555TargetTests(); + BlendBypassTests(); CompactedExportTests(); ReversedComponentOrderTests(); ShadersWriteMemoryTests();