diff --git a/README.md b/README.md index 037d4c25a6..d0db327a4a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ Execution reaches `_start`, [stack unwinding](core/libs/prx/libc/src/exception/U The [shader recompiler](core/shader/recompiler/Recompiler.cpp) successfully produces validated via [Spirv-Tools](3rdparty/SPIRV-Tools) SPIR-V. The application reaches the render loop and **successfully presents its first frame** (logo). -Current exception: `AGC graphics: unsupported primitive type 17`. + +Current exception: `AGC graphics: unsupported SPIR-V memory model` on 6 frame. ## Build diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp index fcd24811cf..5934b47bc3 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp @@ -159,7 +159,7 @@ State DecodeState(const QueueState& queue) { zero(cx, 0x292, ~2u, "scan conversion mode"); zero(cx, 0x293, ~0x06003fffu, "sample iteration, primitive discard or out-of-order rasterization"); zero(cx, 0x80, ~0u, "window offset"); - zero(cx, 0x8d, ~0u, "hardware screen offset"); + zero(cx, 0x8d, ~0x01ff01ffu, "reserved PA_SU_HARDWARE_SCREEN_OFFSET bits"); Require(read(cx, 0x83) == 0xffffu, "clip rectangles are unsupported"); Require((read(cx, 0x8c) & 0xfu) == 0xau, "nonstandard triangle edge rules are unsupported"); Require(read(cx, 0x2f9) == 0x2du, "nonstandard pixel center or vertex quantization is unsupported"); diff --git a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp index 9ff8b0dd70..295cc457c7 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp @@ -116,6 +116,27 @@ void stateTests() { expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "non-finite"); } +void hardwareScreenOffsetTests() { + auto queue = makeState(); + queue.context[0x90] = 0x80010003; + queue.context[0x91] = 0x30020; + const auto reference = AgcDriver::Graphics::DecodeState(queue); + for (const auto offset : {0u, 1u, 0x10000u, 0x0020003cu, 0x01ff0000u, 0x000001ffu, 0x01ff01ffu}) { + queue.context[0x8d] = offset; + const auto state = AgcDriver::Graphics::DecodeState(queue); + Require(state.viewport.x == reference.viewport.x && state.viewport.y == reference.viewport.y && state.viewport.width == reference.viewport.width && state.viewport.height == reference.viewport.height && state.viewport.minDepth == reference.viewport.minDepth && state.viewport.maxDepth == reference.viewport.maxDepth, "hardware guard-band offset changed the viewport"); + Require(state.scissor.offset.x == reference.scissor.offset.x && state.scissor.offset.y == reference.scissor.offset.y && state.scissor.extent.width == reference.scissor.extent.width && state.scissor.extent.height == reference.scissor.extent.height, "hardware guard-band offset changed the scissor"); + Require(state.renderExtent.width == reference.renderExtent.width && state.renderExtent.height == reference.renderExtent.height, "hardware guard-band offset changed the framebuffer extent"); + } + for (std::uint32_t bit = 0; bit < 32; ++bit) { + if (bit < 9 || (bit >= 16 && bit < 25)) continue; + queue.context[0x8d] = 1u << bit; + expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "reserved PA_SU_HARDWARE_SCREEN_OFFSET bits"); + } + queue.context.erase(0x8d); + expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "missing register"); +} + void ShaderStageTests() { auto queue = makeState(); for (const auto routing : {0x2000u, 0x2010u, 0x02002000u, 0x02002010u}) { @@ -1121,6 +1142,7 @@ int main() { expectFailure([&] { AgcDriver::Graphics::Draw(context, state, draw, {}); }, "draw modifiers"); } stateTests(); + hardwareScreenOffsetTests(); DepthClipTests(); DisabledColorTests(); ShaderStageTests();