diff --git a/util/test/demos/d3d12/d3d12_execute_indirect.cpp b/util/test/demos/d3d12/d3d12_execute_indirect.cpp index 74dda582e..c1577cbc9 100644 --- a/util/test/demos/d3d12/d3d12_execute_indirect.cpp +++ b/util/test/demos/d3d12/d3d12_execute_indirect.cpp @@ -415,24 +415,28 @@ void main(uint3 gid : SV_GroupID) ID3D12PipelineStatePtr patchpso2 = MakePSO().RootSig(patchsig).InputLayout(layout).VS(vsblob).PS(psblob); - struct PatchArgs3 + D3D12_DRAW_ARGUMENTS singleDraw; + singleDraw.VertexCountPerInstance = 3; + singleDraw.InstanceCount = 1024; + singleDraw.StartInstanceLocation = 0; + singleDraw.StartVertexLocation = 6; + + ID3D12ResourcePtr patchArgBuf3 = MakeBuffer().Upload().Size(sizeof(singleDraw)).Data(&singleDraw); + + const uint32_t maxCountDraws = 1024; + D3D12_DRAW_ARGUMENTS countSingleDraws[maxCountDraws]; + for(uint32_t i = 0; i < maxCountDraws; ++i) { - D3D12_DRAW_ARGUMENTS draw; - } patchargs3; + countSingleDraws[i].VertexCountPerInstance = 3; + countSingleDraws[i].InstanceCount = i + 1; + countSingleDraws[i].StartInstanceLocation = 0; + countSingleDraws[i].StartVertexLocation = (9 + (i * 3)) % 18; + } + ID3D12ResourcePtr countSingleDrawsArgBuf = + MakeBuffer().Size(sizeof(countSingleDraws)).Data(&countSingleDraws); - patchargs3.draw.VertexCountPerInstance = 3; - patchargs3.draw.InstanceCount = 1024; - patchargs3.draw.StartInstanceLocation = 0; - patchargs3.draw.StartVertexLocation = 6; - - std::vector patchArgsData3; - patchArgsData3.resize(sizeof(PatchArgs3)); - - char *ptr3 = patchArgsData3.data(); - patchArgsData3.resize(sizeof(PatchArgs3)); - memcpy(ptr3, &patchargs3.draw, sizeof(D3D12_DRAW_ARGUMENTS)); - ID3D12ResourcePtr patchArgBuf3 = - MakeBuffer().Upload().Size((UINT)patchArgsData3.size()).Data(patchArgsData3.data()); + uint32_t counts[] = {0, 5, 7, 11}; + ID3D12ResourcePtr countBuf = MakeBuffer().Data(counts); ID3D12PipelineStatePtr patchpso3 = MakePSO().RootSig(patchsig).InputLayout(layout).VS(vsblob).PS(psblob); @@ -710,6 +714,42 @@ void main(uint3 gid : SV_GroupID) } popMarker(cmd); + pushMarker(cmd, "Count Buffer Draws"); + { + cmd->SetPipelineState(patchpso3); + cmd->SetGraphicsRootSignature(patchsig); + cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr()); + cmd->SetGraphicsRootDescriptorTable(5, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->SetGraphicsRootConstantBufferView(0, cbv->GetGPUVirtualAddress() + 256); + cmd->SetGraphicsRootShaderResourceView(1, srv->GetGPUVirtualAddress() + 256); + cmd->SetGraphicsRootUnorderedAccessView(2, uav->GetGPUVirtualAddress() + 256); + D3D12_VERTEX_BUFFER_VIEW view; + view.BufferLocation = vb->GetGPUVirtualAddress(); + view.SizeInBytes = sizeof(tris); + view.StrideInBytes = sizeof(A2V); + cmd->IASetVertexBuffers(0, 1, &view); + + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + + OMSetRenderTargets(cmd, {rtv}, {}); + + cmd->SetGraphicsRoot32BitConstants(3, 4, baseConstData, 0); + + setMarker(cmd, "MaxCount: 1024 CountBuf: 5"); + cmd->ExecuteIndirect(plainArgSig, maxCountDraws, countSingleDrawsArgBuf, 0, countBuf, 4); + NextTest(); + setMarker(cmd, "MaxCount: 1 CountBuf: 7"); + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + cmd->ExecuteIndirect(plainArgSig, 1, countSingleDrawsArgBuf, 0, countBuf, 8); + NextTest(); + setMarker(cmd, "MaxCount: 0 CountBuf: 11"); + RSSetViewport(cmd, {viewXY.x, viewXY.y, sqSize, sqSize, 0.0f, 1.0f}); + cmd->ExecuteIndirect(plainArgSig, 0, countSingleDrawsArgBuf, 0, countBuf, 12); + NextTest(); + } + popMarker(cmd); + pushMarker(cmd, "Two Single Draws"); { cmd->SetPipelineState(patchpso3); diff --git a/util/test/tests/D3D12/D3D12_Execute_Indirect.py b/util/test/tests/D3D12/D3D12_Execute_Indirect.py index 74c09f86f..32a97cb84 100644 --- a/util/test/tests/D3D12/D3D12_Execute_Indirect.py +++ b/util/test/tests/D3D12/D3D12_Execute_Indirect.py @@ -65,145 +65,144 @@ class D3D12_Execute_Indirect(rdtest.TestCase): rdtest.log.success("rootConsts is as expected") def check_capture(self): - action = self.find_action("EI without Root Signature"); - self.controller.SetFrameEvent(action.eventId, False) - 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())}") - self.check_pixel_history_succeeds(285, 110) - if drawNum == 0: - self.check_overlays(action.eventId, 285, 110) - rdtest.log.success("Draw without Root Signature replayed correctly"); + with rdtest.log.auto_section('EI without Root Signature'): + action = self.find_action("EI without Root Signature"); + self.controller.SetFrameEvent(action.eventId, False) + 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())}") + self.check_pixel_history_succeeds(285, 110) + if drawNum == 0: + self.check_overlays(action.eventId, 285, 110) - from_eid = self.find_action("Multiple draws").eventId - ei_eid = self.find_action("ExecuteIndirect", from_eid).eventId - self.controller.SetFrameEvent(ei_eid - 1, False) - self.check_root_consts([10.0, 9.0, 8.0, 7.0]) - viewX = 0 - viewY = 0 - sqSize = 300 / 4 - viewW = sqSize - viewH = sqSize - for i in range(8): - action = self.find_action("IndirectDraw", from_eid) - eid = action.eventId - self.controller.SetFrameEvent(eid, False) - self.check_root_consts([123.0, 9.0, 8.0, 7.0]) + with rdtest.log.auto_section('Multiple draws'): + from_eid = self.find_action("Multiple draws").eventId + ei_eid = self.find_action("ExecuteIndirect", from_eid).eventId + self.controller.SetFrameEvent(ei_eid - 1, False) + self.check_root_consts([10.0, 9.0, 8.0, 7.0]) + viewX = 0 + viewY = 0 + sqSize = 300 / 4 + viewW = sqSize + viewH = sqSize + for i in range(8): + action = self.find_action("IndirectDraw", from_eid) + eid = action.eventId + self.controller.SetFrameEvent(eid, False) + self.check_root_consts([123.0, 9.0, 8.0, 7.0]) - # Should be a green triangle in the centre of the screen on a black background + # Should be a green triangle in the centre of the screen on a black background + self.check_triangle(back=[0.0, 0.0, 0.0, 1.0], vp=[viewX, viewY, viewW, viewH]) + + vsin_ref = { + 0: { + 'vtx': 0, + 'idx': 0, + 'POSITION': [-0.5, -0.5, 0.0, 0.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + }, + 1: { + 'vtx': 1, + 'idx': 1, + 'POSITION': [0.0, 0.5, 0.0, 0.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + }, + 2: { + 'vtx': 2, + 'idx': 2, + 'POSITION': [0.5, -0.5, 0.0, 0.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + }, + } + self.check_mesh_data(vsin_ref, self.get_vsin(action)) + postvs_data = self.get_postvs(action, rd.MeshDataStage.VSOut, 0, action.numIndices) + postvs_ref = { + 0: { + 'vtx': 0, + 'idx': 0, + 'SV_POSITION': [-0.5, -0.5, 0.0, 1.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + }, + 1: { + 'vtx': 1, + 'idx': 1, + 'SV_POSITION': [0.0, 0.5, 0.0, 1.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + }, + 2: { + 'vtx': 2, + 'idx': 2, + 'SV_POSITION': [0.5, -0.5, 0.0, 1.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + }, + } + self.check_mesh_data(postvs_ref, postvs_data) + + x = int(viewX + viewW/2) + y = int(viewY + viewH/2) + self.check_pixel_history_succeeds(x,y) + self.check_overlays(eid, x,y) + + from_eid = eid + 1 + + pipe = self.controller.GetPipelineState() + + vbs = pipe.GetVBuffers() + ro = pipe.GetReadOnlyResources(rd.ShaderStage.Vertex) + rw = pipe.GetReadWriteResources(rd.ShaderStage.Vertex) + self.check(vbs[0].resourceId != rd.ResourceId()) + self.check(ro[0].descriptor.resource != rd.ResourceId()) + self.check(rw[0].descriptor.resource != rd.ResourceId()) + self.check(pipe.GetConstantBlock(rd.ShaderStage.Vertex, 0, 0).descriptor.resource != rd.ResourceId()) + + viewX += sqSize + if viewX + sqSize >= 400: + viewX = 0 + viewY += sqSize + + with rdtest.log.auto_section('State is reset after execute'): + viewX = 0 + viewY = 0 + action = self.find_action("Post draw") + self.controller.SetFrameEvent(action.eventId, False) + + # triangle should still be visible self.check_triangle(back=[0.0, 0.0, 0.0, 1.0], vp=[viewX, viewY, viewW, viewH]) - vsin_ref = { - 0: { - 'vtx': 0, - 'idx': 0, - 'POSITION': [-0.5, -0.5, 0.0, 0.0], - 'COLOR': [0.0, 1.0, 0.0, 1.0], - }, - 1: { - 'vtx': 1, - 'idx': 1, - 'POSITION': [0.0, 0.5, 0.0, 0.0], - 'COLOR': [0.0, 1.0, 0.0, 1.0], - }, - 2: { - 'vtx': 2, - 'idx': 2, - 'POSITION': [0.5, -0.5, 0.0, 0.0], - 'COLOR': [0.0, 1.0, 0.0, 1.0], - }, - } - self.check_mesh_data(vsin_ref, self.get_vsin(action)) - postvs_data = self.get_postvs(action, rd.MeshDataStage.VSOut, 0, action.numIndices) - postvs_ref = { - 0: { - 'vtx': 0, - 'idx': 0, - 'SV_POSITION': [-0.5, -0.5, 0.0, 1.0], - 'COLOR': [0.0, 1.0, 0.0, 1.0], - }, - 1: { - 'vtx': 1, - 'idx': 1, - 'SV_POSITION': [0.0, 0.5, 0.0, 1.0], - 'COLOR': [0.0, 1.0, 0.0, 1.0], - }, - 2: { - 'vtx': 2, - 'idx': 2, - 'SV_POSITION': [0.5, -0.5, 0.0, 1.0], - 'COLOR': [0.0, 1.0, 0.0, 1.0], - }, - } - self.check_mesh_data(postvs_ref, postvs_data) - - x = int(viewX + viewW/2) - y = int(viewY + viewH/2) - self.check_pixel_history_succeeds(x,y) - self.check_overlays(eid, x,y) - - from_eid = eid + 1 - + # but state should be reset pipe = self.controller.GetPipelineState() vbs = pipe.GetVBuffers() ro = pipe.GetReadOnlyResources(rd.ShaderStage.Vertex) rw = pipe.GetReadWriteResources(rd.ShaderStage.Vertex) - self.check(vbs[0].resourceId != rd.ResourceId()) - self.check(ro[0].descriptor.resource != rd.ResourceId()) - self.check(rw[0].descriptor.resource != rd.ResourceId()) - self.check(pipe.GetConstantBlock(rd.ShaderStage.Vertex, 0, 0).descriptor.resource != rd.ResourceId()) - - viewX += sqSize - if viewX + sqSize >= 400: - viewX = 0 - viewY += sqSize - - viewX = 0 - viewY = 0 - action = self.find_action("Post draw") - self.controller.SetFrameEvent(action.eventId, False) - - # triangle should still be visible - self.check_triangle(back=[0.0, 0.0, 0.0, 1.0], vp=[viewX, viewY, viewW, viewH]) - - # but state should be reset - pipe = self.controller.GetPipelineState() - - vbs = pipe.GetVBuffers() - ro = pipe.GetReadOnlyResources(rd.ShaderStage.Vertex) - rw = pipe.GetReadWriteResources(rd.ShaderStage.Vertex) - self.check(len(vbs) == 0 or vbs[0].resourceId == rd.ResourceId()) - self.check(len(ro) == 0 or ro[0].descriptor.resource == rd.ResourceId()) - self.check(len(rw) == 0 or rw[0].descriptor.resource == rd.ResourceId()) - self.check(pipe.GetConstantBlock(rd.ShaderStage.Vertex, 0, 0).descriptor.resource == rd.ResourceId()) - - rdtest.log.success("State is reset after execute") + self.check(len(vbs) == 0 or vbs[0].resourceId == rd.ResourceId()) + self.check(len(ro) == 0 or ro[0].descriptor.resource == rd.ResourceId()) + self.check(len(rw) == 0 or rw[0].descriptor.resource == rd.ResourceId()) + self.check(pipe.GetConstantBlock(rd.ShaderStage.Vertex, 0, 0).descriptor.resource == rd.ResourceId()) self.check_pixel_history_succeeds(185, 50) - action = self.find_action("Post Single dispatch") - self.controller.SetFrameEvent(action.eventId, False) + with rdtest.log.auto_section('Dispatch buffer output is correct'): + action = self.find_action("Post Single dispatch") + self.controller.SetFrameEvent(action.eventId, False) - pipe = self.controller.GetPipelineState() - rw = pipe.GetReadWriteResources(rd.ShaderStage.Compute) + pipe = self.controller.GetPipelineState() + rw = pipe.GetReadWriteResources(rd.ShaderStage.Compute) - for z in range(10): - for y in range(30): - for x in range(12): - idx = z*30*12+y*12+x - value = struct.unpack_from('4f', self.controller.GetBufferData(rw[0].descriptor.resource, 16*idx, 16)) - expect = [float(x), float(y), float(z), float(idx)] + for z in range(10): + for y in range(30): + for x in range(12): + idx = z*30*12+y*12+x + value = struct.unpack_from('4f', self.controller.GetBufferData(rw[0].descriptor.resource, 16*idx, 16)) + expect = [float(x), float(y), float(z), float(idx)] - if not rdtest.value_compare(expect, value): - raise rdtest.TestFailureException( - "buffer at {},{},{}: {} doesn't match expected {}".format(x, y, z, value, expect)) - - rdtest.log.success("Dispatch buffer output is correct") + if not rdtest.value_compare(expect, value): + raise rdtest.TestFailureException( + "buffer at {},{},{}: {} doesn't match expected {}".format(x, y, z, value, expect)) self.check_pixel_history_succeeds(185, 50) @@ -214,129 +213,173 @@ class D3D12_Execute_Indirect(rdtest.TestCase): # time we replay it should be self-consistent - after selecting the 4th draw then eactly 4 draws should appear. # And of course no exploding polys! - action = self.find_action("Custom order draw") - action = self.find_action("IndirectDraw", action.eventId) + with rdtest.log.auto_section('Custom order draw'): + action = self.find_action("Custom order draw") + action = self.find_action("IndirectDraw", action.eventId) - drawPoints = [ - (310, 78), - (338, 78), - (367, 78), + drawPoints = [ + (310, 78), + (338, 78), + (367, 78), - (310, 107), - (367, 107), + (310, 107), + (367, 107), - (310, 135), - (338, 135), - (367, 135), - ] + (310, 135), + (338, 135), + (367, 135), + ] - sdfile = self.controller.GetStructuredFile() + sdfile = self.controller.GetStructuredFile() - # do N passes since it will be unpredictable - for passNum in range(50): - for drawNum in range(8): + # do N passes since it will be unpredictable + for passNum in range(50): + for drawNum in range(8): + self.controller.SetFrameEvent(action.eventId + drawNum, False) + + pipe = self.controller.GetPipelineState() + out = pipe.GetOutputTargets()[0].resource + + count = 0 + draws = [] + for i, p in enumerate(drawPoints): + picked = self.controller.PickPixel(out, p[0], p[1], rd.Subresource(), rd.CompType.UNorm) + if rdtest.value_compare(picked.floatValue, [0.0, 1.0, 0.0, 1.0]): + count += 1 + draws += [i] + + if not rdtest.value_compare(drawNum + 1, count): + raise rdtest.TestFailureException( + "With {} selected we should have {} draws, but counted {} draws".format(action.GetName(sdfile), + drawNum + 1, count)) + + rdtest.log.print("With draw #{} selected we saw draws {} active".format(drawNum, str(draws))) + + # the exploded verts are calibrated to render as purple. We don't handle the case where exploding polys + # reference vertices from other draws, but this _should_ not happen as we leave a large margin between + # each draw's segments + + data = self.controller.GetTextureData(out, rd.Subresource(0, 0, 0)) + tex = self.get_texture(out) + rdtest.log.print("{} - {} {} ".format(len(data), tex.width, tex.height)) + pixels = [struct.unpack_from("4B", data, 4 * p) for p in range(int(tex.width * tex.height))] + unique_pixels = list(set(pixels)) + + if (255, 0, 255, 255) in unique_pixels: + raise rdtest.TestFailureException( + "Detected an exploded polygon with {} selected".format(action.GetName(sdfile))) + + self.check_pixel_history_succeeds(185, 50) + + 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 + with rdtest.log.auto_section('Fully used argument buffer with multiple draws replayed'): + 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() - out = pipe.GetOutputTargets()[0].resource - - count = 0 - draws = [] - for i, p in enumerate(drawPoints): - picked = self.controller.PickPixel(out, p[0], p[1], rd.Subresource(), rd.CompType.UNorm) - if rdtest.value_compare(picked.floatValue, [0.0, 1.0, 0.0, 1.0]): - count += 1 - draws += [i] - - if not rdtest.value_compare(drawNum + 1, count): + if len(pipe.GetOutputTargets()) != 1: raise rdtest.TestFailureException( - "With {} selected we should have {} draws, but counted {} draws".format(action.GetName(sdfile), - drawNum + 1, count)) - - rdtest.log.print("With draw #{} selected we saw draws {} active".format(drawNum, str(draws))) - - # the exploded verts are calibrated to render as purple. We don't handle the case where exploding polys - # reference vertices from other draws, but this _should_ not happen as we leave a large margin between - # each draw's segments - - data = self.controller.GetTextureData(out, rd.Subresource(0, 0, 0)) - tex = self.get_texture(out) - rdtest.log.print("{} - {} {} ".format(len(data), tex.width, tex.height)) - pixels = [struct.unpack_from("4B", data, 4 * p) for p in range(int(tex.width * tex.height))] - unique_pixels = list(set(pixels)) - - if (255, 0, 255, 255) in unique_pixels: - raise rdtest.TestFailureException( - "Detected an exploded polygon with {} selected".format(action.GetName(sdfile))) - + f"With event {action.eventId + drawNum} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") self.check_pixel_history_succeeds(185, 50) - 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())}") - self.check_pixel_history_succeeds(185, 50) - 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): - eid = action.eventId - self.controller.SetFrameEvent(eid, False) - pipe = self.controller.GetPipelineState() - if len(pipe.GetOutputTargets()) != 1: - raise rdtest.TestFailureException( - f"With event {eid} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") - x = 100 - y = 210 - drawNum * 20 - self.check_overlays(eid, x, y) - self.check_pixel_history_succeeds(x, 210) - if drawNum > 0: - self.check_pixel_history_succeeds(x, 190) - if drawNum > 1: - self.check_pixel_history_succeeds(x, 170) - action = action.next - rdtest.log.success("Fully used argument buffer with multiple states + draws replayed") - - for drawNum in range(2): - action = self.find_action("Two Single Draws") + with rdtest.log.auto_section('Fully used argument buffer with multiple states + draws replayed'): + action = self.find_action("Full Arg Buffer: State + Draw") action = self.find_action("IndirectDraw", action.eventId) - if drawNum == 1: - action = self.find_action("IndirectDraw", action.eventId+1) + for drawNum in range(3): + eid = action.eventId + self.controller.SetFrameEvent(eid, False) + pipe = self.controller.GetPipelineState() + if len(pipe.GetOutputTargets()) != 1: + raise rdtest.TestFailureException( + f"With event {eid} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") + x = 100 + y = 210 - drawNum * 20 + self.check_overlays(eid, x, y) + self.check_pixel_history_succeeds(x, 210) + if drawNum > 0: + self.check_pixel_history_succeeds(x, 190) + if drawNum > 1: + self.check_pixel_history_succeeds(x, 170) + action = action.next - eid = action.eventId - self.controller.SetFrameEvent(action.eventId, False) - pipe = self.controller.GetPipelineState() - if len(pipe.GetOutputTargets()) != 1: - raise rdtest.TestFailureException( - f"With event {action.eventId} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") - x = 200 + 80 * drawNum - y = 205 - self.check_pixel_history_succeeds(x, y) - self.check_overlays(eid, x, y) + with rdtest.log.auto_section('Checking Count Buffer Draws'): + base = self.find_action("Count Buffer Draws") + tests = [ + ("MaxCount: 1024 CountBuf: 5", 5, 170), + ("MaxCount: 1 CountBuf: 7", 1, 250), + ("MaxCount: 0 CountBuf: 11", 0, 0) + ] + for test in tests: + marker = test[0] + expectedDraws = test[1] + xpos = test[2] + with rdtest.log.auto_section(f'Checking "{marker}"'): + markerAction = self.find_action(marker, base.eventId); + executeAction = self.find_action("ExecuteIndirect", markerAction.eventId); + # Exclude the ExecuteIndirect end marker + countDraws = len(executeAction.children) - 1 + self.check_eq(countDraws, expectedDraws) + action = self.find_action("IndirectDraw", executeAction.eventId) + for drawNum in range(countDraws): + eid = action.eventId + self.controller.SetFrameEvent(eid, False) + pipe = self.controller.GetPipelineState() + if len(pipe.GetOutputTargets()) != 1: + raise rdtest.TestFailureException( + f"With event {eid} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") + x = xpos + y = 210 - drawNum * 20 + if drawNum > 2: + x = xpos + 30 + y = 165 + (drawNum - 3) * 20 - overlay = rd.DebugOverlay.QuadOverdrawPass - tex = rd.TextureDisplay() - col_tex: rd.ResourceId = pipe.GetOutputTargets()[0].resource - tex.resourceId = col_tex - tex.overlay = overlay - tex.subresource.sample = 0 + self.check_overlays(eid, x, y) + self.check_pixel_history_succeeds(xpos, 210) + if drawNum > 0: + self.check_pixel_history_succeeds(xpos, 190) + if drawNum > 1: + self.check_pixel_history_succeeds(xpos, 170) + if drawNum > 2: + self.check_pixel_history_succeeds(x, 165) + if drawNum > 3: + self.check_pixel_history_succeeds(x, 185) + action = action.next - out: rd.ReplayOutput = self.controller.CreateOutput(rd.CreateHeadlessWindowingData(100, 100), rd.ReplayOutputType.Texture) - out.SetTextureDisplay(tex) - out.Display() - out.Shutdown() - rdtest.log.success("Two Single Draws QuadOverdraw (Pass) replayed correctly"); + with rdtest.log.auto_section('Two Single Draws QuadOverdraw (Pass) replayed correctly'): + for drawNum in range(2): + action = self.find_action("Two Single Draws") + action = self.find_action("IndirectDraw", action.eventId) + if drawNum == 1: + action = self.find_action("IndirectDraw", action.eventId+1) + + eid = action.eventId + self.controller.SetFrameEvent(action.eventId, False) + pipe = self.controller.GetPipelineState() + if len(pipe.GetOutputTargets()) != 1: + raise rdtest.TestFailureException( + f"With event {action.eventId} selected we should have one output target but there is {len(pipe.GetOutputTargets())}") + x = 50 + 80 * drawNum + y = 275 + self.check_pixel_history_succeeds(x, y) + self.check_overlays(eid, x, y) + + overlay = rd.DebugOverlay.QuadOverdrawPass + tex = rd.TextureDisplay() + col_tex: rd.ResourceId = pipe.GetOutputTargets()[0].resource + tex.resourceId = col_tex + tex.overlay = overlay + tex.subresource.sample = 0 + + out: rd.ReplayOutput = self.controller.CreateOutput(rd.CreateHeadlessWindowingData(100, 100), rd.ReplayOutputType.Texture) + out.SetTextureDisplay(tex) + out.Display() + out.Shutdown() with rdtest.log.auto_section('Checking All Overlays'): for eid in range(self.get_first_action().eventId, self.get_last_action().eventId + 1):