From 7e89b97daf52a0010c5a71b640fee537cf73b834 Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 14 Sep 2026 11:17:05 +0400 Subject: [PATCH] Handle front shader allocation state --- .../command_processor/pm4Handlers.cpp | 5 ++++ tests/ShaderRecompilerComputeTests.cpp | 28 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp index 9aebbb752..fb0c2d1b4 100644 --- a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp +++ b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp @@ -3635,6 +3635,11 @@ void GraphicsInitJmpTablesShIndirect() { g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) { HwShIgnoreShaderRegister(cmd_offset, value); }; + // Toolkit state restoration emits the compiler's GS-front allocation + // metadata here. Native GS resource registers already carry that allocation. + g_hw_sh_indirect_func[0x0ca] = [](KYTY_HW_SH_INDIRECT_ARGS) { + HwShIgnoreShaderRegister(cmd_offset, value); + }; g_hw_sh_indirect_func[Pm4::SPI_GRAPHICS_SHADER_CONTROL_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) { HwShIgnoreShaderRegister(cmd_offset, value); }; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 2c4aadcb7..eb6fba318 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -28788,7 +28788,9 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) { legacy_slots_are_unhandled &= g_hw_sh_func[offset] == nullptr && g_hw_sh_indirect_func[offset] == nullptr; } - for (uint32_t offset = 0x0cau; offset <= 0x0ebu; offset++) { + // Restoring shader state after Toolkit rendering still emits the compiler's + // GS-front allocation metadata at 0xca. + for (uint32_t offset = 0x0cbu; offset <= 0x0ebu; offset++) { legacy_slots_are_unhandled &= g_hw_sh_func[offset] == nullptr && g_hw_sh_indirect_func[offset] == nullptr; } @@ -28821,16 +28823,25 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) { void CheckPm4PrivateAgcShaderRegisters(RenderContext &renderer) { GraphicsInitJmpTables(); CommandProcessor processor(renderer, 0); - std::array registers{ + std::array registers{ Pm4::SPI_SHADER_PGM_RSRC4_GS, 0x0badc0deu, Pm4::SPI_SHADER_PGM_CHKSUM_HS, 0x12345678u, Pm4::SPI_SHADER_PGM_RSRC4_HS, 0x87654321u, + Pm4::SPI_SHADER_PGM_LO_ES, 0x050025e5u, + Pm4::SPI_SHADER_PGM_HI_ES, 0u, + Pm4::SPI_SHADER_PGM_RSRC1_GS, 0x60000002u, + Pm4::SPI_SHADER_PGM_RSRC2_GS, 0x00030008u, + 0x000000cau, 0x03000002u, + Pm4::SPI_SHADER_PGM_LO_PS, 0x05000104u, + Pm4::SPI_SHADER_PGM_HI_PS, 0u, + Pm4::SPI_SHADER_PGM_RSRC1_PS, 0x022c018du, + Pm4::SPI_SHADER_PGM_RSRC2_PS, 0x0000003cu, }; const auto address = reinterpret_cast(registers.data()); std::array command{ KYTY_PM4(5, Pm4::IT_SET_SH_REG_INDIRECT, Pm4::R_ZERO), static_cast(address), static_cast(address >> 32u), - 0x80000000u, 3u, + 0x80000000u, static_cast(registers.size() / 2u), }; Pm4Execution execution; const bool handlers_present = @@ -28841,6 +28852,17 @@ void CheckPm4PrivateAgcShaderRegisters(RenderContext &renderer) { handlers_present && processor.Process(execution, command) == Pm4ProcessResult::Complete, "private AGC shader registers were rejected by SET_SH_REG_INDIRECT"); + const auto &vs = processor.GetShCtx().GetVs(); + const auto &ps = processor.GetShCtx().GetPs().ps_regs; + Require("Pm4PrivateAgcShaderRegisters", "native state around front metadata", + vs.es_regs.data_addr == 0x50025e500ull && + vs.gs_regs.rsrc1.vgprs == 2u && + vs.gs_regs.rsrc1.gs_vgpr_component_count == 3u && + vs.gs_regs.rsrc2.es_vgpr_component_count == 3u && + vs.gs_regs.rsrc2.user_sgpr == 4u && + ps.data_addr == 0x500010400ull && ps.rsrc1.vgprs == 13u && + ps.rsrc2.user_sgpr == 30u, + "GS-front metadata changed native GS state or prevented later PS writes"); std::printf("[host] %-32s ok\n", "Pm4PrivateAgcShaderRegisters"); }