From 0a04dc4964abc5fdb00b0c8923011bb9f74aa560 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Thu, 6 Aug 2026 11:38:53 +1000 Subject: [PATCH] [idd] d3d12: signal reusable command slots Signal a per-slot event after callbacks finish and the command slot has returned to the free state. This removes the one millisecond polling delay when candidate state becomes visible just before its slot is reusable. --- idd/LGIdd/CD3D12CommandQueue.cpp | 28 ++++++++++++++++++++++++++-- idd/LGIdd/CD3D12CommandQueue.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/idd/LGIdd/CD3D12CommandQueue.cpp b/idd/LGIdd/CD3D12CommandQueue.cpp index 556b7e99..5d48f362 100644 --- a/idd/LGIdd/CD3D12CommandQueue.cpp +++ b/idd/LGIdd/CD3D12CommandQueue.cpp @@ -99,6 +99,14 @@ bool CD3D12CommandSlot::Init(ID3D12Device3 * device, return false; } + m_availableEvent.Attach(CreateEvent(NULL, FALSE, FALSE, NULL)); + if (!m_availableEvent.Get()) + { + DEBUG_ERROR_HR(GetLastError(), + "Failed to create the availability event (%ls)", name); + return false; + } + if (!RegisterWaitForSingleObject( &m_waitHandle, m_event.Get(), @@ -130,6 +138,7 @@ void CD3D12CommandSlot::DeInit() } m_event.Close(); + m_availableEvent.Close(); m_cmdList.Reset(); m_gfxList.Reset(); m_allocator.Reset(); @@ -224,6 +233,7 @@ void CD3D12CommandSlot::Cancel() m_completionParams[1] = nullptr; m_submitted.store(false, std::memory_order_release); m_state.store(STATE_FREE, std::memory_order_release); + SetEvent(m_availableEvent.Get()); } bool CD3D12CommandSlot::Execute() @@ -250,7 +260,10 @@ bool CD3D12CommandSlot::Execute() return true; if (!m_submitted.load(std::memory_order_acquire)) + { m_state.store(STATE_FREE, std::memory_order_release); + SetEvent(m_availableEvent.Get()); + } return false; } @@ -343,6 +356,7 @@ void CD3D12CommandSlot::OnCompletion(bool timeout) m_completionParams[1] = nullptr; m_submitted.store(false, std::memory_order_release); m_state.store(STATE_FREE, std::memory_order_release); + SetEvent(m_availableEvent.Get()); } bool CD3D12CommandQueue::InitTiming(ID3D12Device3 * device, UINT slotCount) @@ -493,13 +507,23 @@ CD3D12CommandSlot * CD3D12CommandQueue::Acquire(UINT slotIndex) if (slotIndex >= m_slotCount) return nullptr; - for (int i = 0; i < 100; ++i) + const ULONGLONG deadline = GetTickCount64() + 100; + for (;;) { if (m_slots[slotIndex].Acquire()) return &m_slots[slotIndex]; if (m_failed.load(std::memory_order_acquire)) break; - Sleep(1); + + const ULONGLONG now = GetTickCount64(); + if (now >= deadline) + break; + + const DWORD result = + WaitForSingleObject(m_slots[slotIndex].m_availableEvent.Get(), + static_cast(deadline - now)); + if (result != WAIT_OBJECT_0) + break; } DEBUG_ERROR("Failed to acquire CommandSlot(%ls:%u)", m_name, slotIndex); diff --git a/idd/LGIdd/CD3D12CommandQueue.h b/idd/LGIdd/CD3D12CommandQueue.h index 41286f08..1c3534aa 100644 --- a/idd/LGIdd/CD3D12CommandQueue.h +++ b/idd/LGIdd/CD3D12CommandQueue.h @@ -65,6 +65,7 @@ class CD3D12CommandSlot std::atomic m_state = STATE_FREE; std::atomic m_submitted = false; HandleT m_event; + HandleT m_availableEvent; HANDLE m_waitHandle = INVALID_HANDLE_VALUE; bool m_needsReset = false; UINT64 m_fenceTarget = 0;