diff --git a/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp b/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp index 08aae6e56..1fb70cec6 100644 --- a/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp +++ b/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp @@ -776,6 +776,30 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 return float4(x + pos.x, y + pos.y, z + (float)numSamples, w); } +)EOSHADER"; + + std::string compute = R"EOSHADER( + +cbuffer consts : register(b0) +{ + bool boolX; + uint intY; + float floatZ; + double doubleX; +}; + +RWStructuredBuffer bufIn : register(u0); +RWStructuredBuffer bufOut : register(u1); + +[numthreads(3,2,1)] +void main() +{ + bufOut[0].x += bufIn[0].x * (uint)boolX; + bufOut[0].y += bufIn[0].y * (uint)intY; + bufOut[0].z += bufIn[0].z * (uint)floatZ; + bufOut[0].w += bufIn[0].w * (uint)doubleX; +} + )EOSHADER"; int main() @@ -912,6 +936,24 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 .VS(vsblob) .PS(psblob) .RTVs({DXGI_FORMAT_R32G32B32A32_FLOAT}); + // Recompile with SM 6.0 and SM 6.6 + vsblob = Compile(common + vertex, "main", "vs_6_0"); + psblob = Compile(common + "\n#define SM_6_0 1\n" + pixel, "main", "ps_6_0"); + ID3D12PipelineStatePtr pso_6_0 = MakePSO() + .RootSig(sig) + .InputLayout(inputLayout) + .VS(vsblob) + .PS(psblob) + .RTVs({DXGI_FORMAT_R32G32B32A32_FLOAT}); + + vsblob = Compile(common + vertex, "main", "vs_6_6"); + psblob = Compile(common + "\n#define SM_6_6 1\n" + pixel, "main", "ps_6_6"); + ID3D12PipelineStatePtr pso_6_6 = MakePSO() + .RootSig(sig) + .InputLayout(inputLayout) + .VS(vsblob) + .PS(psblob) + .RTVs({DXGI_FORMAT_R32G32B32A32_FLOAT}); static const uint32_t texDim = AlignUp(numTests, 64U) * 4; @@ -1136,14 +1178,26 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 }); ID3D12PipelineStatePtr blitpso = MakePSO().RootSig(blitSig).VS(vsblob).PS(psblob); - vsblob = Compile(vertexSampleVS, "main", "vs_5_0"); - psblob = Compile(vertexSamplePS, "main", "ps_5_0"); ID3D12RootSignaturePtr vertexSampleSig = MakeSig( { tableParam(D3D12_SHADER_VISIBILITY_VERTEX, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 0, 1, 8), }, D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS); - ID3D12PipelineStatePtr vertexSamplePSO = MakePSO().RootSig(vertexSampleSig).VS(vsblob).PS(psblob); + + vsblob = Compile(vertexSampleVS, "main", "vs_5_0"); + psblob = Compile(vertexSamplePS, "main", "ps_5_0"); + ID3D12PipelineStatePtr vertexSamplePSO_5_0 = + MakePSO().RootSig(vertexSampleSig).VS(vsblob).PS(psblob); + + vsblob = Compile(vertexSampleVS, "main", "vs_6_0"); + psblob = Compile(vertexSamplePS, "main", "ps_6_0"); + ID3D12PipelineStatePtr vertexSamplePSO_6_0 = + MakePSO().RootSig(vertexSampleSig).VS(vsblob).PS(psblob); + + vsblob = Compile(vertexSampleVS, "main", "vs_6_6"); + psblob = Compile(vertexSamplePS, "main", "ps_6_6"); + ID3D12PipelineStatePtr vertexSamplePSO_6_6 = + MakePSO().RootSig(vertexSampleSig).VS(vsblob).PS(psblob); // set the NULL descriptors UINT inc = dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); @@ -1202,6 +1256,56 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 ID3D12PipelineStatePtr bannedPSO = MakePSO().InputLayout().RootSig(bannedSig).VS(vsblob).PS(psblob); + const uint32_t renderDataSize = sizeof(float) * 22; + // Create resources for compute shader + const uint32_t computeDataStart = AlignUp(renderDataSize, 1024U); + ID3D12RootSignaturePtr sigCompute = MakeSig({ + uavParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0), + uavParam(D3D12_SHADER_VISIBILITY_ALL, 0, 1), + constParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0, 4), + tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 2, 1, 3), + }); + + const uint32_t countSMs = 2; + ID3DBlobPtr computeBlobs[countSMs]; + ID3D12PipelineStatePtr computePSOs[countSMs]; + std::string computeSMs[countSMs] = {"cs_6_0", "cs_6_6"}; + for(uint32_t i = 0; i < countSMs; ++i) + { + computeBlobs[i] = Compile(compute, "main", computeSMs[i], false); + computePSOs[i] = MakePSO().RootSig(sigCompute).CS(computeBlobs[i]); + } + + const uint32_t uavSize = 1024; + ID3D12ResourcePtr bufIn = MakeBuffer().Size(uavSize).UAV(); + ID3D12ResourcePtr bufOut = MakeBuffer().Size(uavSize).UAV(); + bufIn->SetName(L"bufIn"); + bufOut->SetName(L"bufOut"); + + D3D12_GPU_DESCRIPTOR_HANDLE bufInGPU = + MakeUAV(bufIn).Format(DXGI_FORMAT_R32G32B32A32_UINT).CreateGPU(computeDataStart); + D3D12_CPU_DESCRIPTOR_HANDLE bufInClearCPU = + MakeUAV(bufIn).Format(DXGI_FORMAT_R32G32B32A32_UINT).CreateClearCPU(computeDataStart); + D3D12_GPU_DESCRIPTOR_HANDLE bufOutGPU = + MakeUAV(bufOut).Format(DXGI_FORMAT_R32G32B32A32_UINT).CreateGPU(computeDataStart + 1); + D3D12_CPU_DESCRIPTOR_HANDLE bufOutClearCPU = + MakeUAV(bufOut).Format(DXGI_FORMAT_R32G32B32A32_UINT).CreateClearCPU(computeDataStart + 1); + + D3D12_GPU_VIRTUAL_ADDRESS bufInVA = bufIn->GetGPUVirtualAddress(); + D3D12_GPU_VIRTUAL_ADDRESS bufOutVA = bufOut->GetGPUVirtualAddress(); + + uint32_t bufInInitData[uavSize]; + uint32_t bufOutInitData[uavSize]; + for(uint32_t i = 0; i < uavSize; ++i) + { + bufInInitData[i] = 111 + i / 4; + bufOutInitData[i] = 222 + i / 4; + } + + D3D12_RECT uavClearRect = {}; + uavClearRect.right = uavSize; + uavClearRect.bottom = 1; + while(Running()) { ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer(); @@ -1215,13 +1319,18 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 setMarker(cmd, undefined_tests); - ID3D12PipelineStatePtr psos[2] = {pso_5_0, pso_5_1}; - float blitOffsets[2] = {0.0f, 4.0f}; - D3D12_RECT scissors[2] = {{0, 0, (int)texDim, 4}, {0, 4, (int)texDim, 8}}; - const char *markers[2] = {"sm_5_0", "sm_5_1"}; + ID3D12PipelineStatePtr psos[4] = {pso_5_0, pso_5_1, pso_6_0, pso_6_6}; + float blitOffsets[4] = {0.0f, 4.0f, 8.0f, 12.0f}; + D3D12_RECT scissors[4] = { + {0, 0, (int)texDim, 4}, + {0, 4, (int)texDim, 8}, + {0, 8, (int)texDim, 12}, + {0, 12, (int)texDim, 16}, + }; + const char *markers[4] = {"sm_5_0", "sm_5_1", "sm_6_0", "sm_6_6"}; - // Clear, draw, and blit to backbuffer twice - once for SM 5.0 and again for SM 5.1 - for(int i = 0; i < 2; ++i) + // Clear, draw, and blit to backbuffer twice - once for each SM 5.0, 5.1, 6.0, 6.6 + for(int i = 0; i < ARRAY_COUNT(psos); ++i) { OMSetRenderTargets(cmd, {fltRTV}, {}); ClearRenderTargetView(cmd, fltRTV, {0.2f, 0.2f, 0.2f, 1.0f}); @@ -1237,8 +1346,8 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 cmd->SetGraphicsRootDescriptorTable(3, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); cmd->SetGraphicsRootDescriptorTable(4, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); cmd->SetGraphicsRootUnorderedAccessView(5, rootDummy->GetGPUVirtualAddress()); - cmd->SetGraphicsRootShaderResourceView( - 6, rootStruct->GetGPUVirtualAddress() + sizeof(float) * 22); + cmd->SetGraphicsRootShaderResourceView(6, + rootStruct->GetGPUVirtualAddress() + renderDataSize); cmd->SetPipelineState(psos[i]); @@ -1298,10 +1407,22 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); cmd->SetGraphicsRootSignature(vertexSampleSig); - cmd->SetPipelineState(vertexSamplePSO); - cmd->SetGraphicsRootDescriptorTable(0, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); - setMarker(cmd, "VertexSample"); - cmd->DrawInstanced(4, 1, 0, 0); + + ID3D12PipelineStatePtr vertexSamplePSOs[3] = {vertexSamplePSO_5_0, vertexSamplePSO_6_0, + vertexSamplePSO_6_6}; + + const char *vs_markers[3] = { + "VertexSample sm_5_0", + "VertexSample sm_6_0", + "VertexSample sm_6_6", + }; + for(int i = 0; i < ARRAY_COUNT(vertexSamplePSOs); ++i) + { + cmd->SetPipelineState(vertexSamplePSOs[i]); + cmd->SetGraphicsRootDescriptorTable(0, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + setMarker(cmd, vs_markers[i]); + cmd->DrawInstanced(4, 1, 0, 0); + } setMarker(cmd, "BannedSig"); RSSetViewport(cmd, {60.0f, 60.0f, 10.0f, 10.0f, 0.0f, 1.0f}); @@ -1315,6 +1436,31 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0 FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); + pushMarker(cmd, "Compute"); + for(uint32_t i = 0; i < countSMs; ++i) + { + cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr()); + + cmd->ClearUnorderedAccessViewUint(bufInGPU, bufInClearCPU, bufIn, bufInInitData, 1, + &uavClearRect); + cmd->ClearUnorderedAccessViewUint(bufOutGPU, bufOutClearCPU, bufOut, bufOutInitData, 1, + &uavClearRect); + + cmd->SetComputeRootSignature(sigCompute); + cmd->SetComputeRootUnorderedAccessView(0, bufInVA); + cmd->SetComputeRootUnorderedAccessView(1, bufOutVA); + cmd->SetComputeRoot32BitConstant(2, 5, 0); + cmd->SetComputeRoot32BitConstant(2, 6, 1); + cmd->SetComputeRoot32BitConstant(2, 7, 2); + cmd->SetComputeRoot32BitConstant(2, 8, 3); + cmd->SetComputeRootDescriptorTable(3, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + + cmd->SetPipelineState(computePSOs[i]); + setMarker(cmd, computeSMs[i]); + cmd->Dispatch(3, 2, 1); + } + popMarker(cmd); + cmd->Close(); Submit({cmd}); Present(); diff --git a/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py b/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py index 960c357a9..efb4aef43 100644 --- a/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py +++ b/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py @@ -15,7 +15,7 @@ class D3D12_Shader_Debug_Zoo(rdtest.TestCase): failed = False - shaderModels = ["sm_5_0", "sm_5_1"] + shaderModels = ["sm_5_0", "sm_5_1", "sm_6_0", "sm_6_6"] for sm in range(len(shaderModels)): rdtest.log.begin_section(shaderModels[sm] + " tests") @@ -26,9 +26,28 @@ class D3D12_Shader_Debug_Zoo(rdtest.TestCase): pipe: rd.PipeState = self.controller.GetPipelineState() + if pipe.GetShaderReflection(rd.ShaderStage.Vertex).debugInfo.debuggable: + # Debug the vertex shader + instId = 10 + trace: rd.ShaderDebugTrace = self.controller.DebugVertex(0, instId, 0, 0) + cycles, variables = self.process_trace(trace) + output = self.find_output_source_var(trace, rd.ShaderBuiltin.Undefined, 3) + debugged = self.evaluate_source_var(output, variables) + actual = debugged.value.u32v[0] + expected = instId + if not rdtest.value_compare(actual, expected): + failed = True + rdtest.log.error( + f"Vertex shader TRIANGLE output did not match expectation {actual} != {expected}") + if not failed: + rdtest.log.success("Basic VS debugging was successful") + else: + rdtest.log.print(f"Ignoring undebuggable Vertex shader at {action.eventId}.") + if not pipe.GetShaderReflection(rd.ShaderStage.Pixel).debugInfo.debuggable: - rdtest.log.print("Skipping undebuggable shader at {}.".format(action.eventId)) - return + rdtest.log.print("Skipping undebuggable Pixel shader at {}.".format(action.eventId)) + rdtest.log.end_section(shaderModels[sm] + " tests") + continue # Loop over every test for test in range(action.numInstances): @@ -90,50 +109,57 @@ class D3D12_Shader_Debug_Zoo(rdtest.TestCase): rdtest.log.end_section("MSAA tests") - test_marker: rd.ActionDescription = self.find_action("VertexSample") - action = test_marker.next - self.controller.SetFrameEvent(action.eventId, False) - pipe: rd.PipeState = self.controller.GetPipelineState() + rdtest.log.begin_section("VertexSample tests") + shaderModels = ["sm_5_0", "sm_6_0", "sm_6_6"] + for sm in range(len(shaderModels)): + test_marker: rd.ActionDescription = self.find_action("VertexSample " + shaderModels[sm]) + action = test_marker.next + self.controller.SetFrameEvent(action.eventId, False) + pipe: rd.PipeState = self.controller.GetPipelineState() - # Debug the vertex shader - trace: rd.ShaderDebugTrace = self.controller.DebugVertex(0, 0, 0, 0) + if pipe.GetShaderReflection(rd.ShaderStage.Vertex).debugInfo.debuggable: + # Debug the vertex shader + trace: rd.ShaderDebugTrace = self.controller.DebugVertex(0, 0, 0, 0) + cycles, variables = self.process_trace(trace) + output = self.find_output_source_var(trace, rd.ShaderBuiltin.Undefined, 1) + debugged = self.evaluate_source_var(output, variables) - cycles, variables = self.process_trace(trace) + actual = debugged.value.f32v[0:4] + expected = [0.3, 0.5, 0.8, 1.0] + if not rdtest.value_compare(actual, expected): + failed = True + rdtest.log.error( + f"{shaderModels[sm]} Vertex shader color output did not match expectation {actual} != {expected}") - output = self.find_output_source_var(trace, rd.ShaderBuiltin.Undefined, 1) + if not failed: + rdtest.log.success(shaderModels[sm] + " VertexSample VS was debugged correctly") + else: + rdtest.log.print("Skipping undebuggable Vertex shader at {}.".format(action.eventId)) - debugged = self.evaluate_source_var(output, variables) + if pipe.GetShaderReflection(rd.ShaderStage.Pixel).debugInfo.debuggable: + # Debug the pixel shader + inputs = rd.DebugPixelInputs() + inputs.sample = 0 + trace: rd.ShaderDebugTrace = self.controller.DebugPixel(51, 51, inputs) + cycles, variables = self.process_trace(trace) + output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0) + debugged = self.evaluate_source_var(output, variables) - if not rdtest.value_compare(debugged.value.f32v[0:4], [0.3, 0.5, 0.8, 1.0]): - failed = True - rdtest.log.error( - "Vertex shader color output did not match expectation ({}). {}".format(str(debugged.value.f32v[0:4]), - str([0.3, 0.5, 0.8, 1.0]))) + # Validate the debug output result + try: + self.check_pixel_value(pipe.GetOutputTargets()[0].resource, 51, 51, debugged.value.f32v[0:4]) + except rdtest.TestFailureException as ex: + failed = True + rdtest.log.error("Vertex sample pixel shader output did not match. {}".format(str(ex))) - rdtest.log.success("VertexSample VS was debugged correctly") + rdtest.log.success("VertexSample PS was debugged correctly") + else: + rdtest.log.print("Skipping undebuggable Pixel shader at {}.".format(action.eventId)) - # Debug the pixel shader - inputs = rd.DebugPixelInputs() - inputs.sample = 0 - trace: rd.ShaderDebugTrace = self.controller.DebugPixel(51, 51, inputs) + if failed: + raise rdtest.TestFailureException("Some tests were not as expected") - cycles, variables = self.process_trace(trace) - - output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0) - - debugged = self.evaluate_source_var(output, variables) - - # Validate the debug output result - try: - self.check_pixel_value(pipe.GetOutputTargets()[0].resource, 51, 51, debugged.value.f32v[0:4]) - except rdtest.TestFailureException as ex: - failed = True - rdtest.log.error("Vertex sample pixel shader output did not match. {}".format(str(ex))) - - rdtest.log.success("VertexSample PS was debugged correctly") - - if failed: - raise rdtest.TestFailureException("Some tests were not as expected") + rdtest.log.end_section("VertexSample tests") test_marker: rd.ActionDescription = self.find_action("Banned") action = test_marker.next @@ -149,14 +175,14 @@ class D3D12_Shader_Debug_Zoo(rdtest.TestCase): debugged = self.evaluate_source_var(output, variables) - if not rdtest.value_compare(debugged.value.f32v[0:4], [-0.5, -0.5, 0.0, 1.0]): + actual = debugged.value.f32v[0:4] + expected = [-0.5, -0.5, 0.0, 1.0] + if not rdtest.value_compare(actual, expected): failed = True - rdtest.log.error( - "Banned signature vertex shader position did not match expectation ({}). {}".format( - str(debugged.value.f32v[0:4]), - str([-0.5, -0.5, 0.0, 1.0]))) + rdtest.log.error(f"Banned signature vertex shader position did not match expectation {actual} != {expected}") - rdtest.log.success("Banned signature VS was debugged correctly") + if not failed: + rdtest.log.success("Banned signature VS was debugged correctly") # Debug the pixel shader inputs = rd.DebugPixelInputs() @@ -178,6 +204,35 @@ class D3D12_Shader_Debug_Zoo(rdtest.TestCase): rdtest.log.success("Banned signature PS was debugged correctly") + csShaderModels = ["cs_6_0", "cs_6_6"] + for sm in range(len(csShaderModels)): + test = csShaderModels[sm] + section = test + " tests" + rdtest.log.begin_section(section) + + # Jump to the action + test_marker: rd.ActionDescription = self.find_action(test) + action = test_marker.next + self.controller.SetFrameEvent(action.eventId, False) + pipe: rd.PipeState = self.controller.GetPipelineState() + if not pipe.GetShaderReflection(rd.ShaderStage.Compute).debugInfo.debuggable: + rdtest.log.print("Skipping undebuggable shader at {}.".format(action.eventId)) + continue + + # Debug the shader + trace: rd.ShaderDebugTrace = self.controller.DebugThread([0,0,0], [0,0,0]) + cycles, variables = self.process_trace(trace) + # Check for non-zero cycles + # TODO: Check source variables have expected values (bit like output variables in Vertex and Pixel Shaders) + self.controller.FreeTrace(trace) + if cycles == 0: + rdtest.log.error("Shader debug cycle count was zero") + failed = True + continue + + rdtest.log.success("Test {} matched as expected".format(test)) + rdtest.log.end_section(section) + if failed: raise rdtest.TestFailureException("Some tests were not as expected")