From dbbd9ba010d778a13a1f1a6a0b99fc4c093dc2d4 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Mon, 17 Nov 2025 05:38:12 +1300 Subject: [PATCH] Added MSAA tests for SM6.0 and SM6. Disabled in the python because the RenderDoc does not currently support DXIL debugging of MSAA instructions or SV_Barycentrics --- .../demos/d3d12/d3d12_shader_debug_zoo.cpp | 77 +++++++++++++++++-- .../tests/D3D12/D3D12_Shader_Debug_Zoo.py | 65 +++++++++------- 2 files changed, 111 insertions(+), 31 deletions(-) diff --git a/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp b/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp index 903ee7c7a..fbc1cfece 100644 --- a/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp +++ b/util/test/demos/d3d12/d3d12_shader_debug_zoo.cpp @@ -1133,6 +1133,37 @@ 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 msaaPixel61 = R"EOSHADER( + +struct v2f +{ + float4 pos : SV_POSITION; + float4 col : COLOR0; + float2 uv : TEXCOORD0; +}; + +float4 main(v2f IN, uint samp : SV_SampleIndex, float3 bary : SV_Barycentrics) : SV_Target0 +{ + float2 uvCentroid = EvaluateAttributeCentroid(IN.uv); + float2 uvSamp0 = EvaluateAttributeAtSample(IN.uv, 0) - IN.uv; + float2 uvSampThis = EvaluateAttributeAtSample(IN.uv, samp) - IN.uv; + float2 uvOffset = EvaluateAttributeSnapped(IN.uv, int2(1, 1)); + + float x = (uvCentroid.x + uvCentroid.y) * 0.5f; + float y = (uvSamp0.x + uvSamp0.y) * 0.5f; + float z = (uvSampThis.x + uvSampThis.y) * 0.5f; + float w = (uvOffset.x + uvOffset.y) * 0.5f; + w += x * bary.x + y * bary.y + z * bary.z; + + // Test sampleinfo with a MSAA rasterizer + uint numSamples = GetRenderTargetSampleCount(); + float2 pos = GetRenderTargetSamplePosition(samp); + + return float4(x + pos.x, y + pos.y, z + (float)numSamples, w); +} + )EOSHADER"; std::string compute = R"EOSHADER( @@ -1245,6 +1276,7 @@ void main(int3 inTestIndex : SV_GroupID) return 3; bool supportSM60 = (m_HighestShaderModel >= D3D_SHADER_MODEL_6_0) && m_DXILSupport; + bool supportSM61 = (m_HighestShaderModel >= D3D_SHADER_MODEL_6_1) && m_DXILSupport; bool supportSM62 = (m_HighestShaderModel >= D3D_SHADER_MODEL_6_2) && m_DXILSupport; bool supportSM66 = (m_HighestShaderModel >= D3D_SHADER_MODEL_6_6) && m_DXILSupport; TEST_ASSERT(!supportSM62 || supportSM60, "SM 6.2 requires SM 6.0 support"); @@ -1860,6 +1892,30 @@ void main(int3 inTestIndex : SV_GroupID) .PS(psmsaablob) .SampleCount(4) .RTVs({DXGI_FORMAT_R32G32B32A32_FLOAT}); + + ID3D12PipelineStatePtr msaaPSOs[3] = {psomsaa, NULL}; + if(supportSM60) + { + msaaPSOs[1] = MakePSO() + .RootSig(sigmsaa) + .InputLayout() + .VS(Compile(D3DDefaultVertex, "main", "vs_6_0")) + .PS(Compile(msaaPixel, "main", "ps_6_0")) + .SampleCount(4) + .RTVs({DXGI_FORMAT_R32G32B32A32_FLOAT}); + + if(supportSM61) + { + msaaPSOs[2] = MakePSO() + .RootSig(sigmsaa) + .InputLayout() + .VS(Compile(D3DDefaultVertex, "main", "vs_6_1")) + .PS(Compile(msaaPixel61, "main", "ps_6_1")) + .SampleCount(4) + .RTVs({DXGI_FORMAT_R32G32B32A32_FLOAT}); + } + } + ID3D12ResourcePtr vbmsaa = MakeBuffer().Data(DefaultTri); ID3D12ResourcePtr msaaTex = MakeTexture(DXGI_FORMAT_R32G32B32A32_FLOAT, 8, 8) @@ -2135,14 +2191,25 @@ void main(int3 inTestIndex : SV_GroupID) IASetVertexBuffer(cmd, vbmsaa, sizeof(DefaultA2V), 0); cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmd->SetGraphicsRootSignature(sigmsaa); - cmd->SetPipelineState(psomsaa); RSSetViewport(cmd, {0.0f, 0.0f, 8.0f, 8.0f, 0.0f, 1.0f}); RSSetScissorRect(cmd, {0, 0, 8, 8}); - // Add a marker so we can easily locate this draw - setMarker(cmd, "MSAA"); - cmd->DrawInstanced(3, 1, 0, 0); + size_t countMSAAPasses = supportSM60 ? (supportSM61 ? 3 : 2) : 1; + TEST_ASSERT(countMSAAPasses <= ARRAY_COUNT(msaaPSOs), "More MSAA passes than psos"); + const char *msaa_markers[3] = { + "MSAA sm_5_0", + "MSAA sm_6_0", + "MSAA sm_6_1", + }; + for(int i = 0; i < countMSAAPasses; ++i) + { + cmd->SetGraphicsRootSignature(sigmsaa); + cmd->SetPipelineState(msaaPSOs[i]); + + // Add a marker so we can easily locate this draw + setMarker(cmd, msaa_markers[i]); + cmd->DrawInstanced(3, 1, 0, 0); + } OMSetRenderTargets(cmd, {fltRTV}, {}); ClearRenderTargetView(cmd, fltRTV, {0.3f, 0.5f, 0.8f, 1.0f}); diff --git a/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py b/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py index c67651309..af036ef91 100644 --- a/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py +++ b/util/test/tests/D3D12/D3D12_Shader_Debug_Zoo.py @@ -90,37 +90,50 @@ class D3D12_Shader_Debug_Zoo(rdtest.TestCase): rdtest.log.end_section(sectionName) rdtest.log.begin_section("MSAA tests") - test_marker: rd.ActionDescription = self.find_action("MSAA") - action = test_marker.next - self.controller.SetFrameEvent(action.eventId, False) - pipe: rd.PipeState = self.controller.GetPipelineState() - for (x,y) in [(4, 4), (4, 5), (3, 4), (3, 5)]: - for test in range(4): - # Debug the shader - inputs = rd.DebugPixelInputs() - inputs.sample = test - trace: rd.ShaderDebugTrace = self.controller.DebugPixel(x, y, inputs) - # Validate that the correct sample index was debugged - sampRegister = self.find_input_source_var(trace, rd.ShaderBuiltin.MSAASampleIndex) - sampInput = [var for var in trace.inputs if var.name == sampRegister.variables[0].name][0] - if sampInput.value.u32v[0] != test: - rdtest.log.error("Test {} did not pick the correct sample.".format(test)) + # Enable MSAA tests when DXIL shader debugger supports MSAA instructions and SV_Barycentrics + msaaMarkers = [ + "MSAA sm_5_0", + "MSAA sm_6_0", + "MSAA sm_6_1", + ] + msaaMarkers = [ + "MSAA sm_5_0", + ] + for marker in msaaMarkers: + rdtest.log.begin_section(marker) + test_marker: rd.ActionDescription = self.find_action(marker) + action = test_marker.next + self.controller.SetFrameEvent(action.eventId, False) + pipe: rd.PipeState = self.controller.GetPipelineState() + for (x,y) in [(4, 4), (4, 5), (3, 4), (3, 5)]: + for test in range(4): + # Debug the shader + inputs = rd.DebugPixelInputs() + inputs.sample = test + trace: rd.ShaderDebugTrace = self.controller.DebugPixel(x, y, inputs) - cycles, variables = self.process_trace(trace) + # Validate that the correct sample index was debugged + sampRegister = self.find_input_source_var(trace, rd.ShaderBuiltin.MSAASampleIndex) + sampInput = [var for var in trace.inputs if var.name == sampRegister.variables[0].name][0] + if sampInput.value.u32v[0] != test: + rdtest.log.error("Test {} did not pick the correct sample.".format(test)) - output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0) + cycles, variables = self.process_trace(trace) - debugged = self.evaluate_source_var(output, variables) - self.controller.FreeTrace(trace) + output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0) - # Validate the debug output result - try: - self.check_pixel_value(pipe.GetOutputTargets()[0].resource, x, y, debugged.value.f32v[0:4], sub=rd.Subresource(0, 0, test)) - except rdtest.TestFailureException as ex: - failed = True - rdtest.log.error("Test {} did not match. {}".format(test, str(ex))) - continue + debugged = self.evaluate_source_var(output, variables) + self.controller.FreeTrace(trace) + + # Validate the debug output result + try: + self.check_pixel_value(pipe.GetOutputTargets()[0].resource, x, y, debugged.value.f32v[0:4], sub=rd.Subresource(0, 0, test)) + except rdtest.TestFailureException as ex: + failed = True + rdtest.log.error("Test {} did not match. {}".format(test, str(ex))) + + rdtest.log.end_section(marker) rdtest.log.end_section("MSAA tests")