From f858b2320f7a0bdfd45c14c175722f39e2ac3f3d Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Wed, 12 Nov 2025 04:51:09 +1300 Subject: [PATCH] Extend D3D12_Shader_DebugData_Zoo tests to include matrix Check matrix in the outputs from Vertex Shader Check matrix in the inputs to Pixel Shader Check matrix debug data source values from debugger trace --- .../d3d12/d3d12_shader_debugdata_zoo.cpp | 63 +++++++++++++ util/test/rdtest/testcase.py | 4 +- .../tests/D3D12/D3D12_Shader_DebugData_Zoo.py | 88 +++++++++++++++++-- 3 files changed, 148 insertions(+), 7 deletions(-) diff --git a/util/test/demos/d3d12/d3d12_shader_debugdata_zoo.cpp b/util/test/demos/d3d12/d3d12_shader_debugdata_zoo.cpp index a0f2bb328..3f07dc37b 100644 --- a/util/test/demos/d3d12/d3d12_shader_debugdata_zoo.cpp +++ b/util/test/demos/d3d12/d3d12_shader_debugdata_zoo.cpp @@ -61,6 +61,7 @@ struct v2f float4 pos : SV_POSITION; uint tri : TRIANGLE; uint intval : INTVAL; + row_major float3x4 mat : MAT; }; )EOSHADER"; @@ -76,6 +77,19 @@ v2f main(consts IN, uint tri : SV_InstanceID) OUT.tri = tri; OUT.intval = tri + 11; + OUT.mat._m00 = 1.0; + OUT.mat._m01 = 2.0; + OUT.mat._m02 = 3.0; + OUT.mat._m03 = 4.0; + OUT.mat._m10 = 5.0; + OUT.mat._m11 = 6.0; + OUT.mat._m12 = 7.0; + OUT.mat._m13 = 8.0; + OUT.mat._m20 = 9.0; + OUT.mat._m21 = 10.0; + OUT.mat._m22 = 11.0; + OUT.mat._m23 = 12.0; + return OUT; } @@ -91,6 +105,8 @@ TEST_DEBUG_TYPE(TYPE ## 1) \ TEST_DEBUG_TYPE(TYPE ## 2) \ TEST_DEBUG_TYPE(TYPE ## 3) \ TEST_DEBUG_TYPE(TYPE ## 4) +#define TEST_DEBUG_MATRIX23_TYPE(TYPE) \ +row_major TYPE ## 2x3 __test_ ## TYPE ## 23 = 0; #define USE_DEBUG_VECTOR_TYPE(TYPE) \ testResult.x += __test_ ## TYPE .x; \ @@ -99,12 +115,27 @@ TEST_DEBUG_TYPE(TYPE ## 4) testResult.xyz += __test_ ## TYPE ## 3 .xyz; \ testResult.xyzw += __test_ ## TYPE ## 4 .xyzw; +#define USE_DEBUG_MATRIX23_TYPE(TYPE) \ + testResult.xyz += __test_ ## TYPE ## 23[0] .xyz; \ + testResult.xyz += __test_ ## TYPE ## 23[1] .xyz; \ + #define TEST_DEBUG_VAR_SET(TYPE, VAR, VALUE) \ VAR = VALUE * __ONE; \ __test_ ## TYPE += VAR; #define TEST_DEBUG_VAR_DECLARE(TYPE, VAR, VALUE) TYPE VAR; TEST_DEBUG_VAR_SET(TYPE, VAR, VALUE) +#define TEST_DEBUG_VAR_DECLARE_MATRIX23(TYPE, VAR, VALUE) \ + row_major TYPE ## 2x3 VAR; \ + VAR = VALUE * __ONE; \ + __test_ ## TYPE ## 23 = VAR; \ + __test_ ## TYPE ## 23 ._m00 += VALUE * __ONE; \ + __test_ ## TYPE ## 23 ._m01 += VALUE * __TWO; \ + __test_ ## TYPE ## 23 ._m02 += VALUE * __THREE; \ + __test_ ## TYPE ## 23 ._m10 += VALUE * __FOUR; \ + __test_ ## TYPE ## 23 ._m11 += VALUE * __FIVE; \ + __test_ ## TYPE ## 23 ._m12 += VALUE * __SIX; \ + struct TestStruct { struct @@ -139,6 +170,7 @@ struct TestChild : TestParent TEST_DEBUG_VECTOR_TYPE(int); TEST_DEBUG_VECTOR_TYPE(float); + TEST_DEBUG_MATRIX23_TYPE(float); // TEST_DEBUG_VAR_START TEST_DEBUG_VAR_DECLARE(int, testIndex, TEST_INDEX) @@ -152,6 +184,7 @@ struct TestChild : TestParent TEST_DEBUG_VAR_SET(int2, testChild.i2, 2) TEST_DEBUG_VAR_SET(int3, testChild.i3, 3) TEST_DEBUG_VAR_SET(int4, testChild.i4, 4) + TEST_DEBUG_VAR_DECLARE_MATRIX23(float, fish, 7.0) // TEST_DEBUG_VAR_END if(testIndex == 0) @@ -185,6 +218,13 @@ struct TestChild : TestParent testResult.z = testChild.i3.y; testResult.w = testChild.i4.z; } + else if(testIndex == 6) + { + testResult.x = fish[0].x + fish[1].x; + testResult.y = fish[0].y + fish[1].y; + testResult.z = fish[0].z + fish[1].z; + testResult.w = 0.0; + } else { testResult = 0.4f; @@ -192,6 +232,7 @@ struct TestChild : TestParent USE_DEBUG_VECTOR_TYPE(int); USE_DEBUG_VECTOR_TYPE(float); + USE_DEBUG_MATRIX23_TYPE(float); )EOSHADER"; std::string pixel = R"EOSHADER( @@ -205,6 +246,23 @@ struct TestChild : TestParent float4 main(v2f IN) : SV_Target0 { int __ONE = floor((IN.intval - 11)/(IN.tri+1.0e-6f)) + 1; + __ONE += floor(abs(IN.pos.x / 1.0e6f)); + __ONE += floor(abs(IN.pos.y / 1.0e6f)); + __ONE += floor(abs(IN.pos.z / 1.0e6f)); + __ONE += floor(abs(IN.pos.w / 1.0e6f)); + for (int i = 0; i < 3; i++) + { + __ONE += floor(abs(IN.mat[i].x / 1.0e6f)); + __ONE += floor(abs(IN.mat[i].y / 1.0e6f)); + __ONE += floor(abs(IN.mat[i].z / 1.0e6f)); + __ONE += floor(abs(IN.mat[i].w / 1.0e6f)); + } + int __TWO = __ONE + 1; + int __THREE = __TWO + 1; + int __FOUR = __THREE + 1; + int __FIVE = __FOUR + 1; + int __SIX = __FIVE + 1; + )EOSHADER" + testsBody + R"EOSHADER( @@ -232,6 +290,11 @@ void SetOutput(uint index, float4 data) void main(int inTestIndex: SV_GroupID) { int __ONE = floor(inTestIndex/(inTestIndex+1.0e-6f)) + 1; + int __TWO = __ONE + 1; + int __THREE = __TWO + 1; + int __FOUR = __THREE + 1; + int __FIVE = __FOUR + 1; + int __SIX = __FIVE + 1; )EOSHADER" + testsBody + R"EOSHADER( diff --git a/util/test/rdtest/testcase.py b/util/test/rdtest/testcase.py index ff39dc4f8..863ab7803 100644 --- a/util/test/rdtest/testcase.py +++ b/util/test/rdtest/testcase.py @@ -407,7 +407,7 @@ class TestCase: def get_source_shader_var_value(self, sourceVars: List[rd.SourceVariableMapping], name, varType, debuggerVars): sourceVar = [v for v in sourceVars if v.name == name] if len(sourceVar) != 1: - raise TestFailureException(f"Couldn't find source variable {name} {varType}") + raise TestFailureException(f"Couldn't find source variable {name} type:{varType}") scalarType, countElems = self.parse_shader_var_type(varType) @@ -417,7 +417,7 @@ class TestCase: elif scalarType == 'int': return list(debugged.value.s32v[0:countElems]) else: - raise TestFailureException(f"Unhandled scalarType {scalarType} {varType}") + raise TestFailureException(f"Unhandled scalarType {scalarType} type:{varType}") return None def check_task_data(self, task_ref, task_data): diff --git a/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py b/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py index d252cec63..1c0ae119a 100644 --- a/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py +++ b/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py @@ -14,6 +14,7 @@ class D3D12_Shader_DebugData_Zoo(rdtest.TestCase): TEST_DEBUG_VAR_DECLARE(int2, jake, 5) TEST_DEBUG_VAR_DECLARE(float1, bob, 3.0) TEST_DEBUG_VAR_USE(int4, testStruct.anon.a, 1) + TEST_DEBUG_VAR_DECLARE_MATRIX23(float, fish, 7.2) // TEST_DEBUG_VAR_END ''' varsToCheck = [] @@ -37,6 +38,12 @@ class D3D12_Shader_DebugData_Zoo(rdtest.TestCase): name = toks[1].strip() valString = toks[2].split(')')[0].strip() scalarType, countElems = self.parse_shader_var_type(type) + isMatrix23 = line.startswith('TEST_DEBUG_VAR_DECLARE_MATRIX23') + if isMatrix23: + rows = 2 + columns = 3 + countElems = columns # each row is its own variable + if valString == 'TEST_INDEX': value = test elif valString == 'TEST_RESULT': @@ -50,8 +57,13 @@ class D3D12_Shader_DebugData_Zoo(rdtest.TestCase): raise rdtest.TestFailureException(f"Unhandled scalarType {scalarType} {type}") value = [scalarVal] * countElems - var = (name, type, value) - varsToCheck.append(var) + if not isMatrix23: + var = (name, type, value) + varsToCheck.append(var) + else: + for row in range(rows): + var = (f"{name}.row{row}", f"{type}3", value) + varsToCheck.append(var) if not foundStart or not foundEnd: raise rdtest.TestFailureException("Couldn't find TEST_DEBUG_VAR_START and TEST_DEBUG_VAR_END") @@ -89,15 +101,44 @@ class D3D12_Shader_DebugData_Zoo(rdtest.TestCase): cycles, variables = self.process_trace(trace) output = self.find_output_source_var(trace, rd.ShaderBuiltin.Undefined, 1) debugged = self.evaluate_source_var(output, variables) - self.controller.FreeTrace(trace) 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") + + # Look for MAT0 variable in the trace initial source variables + matched = True + varsToCheck = [] + varsToCheck.append((f"MAT0[0]", "float4", [1.0, 2.0, 3.0, 4.0])) + varsToCheck.append((f"MAT0[1]", "float4", [5.0, 6.0, 7.0, 8.0])) + varsToCheck.append((f"MAT0[2]", "float4", [9.0, 10.0, 11.0, 12.0])) + for name, varType, expectedValue in varsToCheck: + debuggedValue = None + try: + debuggedValue = self.get_source_shader_var_value(trace.sourceVars, name, varType, variables) + except KeyError as ex: + matched = False + failed = True + except rdtest.TestFailureException as ex: + matched = False + failed = True + + if debuggedValue is None: + raise rdtest.TestFailureException(f"Couldn't find source variable {name} type:{varType}") + if not rdtest.value_compare(expectedValue, debuggedValue): + matched = False + failed = True + rdtest.log.error(f"'{name}' {varType} debugger {debuggedValue} doesn't match expected {expectedValue}") + + self.controller.FreeTrace(trace) + if matched: + rdtest.log.success("VS MAT0 output source variable matched as expected") + else: rdtest.log.print(f"Ignoring undebuggable Vertex shader at {action.eventId} for {shaderModels[sm]}.") @@ -137,11 +178,48 @@ class D3D12_Shader_DebugData_Zoo(rdtest.TestCase): continue break if debuggedValue is None: - raise rdtest.TestFailureException(f"Couldn't find source variable {name} {varType}") + raise rdtest.TestFailureException(f"Couldn't find source variable {name} type:{varType}") if not rdtest.value_compare(expectedValue, debuggedValue): raise rdtest.TestFailureException(f"'{name}' {varType} debugger {debuggedValue} doesn't match expected {expectedValue}") + rdtest.log.success(f"{len(varsToCheck)} source variables matched as expected") + # Look for _IN.MAT0 variable in the trace input variables + name = "_IN" + inVar = [v for v in trace.inputs if v.name == name] + if len(inVar) != 1: + raise rdtest.TestFailureException(f"Couldn't find source variable {name} type:{varType}") + name = "MAT0" + inVar = [v for v in inVar[0].members if v.name == name] + if len(inVar) != 1: + raise rdtest.TestFailureException(f"Couldn't find source variable {name} type:{varType}") + + matched = True + varsToCheck = [] + varsToCheck.append((f"[0]", "float4", [1.0, 2.0, 3.0, 4.0])) + varsToCheck.append((f"[1]", "float4", [5.0, 6.0, 7.0, 8.0])) + varsToCheck.append((f"[2]", "float4", [9.0, 10.0, 11.0, 12.0])) + for name, varType, expectedValue in varsToCheck: + debuggedValue = None + for v in inVar[0].members: + if v.name == name: + try: + debuggedValue = v.value.f32v[0:len(expectedValue)] + except rdtest.TestFailureException as ex: + matched = False + failed = True + break + + if debuggedValue is None: + raise rdtest.TestFailureException(f"Couldn't find source variable {name} type:{varType}") + if not rdtest.value_compare(expectedValue, debuggedValue): + matched = False + failed = True + rdtest.log.error(f"'{name}' {varType} debugger {debuggedValue} doesn't match expected {expectedValue}") + + if matched: + rdtest.log.success("PS MAT0 input source variable matched as expected") + except rdtest.TestFailureException as ex: rdtest.log.error(f"Test {test} failed {ex}") failed = True @@ -208,7 +286,7 @@ class D3D12_Shader_DebugData_Zoo(rdtest.TestCase): continue break if debuggedValue is None: - raise rdtest.TestFailureException(f"Couldn't find source variable {name} {varType}") + raise rdtest.TestFailureException(f"Couldn't find source variable {name} type:{varType}") if not rdtest.value_compare(expectedValue, debuggedValue): raise rdtest.TestFailureException(f"'{name}' {varType} debugger {debuggedValue} doesn't match expected {expectedValue}") rdtest.log.success(f"{len(varsToCheck)} source variables matched as expected")