From 717c54e0850ff35e59e42c5c6fc4c7e55e7656d3 Mon Sep 17 00:00:00 2001 From: nmzik Date: Tue, 13 Oct 2026 04:04:19 +0200 Subject: [PATCH] gpu: match complete NOP marker tags and ignore opaque payloads Co-authored-by: Ali Almohaya --- .../command_processor/pm4Handlers.cpp | 19 ++++++++----------- tests/ShaderRecompilerComputeTests.cpp | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp index 5586ecec..6aed00ea 100644 --- a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp +++ b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp @@ -2142,27 +2142,23 @@ KYTY_CP_OP_PARSER(CpOpIndirectUcRegs) { KYTY_CP_OP_PARSER(CpOpMarker) { KYTY_PROFILER_FUNCTION(); - // EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0001000); - - uint32_t id = buffer[0] & 0xfffu; uint32_t len_dw = ((cmd_id >> 16u) & 0x3fffu); - switch (id) { - case 0x0: break; - case 0x4: cp.SetUserDataMarker(HW::UserSgprType::Vsharp); break; - case 0xd: cp.SetUserDataMarker(HW::UserSgprType::Region); break; - case 0x777: { + switch (buffer[0]) { + case 0x68750004: cp.SetUserDataMarker(HW::UserSgprType::Vsharp); break; + case 0x6875000d: cp.SetUserDataMarker(HW::UserSgprType::Region); break; + case 0x68750777: { cp.Flip(); break; } - case 0x778: { + case 0x68750778: { auto* addr = reinterpret_cast(buffer[1] | (static_cast(buffer[2]) << 32u)); uint32_t value = buffer[3]; cp.Flip(addr, value); break; } - case 0x781: { + case 0x68750781: { auto* addr = reinterpret_cast(buffer[1] | (static_cast(buffer[2]) << 32u)); uint32_t value = buffer[3]; @@ -2171,7 +2167,8 @@ KYTY_CP_OP_PARSER(CpOpMarker) { cp.FlipWithInterrupt(eop_event_type, cache_action, addr, value); break; } - default: EXIT("unknown marker at %05" PRIx32 ": 0x%" PRIx32 "\n", num_dw - dw, id); + // NOP payloads are caller-owned data; only complete known marker tags execute. + default: break; } return len_dw + 1; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 28adbc19..df6b9ff2 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -44129,6 +44129,25 @@ void CheckPm4IndirectControlFlow(RenderContext &renderer) { Gen5::AgcCbNop(reinterpret_cast(&payload_dcb), 3) == payload.data() && payload == std::array{0xc0011000u, 0x12345678u, 0x9abcdef0u}, "NOP emitter overwrote the caller's reserved payload"); + for (const uint32_t value : {0x68750820u, 0x68751777u, 0x68751004u}) { + std::array commands{KYTY_PM4(3, Pm4::IT_NOP, Pm4::R_ZERO), value, 0x12345678u}; + std::copy(completion.begin(), completion.end(), commands.begin() + 3); + processor.SetUserDataMarker(HW::UserSgprType::Unknown); + selected = 0; + Pm4Execution execution; + Require(name, "opaque NOP payload", + processor.Process(execution, commands) == Pm4ProcessResult::Complete && selected == 7 && + processor.GetUserDataMarker() == HW::UserSgprType::Unknown && commands[1] == value, + "a NOP payload prefix executed a marker or blocked the following packet"); + } + const std::array vsharp_marker{ + KYTY_PM4(2, Pm4::IT_NOP, Pm4::R_ZERO), 0x68750004u}; + Pm4Execution marker_execution; + Require(name, "exact user-data marker", + processor.Process(marker_execution, vsharp_marker) == Pm4ProcessResult::Complete && + processor.GetUserDataMarker() == HW::UserSgprType::Vsharp, + "exact marker dispatch lost the existing user-data annotation"); + processor.SetUserDataMarker(HW::UserSgprType::Unknown); alignas(8) uint64_t released = 0; std::array disabled_commands{}; const auto disabled_write = write(&returned, 99);