diff --git a/util/test/demos/d3d12/d3d12_execute_indirect.cpp b/util/test/demos/d3d12/d3d12_execute_indirect.cpp index 4c05eb3d5..c07c0e52d 100644 --- a/util/test/demos/d3d12/d3d12_execute_indirect.cpp +++ b/util/test/demos/d3d12/d3d12_execute_indirect.cpp @@ -269,7 +269,7 @@ void main(uint3 gid : SV_GroupID) ID3D12CommandSignaturePtr patchArgSig = MakeCommandSig(patchsig, {vbArg(0), cbvArg(0), srvArg(1), uavArg(2), drawArg()}); - struct + struct PatchArgs { D3D12_VERTEX_BUFFER_VIEW vb; D3D12_GPU_VIRTUAL_ADDRESS cbv; @@ -322,6 +322,16 @@ void main(uint3 gid : SV_GroupID) ID3D12PipelineStatePtr comppso = MakePSO().RootSig(compsig).CS(csblob); ID3D12ResourcePtr customvbargs = MakeBuffer().Size(1024 * 1024 * 4); + const uint32_t countDrawsInFullBuffer = 3; + ID3D12ResourcePtr fullargsDrawBuf = + MakeBuffer().Size(countDrawsInFullBuffer * sizeof(D3D12_INDIRECT_ARGUMENT_DESC)); + + PatchArgs fullargsStateDraw[countDrawsInFullBuffer]; + for(uint32_t i = 0; i < countDrawsInFullBuffer; ++i) + fullargsStateDraw[i] = patchargs; + + ID3D12ResourcePtr fullargsStateDrawBuf = + MakeBuffer().Upload().Size(countDrawsInFullBuffer * sizeof(patchargs)).Data(fullargsStateDraw); ID3D12RootSignaturePtr plainsig = MakeSig({}); ID3D12PipelineStatePtr plainpso = @@ -448,6 +458,42 @@ void main(uint3 gid : SV_GroupID) } popMarker(cmd); + pushMarker(cmd, "Full Arg Buffer: Pure Draw"); + { + cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + D3D12_VERTEX_BUFFER_VIEW view; + view.BufferLocation = customvbargs->GetGPUVirtualAddress() + 4096 * (sizeof(Vec4f)) + 256; + view.StrideInBytes = sizeof(A2V); + view.SizeInBytes = sizeof(A2V) * 1120; + cmd->IASetVertexBuffers(0, 1, &view); + + cmd->SetPipelineState(plainpso); + cmd->SetGraphicsRootSignature(plainsig); + + RSSetViewport(cmd, {0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + + OMSetRenderTargets(cmd, {rtv}, {}); + + cmd->ExecuteIndirect(plainArgSig, countDrawsInFullBuffer, fullargsDrawBuf, 0, NULL, 0); + } + popMarker(cmd); + + pushMarker(cmd, "Full Arg Buffer: State + Draw"); + { + cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + cmd->SetPipelineState(patchpso); + cmd->SetGraphicsRootSignature(patchsig); + + RSSetViewport(cmd, {0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + + OMSetRenderTargets(cmd, {rtv}, {}); + cmd->ExecuteIndirect(patchArgSig, countDrawsInFullBuffer, fullargsStateDrawBuf, 0, NULL, 0); + } + popMarker(cmd); + FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); cmd->Close(); diff --git a/util/test/tests/D3D12/D3D12_Execute_Indirect.py b/util/test/tests/D3D12/D3D12_Execute_Indirect.py index 4c3f9c26c..af941c71b 100644 --- a/util/test/tests/D3D12/D3D12_Execute_Indirect.py +++ b/util/test/tests/D3D12/D3D12_Execute_Indirect.py @@ -172,4 +172,28 @@ class D3D12_Execute_Indirect(rdtest.TestCase): raise rdtest.TestFailureException( "Detected an exploded polygon with {} selected".format(action.GetName(sdfile))) - rdtest.log.success("Pass {} of unordered draw was correct") \ No newline at end of file + rdtest.log.success(f"Pass {passNum} of unordered draw was correct") + + # This does not draw anything but its argument buffer is fully used with no spare bytes + # Iterate over every draw and check the replay has valid output target + action = self.find_action("Full Arg Buffer") + action = self.find_action("IndirectDraw", action.eventId) + for drawNum in range(3): + self.controller.SetFrameEvent(action.eventId + drawNum, False) + pipe = self.controller.GetPipelineState() + if len(pipe.GetOutputTargets()) != 1: + raise rdtest.TestFailureException( + f"With event {action.eventId + drawNum} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") + rdtest.log.success("Fully used argument buffer with multiple draws replayed") + + # This does not draw anything but its argument buffer is fully used with no spare bytes + # Iterate over every draw and check the replay has valid output target + action = self.find_action("Full Arg Buffer: State + Draw") + action = self.find_action("IndirectDraw", action.eventId) + for drawNum in range(3): + self.controller.SetFrameEvent(action.eventId + drawNum, False) + pipe = self.controller.GetPipelineState() + if len(pipe.GetOutputTargets()) != 1: + raise rdtest.TestFailureException( + f"With event {action.eventId + drawNum} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") + rdtest.log.success("Fully used argument buffer with multiple states + draws replayed")