From 7684c343d6b772b8208072c0a9414d5fcefcc311 Mon Sep 17 00:00:00 2001 From: nmzik Date: Tue, 1 Sep 2026 04:08:41 +0400 Subject: [PATCH] guest_gpu: fix private AGC register regression --- .../command_processor/pm4Handlers.cpp | 14 ++++ src/graphics/guest_gpu/pm4.h | 5 +- src/libs/agc.cpp | 2 +- tests/ShaderRecompilerComputeTests.cpp | 66 ++++++++++++++++--- 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp index 557302d2e..d178f8363 100644 --- a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp +++ b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp @@ -3635,6 +3635,9 @@ void GraphicsInitJmpTablesShIndirect() { g_hw_sh_indirect_func[Pm4::SPI_SHADER_PACE_ID_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) { HwShIgnoreShaderRegister(cmd_offset, value); }; + g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_GS] = [](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); }; @@ -3644,6 +3647,12 @@ void GraphicsInitJmpTablesShIndirect() { g_hw_sh_indirect_func[Pm4::SPI_SHADER_USER_DATA_ADDR_HI_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) { HwShIgnoreShaderRegister(cmd_offset, value); }; + g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_CHKSUM_HS] = [](KYTY_HW_SH_INDIRECT_ARGS) { + HwShIgnoreShaderRegister(cmd_offset, value); + }; + g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_HS] = [](KYTY_HW_SH_INDIRECT_ARGS) { + HwShIgnoreShaderRegister(cmd_offset, value); + }; g_hw_sh_indirect_func[Pm4::SPI_GRAPHICS_SHADER_CONTROL_HS] = [](KYTY_HW_SH_INDIRECT_ARGS) { HwShIgnoreShaderRegister(cmd_offset, value); }; @@ -3818,6 +3827,11 @@ void GraphicsInitJmpTablesUcIndirect() { r.vertex_group_size = KYTY_PM4_GET(value, GE_CNTL, VERT_GRP_SIZE); cp.GetUcfg().SetGeControl(r); }; + g_hw_uc_indirect_func[Pm4::UC_PARAMETER_OVERSUBSCRIPTION] = [](KYTY_HW_UC_INDIRECT_ARGS) { + (void)cp; + (void)cmd_offset; + (void)value; + }; g_hw_uc_indirect_func[Pm4::GE_USER_VGPR_EN] = [](KYTY_HW_UC_INDIRECT_ARGS) { HW::GeUserVgprEn r; r.vgpr1 = KYTY_PM4_GET(value, GE_USER_VGPR_EN, EN_USER_VGPR1) != 0; diff --git a/src/graphics/guest_gpu/pm4.h b/src/graphics/guest_gpu/pm4.h index 7cce9ff63..8d0ff1db1 100644 --- a/src/graphics/guest_gpu/pm4.h +++ b/src/graphics/guest_gpu/pm4.h @@ -834,8 +834,9 @@ constexpr uint32_t SPI_SHADER_USER_ACCUM_ESGS_0 = 0xB2; constexpr uint32_t SPI_SHADER_USER_ACCUM_ESGS_3 = 0xB5; constexpr uint32_t SPI_SHADER_PGM_LO_ES = 0xC8; constexpr uint32_t SPI_SHADER_PGM_HI_ES = 0xC9; -// Retained only as an opaque AGC compiler-record tag; 0x100 is not a PS5 SH register. +// Private AGC registers used by shader binaries submitted through SET_SH_REG_INDIRECT. constexpr uint32_t SPI_SHADER_PGM_CHKSUM_HS = 0x100; +constexpr uint32_t SPI_SHADER_PGM_RSRC4_HS = 0x101; constexpr uint32_t SPI_SHADER_USER_DATA_ADDR_LO_HS = 0x102; constexpr uint32_t SPI_SHADER_USER_DATA_ADDR_HI_HS = 0x103; constexpr uint32_t SPI_GRAPHICS_SHADER_CONTROL_HS = 0x107; @@ -976,7 +977,7 @@ constexpr uint32_t GE_USER_VGPR1 = 0x25C; constexpr uint32_t GE_USER_VGPR2 = 0x25D; constexpr uint32_t GE_USER_VGPR3 = 0x25E; constexpr uint32_t GE_STEREO_CNTL = 0x25F; -constexpr uint32_t GE_PC_ALLOC = 0x260; +constexpr uint32_t UC_PARAMETER_OVERSUBSCRIPTION = 0x260; constexpr uint32_t GE_USER_VGPR_EN = 0x262; constexpr uint32_t GE_USER_VGPR_EN_EN_USER_VGPR1_SHIFT = 0; diff --git a/src/libs/agc.cpp b/src/libs/agc.cpp index 7b3192e18..af09e8210 100644 --- a/src/libs/agc.cpp +++ b/src/libs/agc.cpp @@ -1220,7 +1220,7 @@ int KYTY_SYSV_ABI AgcGetGsOversubscription(ShaderRegister* regs, const Shader* g constexpr uint32_t FULL_PC_OVERSUBSCRIPTION = 0x7ffu; constexpr uint32_t FULL_SH_OVERSUBSCRIPTION = 0x007f0000u; - regs[0] = {Pm4::GE_PC_ALLOC, 0u}; + regs[0] = {Pm4::UC_PARAMETER_OVERSUBSCRIPTION, 0u}; regs[1] = {Pm4::SPI_SHADER_PGM_RSRC4_GS, 0u}; if (budget == 0u) { diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 09b72c5d6..599d28cea 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -24556,10 +24556,10 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) { // Removed GCN shader resource/checksum/queue registers. Numeric offsets keep // this check independent of the deleted legacy names. - constexpr std::array legacy_shader_slots{ - 0x000u, 0x001u, 0x002u, 0x003u, 0x030u, 0x081u, 0x0b0u, 0x0bcu, - 0x100u, 0x101u, 0x130u, 0x14au, 0x14bu, 0x20eu, 0x20fu, 0x210u, - 0x211u, 0x216u, 0x217u, 0x219u, 0x21au, 0x27du, + constexpr std::array legacy_shader_slots{ + 0x000u, 0x001u, 0x002u, 0x003u, 0x030u, 0x0b0u, 0x0bcu, 0x130u, + 0x14au, 0x14bu, 0x20eu, 0x20fu, 0x210u, 0x211u, 0x216u, 0x217u, + 0x219u, 0x21au, 0x27du, }; for (const auto offset : legacy_shader_slots) { legacy_slots_are_unhandled &= g_hw_sh_func[offset] == nullptr && @@ -24570,12 +24570,6 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) { g_hw_sh_indirect_func[offset] == nullptr; } - constexpr std::array legacy_uconfig_slots{0x0260u}; - for (const auto offset : legacy_uconfig_slots) { - legacy_slots_are_unhandled &= g_hw_uc_func[offset] == nullptr && - g_hw_uc_indirect_func[offset] == nullptr; - } - std::array index_size_packet{ KYTY_PM4(3, Pm4::IT_SET_UCONFIG_REG_INDEX, Pm4::R_ZERO), 0x20000000u | Pm4::VGT_INDEX_TYPE, @@ -24601,6 +24595,54 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) { std::printf("[host] %-32s ok\n", "Pm4NativeTargetGeometry"); } +void CheckPm4PrivateAgcShaderRegisters(RenderContext &renderer) { + GraphicsInitJmpTables(); + CommandProcessor processor(renderer, 0); + std::array registers{ + Pm4::SPI_SHADER_PGM_RSRC4_GS, 0x0badc0deu, + Pm4::SPI_SHADER_PGM_CHKSUM_HS, 0x12345678u, + Pm4::SPI_SHADER_PGM_RSRC4_HS, 0x87654321u, + }; + 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, + }; + Pm4Execution execution; + const bool handlers_present = + g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_GS] != nullptr && + g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_CHKSUM_HS] != nullptr && + g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_HS] != nullptr; + Require("Pm4PrivateAgcShaderRegisters", "private shader register stream", + handlers_present && + processor.Process(execution, command) == Pm4ProcessResult::Complete, + "private AGC shader registers were rejected by SET_SH_REG_INDIRECT"); + std::printf("[host] %-32s ok\n", "Pm4PrivateAgcShaderRegisters"); +} + +void CheckPm4PrivateAgcUconfigRegisters(RenderContext &renderer) { + GraphicsInitJmpTables(); + CommandProcessor processor(renderer, 0); + std::array registers{ + Pm4::UC_PARAMETER_OVERSUBSCRIPTION, 0x12345678u, + }; + const auto address = reinterpret_cast(registers.data()); + std::array command{ + KYTY_PM4(5, Pm4::IT_SET_UCONFIG_REG_INDIRECT, Pm4::R_ZERO), + static_cast(address), static_cast(address >> 32u), + 0x80000000u, 1u, + }; + Pm4Execution execution; + const bool handler_present = + g_hw_uc_indirect_func[Pm4::UC_PARAMETER_OVERSUBSCRIPTION] != nullptr; + Require("Pm4PrivateAgcUconfigRegisters", "private UCONFIG register stream", + handler_present && + processor.Process(execution, command) == Pm4ProcessResult::Complete, + "private AGC UCONFIG register was rejected by SET_UCONFIG_REG_INDIRECT"); + std::printf("[host] %-32s ok\n", "Pm4PrivateAgcUconfigRegisters"); +} + void CheckPm4DirectShaderRegisterFallback(RenderContext &renderer) { GraphicsInitJmpTables(); CommandProcessor processor(renderer, 0); @@ -25361,6 +25403,8 @@ int main(int argc, char **argv) { if (argc == 2 && std::strcmp(argv[1], "--context-state-only") == 0) { VulkanHarness vulkan; CheckPm4NativeTargetGeometryRegisters(vulkan.RuntimeRenderer()); + CheckPm4PrivateAgcShaderRegisters(vulkan.RuntimeRenderer()); + CheckPm4PrivateAgcUconfigRegisters(vulkan.RuntimeRenderer()); CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer()); CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer()); CheckPm4ContextStateOperations(vulkan.RuntimeRenderer()); @@ -25541,6 +25585,8 @@ int main(int argc, char **argv) { CheckPm4SyntheticOcclusionCounterDump(vulkan.RuntimeRenderer()); CheckPm4StencilInfoValueLane(vulkan.RuntimeRenderer()); CheckPm4NativeTargetGeometryRegisters(vulkan.RuntimeRenderer()); + CheckPm4PrivateAgcShaderRegisters(vulkan.RuntimeRenderer()); + CheckPm4PrivateAgcUconfigRegisters(vulkan.RuntimeRenderer()); CheckPm4DirectShaderRegisterFallback(vulkan.RuntimeRenderer()); CheckPm4GuardBandRegisterRanges(vulkan.RuntimeRenderer()); CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer());