From a4b81797949ffee1da38f1e2a9da725099e7b970 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 12 Feb 2026 17:56:39 +0000 Subject: [PATCH] Fix query tracking to be per-cmdbuf on replay. Closes #3797 --- renderdoc/driver/d3d12/d3d12_command_list.h | 14 ------------ .../driver/d3d12/d3d12_command_list_wrap.cpp | 14 +++++++----- renderdoc/driver/d3d12/d3d12_commands.h | 14 ++++++++++++ util/test/demos/d3d12/d3d12_predication.cpp | 22 ++++++++++++++++++- util/test/tests/D3D12/D3D12_Predication.py | 8 +++++++ 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_command_list.h b/renderdoc/driver/d3d12/d3d12_command_list.h index ad1ab743b..6c12583b9 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list.h +++ b/renderdoc/driver/d3d12/d3d12_command_list.h @@ -185,20 +185,6 @@ private: // the list is reset, and each time the list is submitted the queue takes an additional reference rdcarray m_RayDispatches; - struct OutstandingQuery - { - ID3D12QueryHeap *heap; - D3D12_QUERY_TYPE Type; - UINT Index; - - bool operator==(const OutstandingQuery &q) const - { - return heap == q.heap && Type == q.Type && Index == q.Index; - } - }; - - rdcarray m_OutstandingQueries; - CaptureState &m_State; WrappedID3D12DebugCommandList m_WrappedDebug; diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index c70b5e7ac..deba85d25 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -67,15 +67,15 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close(SerialiserType &ser) ToStr(BakedCommandList).c_str()); #endif - int &markerCount = m_Cmd->m_BakedCmdListInfo[BakedCommandList].markerCount; + BakedCmdListInfo &bakedInfo = m_Cmd->m_BakedCmdListInfo[BakedCommandList]; - for(int i = 0; i < markerCount; i++) + for(int i = 0; i < bakedInfo.markerCount; i++) D3D12MarkerRegion::End(list); - for(OutstandingQuery &q : m_OutstandingQueries) + for(BakedCmdListInfo::OutstandingQuery &q : bakedInfo.m_OutstandingQueries) Unwrap(list)->EndQuery(Unwrap(q.heap), q.Type, q.Index); - m_OutstandingQueries.clear(); + bakedInfo.m_OutstandingQueries.clear(); if(m_Cmd->m_ActionCallback) m_Cmd->m_ActionCallback->PreCloseCommandList(list); @@ -2851,7 +2851,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_BeginQuery(SerialiserType &ser, Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->BeginQuery(Unwrap(pQueryHeap), Type, Index); - m_OutstandingQueries.push_back({pQueryHeap, Type, Index}); + m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].m_OutstandingQueries.push_back( + {pQueryHeap, Type, Index}); } } } @@ -2912,7 +2913,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_EndQuery(SerialiserType &ser, Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->EndQuery(Unwrap(pQueryHeap), Type, Index); - m_OutstandingQueries.removeOne({pQueryHeap, Type, Index}); + m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].m_OutstandingQueries.removeOne( + {pQueryHeap, Type, Index}); } } } diff --git a/renderdoc/driver/d3d12/d3d12_commands.h b/renderdoc/driver/d3d12/d3d12_commands.h index 606c8fb4e..2c4762dee 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.h +++ b/renderdoc/driver/d3d12/d3d12_commands.h @@ -214,6 +214,20 @@ struct BakedCmdListInfo rdcflatmap m_patchRaytracingInfo; + struct OutstandingQuery + { + ID3D12QueryHeap *heap; + D3D12_QUERY_TYPE Type; + UINT Index; + + bool operator==(const OutstandingQuery &q) const + { + return heap == q.heap && Type == q.Type && Index == q.Index; + } + }; + + rdcarray m_OutstandingQueries; + ResourceId allocator; D3D12_COMMAND_LIST_TYPE type; UINT nodeMask; diff --git a/util/test/demos/d3d12/d3d12_predication.cpp b/util/test/demos/d3d12/d3d12_predication.cpp index 6b44360de..5b0838948 100644 --- a/util/test/demos/d3d12/d3d12_predication.cpp +++ b/util/test/demos/d3d12/d3d12_predication.cpp @@ -45,6 +45,14 @@ RD_TEST(D3D12_Predication, D3D12GraphicsTest) ID3D12QueryHeapPtr qh; dev->CreateQueryHeap(&desc, __uuidof(ID3D12QueryHeap), (void **)&qh); + desc.Count = 16; + ID3D12QueryHeapPtr qh2; + dev->CreateQueryHeap(&desc, __uuidof(ID3D12QueryHeap), (void **)&qh2); + + ID3D12CommandAllocatorPtr alloc2; + CHECK_HR(dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + __uuidof(ID3D12CommandAllocator), (void **)&alloc2)); + ID3D12ResourcePtr queryData = MakeBuffer().Size(sizeof(uint64_t) * (desc.Count + 1) * 3); uint64_t val = 1; @@ -98,6 +106,7 @@ RD_TEST(D3D12_Predication, D3D12GraphicsTest) while(Running()) { ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer(); + ID3D12GraphicsCommandListPtr cmd2 = GetCommandBuffer(); Reset(cmd); @@ -177,9 +186,20 @@ RD_TEST(D3D12_Predication, D3D12GraphicsTest) FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); + // check for queries being "imbalanced" between command buffers + + cmd2->Reset(alloc2, NULL); + + cmd2->BeginQuery(qh2, D3D12_QUERY_TYPE_OCCLUSION, 0); + + // this is fine, because the query is open on cmd2 cmd->Close(); - Submit({cmd}); + cmd2->EndQuery(qh2, D3D12_QUERY_TYPE_OCCLUSION, 0); + + cmd2->Close(); + + Submit({cmd, cmd2}); Present(); } diff --git a/util/test/tests/D3D12/D3D12_Predication.py b/util/test/tests/D3D12/D3D12_Predication.py index 2e279c7aa..aaee1e360 100644 --- a/util/test/tests/D3D12/D3D12_Predication.py +++ b/util/test/tests/D3D12/D3D12_Predication.py @@ -54,3 +54,11 @@ class D3D12_Predication(rdtest.TestCase): self.check(self.controller.GetD3D12PipelineState().predication.offset > 0) rdtest.log.success("Failing predicated triangle is correct") + + for eid in range(self.get_last_action().eventId): + self.controller.SetFrameEvent(eid, False) + + if not self.controller.GetFatalErrorStatus().OK(): + raise rdtest.TestFailureException(self.controller.GetFatalErrorStatus().Message()) + + rdtest.log.success("All events replay correctly")