From 6aaa53329614ee709b1b6fa5122598b252600d2e Mon Sep 17 00:00:00 2001 From: nmzik Date: Fri, 23 Oct 2026 22:22:39 +0200 Subject: [PATCH] gpu: queue GDS release interrupts behind earlier interrupts --- src/graphics/guest_gpu/graphicsRun.cpp | 6 +---- tests/ShaderRecompilerComputeTests.cpp | 32 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/graphics/guest_gpu/graphicsRun.cpp b/src/graphics/guest_gpu/graphicsRun.cpp index 381803349..3837d504b 100644 --- a/src/graphics/guest_gpu/graphicsRun.cpp +++ b/src/graphics/guest_gpu/graphicsRun.cpp @@ -979,11 +979,7 @@ void CommandProcessor::ReleaseMem(uint32_t data_sel, uint32_t interrupt_selector const auto gds = static_cast(data); Sync::ReadGds(*m_renderer.GetBufferCache().GetGdsBuffer(), static_cast(address), gds & 0xffffu, gds >> 16u); - if (interrupt) { - // The GPU is idle, so the interrupt needs no fence. - m_renderer.TriggerInterrupt(m_interrupt_event_id, interrupt_context_id); - } - return; + break; } default: EXIT("unknown release_mem data selector: %" PRIu32 "\n", data_sel); } diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index be95c3044..b3ca80c4b 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -3362,6 +3362,38 @@ public: interrupt_event.ident == 0x20 && interrupt_event.data == 0x789u, "kSendIntCtx lost its interrupt or context id"); + // A GDS release interrupt follows the interrupts queued before it, so + // neither arrives while the priority thread is parked. + std::binary_semaphore priority_parked{0}; + gpu.SendCommandSync([&] { + auto &scheduler = context.GetCommandScheduler(); + scheduler.Finish(); + scheduler.DeferPriorityOperation([&] { priority_parked.acquire(); }); + }); + uint32_t ordered_gds_label = 0; + const auto ordered_first = make_interrupt_packet(0, 2, nullptr, 0, 0xa1u); + const auto ordered_gds = + make_interrupt_packet(5, 2, &ordered_gds_label, 1u << 16u, 0xa2u); + std::array ordered_commands{}; + std::copy(ordered_first.begin(), ordered_first.end(), ordered_commands.begin()); + std::copy(ordered_gds.begin(), ordered_gds.end(), ordered_commands.begin() + 8); + gpu.SubmitCompute(0x20, ordered_commands); + gpu.WaitForIdle(); + interrupt_count = 0; + const auto parked_wait = wait_for_interrupt(interrupt_event, interrupt_count); + priority_parked.release(); + finish_gpu(); + LibKernel::EventQueue::KernelEvent second_event{}; + int second_count = 0; + interrupt_count = 0; + const auto first_wait = wait_for_interrupt(interrupt_event, interrupt_count); + const auto second_wait = wait_for_interrupt(second_event, second_count); + Require("GpuCommandLane", "GDS interrupt order", + parked_wait == LibKernel::KERNEL_ERROR_ETIMEDOUT && first_wait == 0 && + interrupt_count == 1 && interrupt_event.data == 0xa1u && + second_wait == 0 && second_count == 1 && second_event.data == 0xa2u, + "a GDS release interrupt overtook an earlier interrupt"); + interrupt_count = 0; const auto extra_interrupt_wait = wait_for_interrupt(interrupt_event, interrupt_count);