From 5a1b2c23e147f0dd063f9ef2b44b6fb89526ad59 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Fri, 24 Jul 2026 17:12:22 +0100 Subject: [PATCH] Extend D3D12_Annotations test - loose event annotation - a barrier at end of command buffer - at end of command buffer attached to CommandList Close - command buffer with no actions, just set marker - annotations before/during/after ExecuteIndirect calls --- util/test/demos/d3d12/d3d12_annotations.cpp | 127 +++++++++++++++++++- util/test/tests/D3D12/D3D12_Annotations.py | 52 +++++++- 2 files changed, 174 insertions(+), 5 deletions(-) diff --git a/util/test/demos/d3d12/d3d12_annotations.cpp b/util/test/demos/d3d12/d3d12_annotations.cpp index 909eb59d1..bf23f45ab 100644 --- a/util/test/demos/d3d12/d3d12_annotations.cpp +++ b/util/test/demos/d3d12/d3d12_annotations.cpp @@ -28,6 +28,20 @@ RD_TEST(D3D12_Annotations, D3D12GraphicsTest) { static constexpr const char *Description = "Test annotations via the D3D12 API."; + float sqSize; + Vec2f viewXY; + + void NextTest() + { + viewXY.x += sqSize; + + if(viewXY.x + sqSize >= (float)screenWidth) + { + viewXY.x = 0.0f; + viewXY.y += sqSize; + } + } + int main() { // initialise, create window, create device, etc @@ -41,6 +55,23 @@ RD_TEST(D3D12_Annotations, D3D12GraphicsTest) img->SetName(L"Annotated Image"); DefaultTriVB->SetName(L"Vertex Buffer"); + ID3D12CommandSignaturePtr plainArgSig = MakeCommandSig(NULL, {drawArg()}); + + const uint32_t maxCountDraws = 16; + D3D12_DRAW_ARGUMENTS countSingleDraws[maxCountDraws]; + for(uint32_t i = 0; i < maxCountDraws; ++i) + { + countSingleDraws[i].VertexCountPerInstance = 3; + countSingleDraws[i].InstanceCount = i + 1; + countSingleDraws[i].StartInstanceLocation = 0; + countSingleDraws[i].StartVertexLocation = 0; + } + ID3D12ResourcePtr countSingleDrawsArgBuf = + MakeBuffer().Size(sizeof(countSingleDraws)).Data(&countSingleDraws); + + uint32_t counts[] = {0, 0, 2, 0}; + ID3D12ResourcePtr countBuf = MakeBuffer().Data(counts); + // cache the device pointer we pass in void *d = dev; @@ -103,8 +134,13 @@ RD_TEST(D3D12_Annotations, D3D12GraphicsTest) rdoc->SetObjectAnnotation(d, img, "path.deleted", eRENDERDOC_Empty, 0, NULL); } + sqSize = float(screenHeight) / 3.0f; + while(Running()) { + viewXY.x = 0.0f; + viewXY.y = 0.0f; + if(rdoc) { // queue annotations are only included when in the captured frame @@ -123,6 +159,9 @@ RD_TEST(D3D12_Annotations, D3D12GraphicsTest) rdoc->SetCommandAnnotation(d, queue, "command.deleted", eRENDERDOC_Int32, 0, RDAnnotationHelper(50)); + + rdoc->SetCommandAnnotation(d, queue, "draw.indirect", eRENDERDOC_Int32, 0, + RDAnnotationHelper(10000)); } ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer(); @@ -143,6 +182,9 @@ RD_TEST(D3D12_Annotations, D3D12GraphicsTest) RDAnnotationHelper(3333)); rdoc->SetCommandAnnotation(d, cmd, "command.deleted", eRENDERDOC_Empty, 0, NULL); + + rdoc->SetCommandAnnotation(d, cmd, "draw.indirect", eRENDERDOC_Int32, 0, + RDAnnotationHelper(20000)); } setMarker(cmd, "Initial"); @@ -166,7 +208,8 @@ RD_TEST(D3D12_Annotations, D3D12GraphicsTest) cmd->SetPipelineState(DefaultTriPSO); cmd->SetGraphicsRootSignature(DefaultTriSig); - SetMainWindowViewScissor(cmd); + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); OMSetRenderTargets(cmd, {BBRTV}, {}); @@ -183,19 +226,95 @@ RD_TEST(D3D12_Annotations, D3D12GraphicsTest) setMarker(cmd, "Draw 1"); cmd->DrawInstanced(3, 1, 0, 0); + NextTest(); - RSSetViewport( - cmd, {0.0f, 0.0f, (float)screenWidth / 2.0f, (float)screenHeight / 2.0f, 0.0f, 1.0f}); + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); setMarker(cmd, "Draw 2"); cmd->DrawInstanced(3, 1, 0, 0); + NextTest(); + + if(rdoc) + { + rdoc->SetCommandAnnotation(d, cmd, "draw.indirect", eRENDERDOC_Int32, 0, + RDAnnotationHelper(30000)); + } + setMarker(cmd, "Pre-DrawIndirectCount"); + + pushMarker(cmd, "DrawIndirectCount"); + { + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + setMarker(cmd, "DrawIndirectCount(0:0)"); + if(rdoc) + { + rdoc->SetCommandAnnotation(d, cmd, "draw.indirect", eRENDERDOC_Int32, 0, + RDAnnotationHelper(1)); + } + cmd->ExecuteIndirect(plainArgSig, 0, countSingleDrawsArgBuf, 0, countBuf, 0); + NextTest(); + + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + setMarker(cmd, "DrawIndirectCount(10:0)"); + if(rdoc) + { + rdoc->SetCommandAnnotation(d, cmd, "draw.indirect", eRENDERDOC_Int32, 0, + RDAnnotationHelper(2)); + } + // TODO EXECUTE INDIRECT DRAW MAXCOUNT = 10 COUNT = 0 + cmd->ExecuteIndirect(plainArgSig, 10, countSingleDrawsArgBuf, 0, countBuf, 4); + NextTest(); + + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + setMarker(cmd, "DrawIndirectCount(10:N)"); + if(rdoc) + { + rdoc->SetCommandAnnotation(d, cmd, "draw.indirect", eRENDERDOC_Int32, 0, + RDAnnotationHelper(3)); + } + // TODO EXECUTE INDIRECT DRAW MAXCOUNT = 10 COUNT = N + cmd->ExecuteIndirect(plainArgSig, 10, countSingleDrawsArgBuf, 0, countBuf, 8); + NextTest(); + popMarker(cmd); + } + + if(rdoc) + { + rdoc->SetCommandAnnotation(d, cmd, "draw.indirect", eRENDERDOC_Int32, 0, + RDAnnotationHelper(40000)); + } + setMarker(cmd, "Post-DrawIndirectCount"); + + setMarker(cmd, "Loose"); + if(rdoc) + { + rdoc->SetCommandAnnotation(d, cmd, "loose.int", eRENDERDOC_Int32, 0, RDAnnotationHelper(1)); + } FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); + if(rdoc) + { + rdoc->SetCommandAnnotation(d, cmd, "loose.int", eRENDERDOC_Int32, 0, RDAnnotationHelper(2)); + rdoc->SetCommandAnnotation(d, cmd, "new.value", eRENDERDOC_Empty, 0, NULL); + } cmd->Close(); - SubmitAndPresent({cmd}); + ID3D12GraphicsCommandListPtr empty = GetCommandBuffer(); + + Reset(empty); + setMarker(empty, "Empty"); + if(rdoc) + { + rdoc->SetCommandAnnotation(d, empty, "empty.int", eRENDERDOC_Int32, 0, RDAnnotationHelper(1)); + } + empty->Close(); + + SubmitAndPresent({empty, cmd}); } return 0; diff --git a/util/test/tests/D3D12/D3D12_Annotations.py b/util/test/tests/D3D12/D3D12_Annotations.py index 5ec7003ba..d18b5bf76 100644 --- a/util/test/tests/D3D12/D3D12_Annotations.py +++ b/util/test/tests/D3D12/D3D12_Annotations.py @@ -8,4 +8,54 @@ class D3D12_Annotations(rdtest.Annotations): def check_capture(self): super().check_resource_annotations() - super().check_command_annotations(True) \ No newline at end of file + super().check_command_annotations(True) + + annot = lambda x: annots.FindChildByKeyPath(x) + + # Check annotations attached to indirect draws + draw_indirect_count = self.find_action("DrawIndirectCount") + with rdtest.log.auto_section('DrawIndirectCount'): + expected_values = [("Start", 10000), + ("Initial", 20000), + ("Pre-DrawIndirectCount", 30000)] + if draw_indirect_count is not None: + expected_values += [ + ("ExecuteIndirect(maxCount 0, count <0>)", 1), + ("ExecuteIndirect(maxCount 10, count <0>)", 2), + ("[0] arg0: IndirectDraw(<3, 1>)", 3), + ("[1] arg0: IndirectDraw(<3, 2>)", 3)] + expected_values += [("Post-DrawIndirectCount", 40000)] + + action = self.get_first_action() + for name, value in expected_values: + action = self.find_action(name, action.eventId) + rdtest.log.print(f'Checking {name}') + annots = action.events[-1].annotations + key = "draw.indirect" + self.check_eq(annot(key).type.basetype, rd.SDBasic.SignedInteger) + self.check_eq(annot(key).AsInt(), value) + + # Check loose event annotation attached to a barrier + with rdtest.log.auto_section('Loose Event'): + marker = self.find_action("Loose") + action = marker.next + annots = action.events[0].annotations + self.check_eq(annot("loose.int").type.basetype, rd.SDBasic.SignedInteger) + self.check_eq(annot("loose.int").AsInt(), 1) + + # Check loose event annotation attached to vkEndCommandBuffer + with rdtest.log.auto_section('CommandList Close Event'): + marker = self.find_action("Loose") + action = marker.next + annots = action.events[-1].annotations + self.check_eq(annot("loose.int").type.basetype, rd.SDBasic.SignedInteger) + self.check_eq(annot("loose.int").AsInt(), 2) + self.check(annot("new.value") is None) + + # Check loose event annotation in an empty command buffer + with rdtest.log.auto_section('Empty Command Buffer'): + marker = self.find_action("Empty") + action = marker.next + annots = action.events[0].annotations + self.check_eq(annot("empty.int").type.basetype, rd.SDBasic.SignedInteger) + self.check_eq(annot("empty.int").AsInt(), 1)