Extend D3D12 ExecuteIndirect test to do multiple draws per Execute

The argument buffers are used fully used with no spare bytes
The python test iterates over every draw to check the replay has a valid output target count
This verifies the replay did not crash when replaying ExecuteIndirect with multiple draws and an argument buffer with no spare bytes
This commit is contained in:
Jake Turner
2024-01-29 15:56:05 +00:00
parent b6a105d695
commit 20578f46a6
2 changed files with 72 additions and 2 deletions
@@ -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();
@@ -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")
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")