From 031212e916715ef4dc095065ea91994d43ca32cd Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 11 Sep 2026 16:07:14 +0100 Subject: [PATCH] Use context helpers for vertex debugging --- util/test/rdtest/testcase.py | 98 +++++++++---------- .../tests/D3D12/D3D12_Shader_DebugData_Zoo.py | 77 +++++++-------- 2 files changed, 85 insertions(+), 90 deletions(-) diff --git a/util/test/rdtest/testcase.py b/util/test/rdtest/testcase.py index 38b2a19bb..afe39c750 100644 --- a/util/test/rdtest/testcase.py +++ b/util/test/rdtest/testcase.py @@ -646,74 +646,70 @@ class TestCase: ignore_uninit=False, name_retry: Callable[[str], str] | None = None ) -> Tuple[bool, str]: - trace = None try: - trace = self.controller.DebugVertex(vtx, inst, idx, max(0, view)) + with self.debug_vertex(vtx, inst, idx, max(0, view)) as debug: + ctx = f"vertex {vtx} (idx {idx}) instance {inst}" + if view >= 0: + ctx += f" view {view}" - ctx = f"vertex {vtx} (idx {idx}) instance {inst}" - if view >= 0: - ctx += f" view {view}" + if debug.trace.debugger is None: + raise TestFailureException(f"Couldn't debug {ctx}") - if trace.debugger is None: - raise TestFailureException(f"Couldn't debug {ctx}") + cycles, variables = self.process_trace(debug.trace) - cycles, variables = self.process_trace(trace) + postvs_vtx = vtx + if single_postvs: + postvs_vtx = 0 - postvs_vtx = vtx - if single_postvs: - postvs_vtx = 0 + for var in debug.trace.sourceVars: + if var.variables[0].type == rd.DebugVariableType.Variable and var.signatureIndex >= 0: + name = var.name - for var in trace.sourceVars: - if var.variables[0].type == rd.DebugVariableType.Variable and var.signatureIndex >= 0: - name = var.name + if name not in postvs[postvs_vtx].keys() and name_retry is not None: + name = name_retry(name) - if name not in postvs[postvs_vtx].keys() and name_retry is not None: - name = name_retry(name) + if name not in postvs[postvs_vtx].keys(): + raise TestFailureException(f"Don't have expected output for {name}") - if name not in postvs[postvs_vtx].keys(): - raise TestFailureException(f"Don't have expected output for {name}") + expect = postvs[postvs_vtx][name] + assert expect is not None + value = self.evaluate_source_var(var, variables) - expect = postvs[postvs_vtx][name] - assert expect is not None - value = self.evaluate_source_var(var, variables) + expect_cols = 1 + if util.is_vector(expect): + expect_cols = len(expect) + if expect_cols != value.columns: + raise TestFailureException( + f"Output {name} at {ctx} has different size ({value.columns} values) to expectation ({expect_cols} values)") - expect_cols = 1 - if util.is_vector(expect): - expect_cols = len(expect) - if expect_cols != value.columns: - raise TestFailureException( - f"Output {name} at {ctx} has different size ({value.columns} values) to expectation ({expect_cols} values)") + compType = rd.VarTypeCompType(value.type) + debugged: util.VectorValue = [] + if compType == rd.CompType.UInt: + debugged = list(value.value.u32v[0:value.columns]) + elif compType == rd.CompType.SInt: + debugged = list(value.value.s32v[0:value.columns]) + else: + debugged = list(value.value.f32v[0:value.columns]) - compType = rd.VarTypeCompType(value.type) - debugged: util.VectorValue = [] - if compType == rd.CompType.UInt: - debugged = list(value.value.u32v[0:value.columns]) - elif compType == rd.CompType.SInt: - debugged = list(value.value.s32v[0:value.columns]) - else: - debugged = list(value.value.f32v[0:value.columns]) + # For now, ignore debugged values that are uninitialised. This is an application bug but it causes false + # reports of problems + if ignore_uninit and value.columns > 1: + assert util.is_vector(expect) + for comp in range(4): + if value.value.u32v[comp] == 0xcccccccc: + debugged[comp] = expect[comp] - # For now, ignore debugged values that are uninitialised. This is an application bug but it causes false - # reports of problems - if ignore_uninit and value.columns > 1: - assert util.is_vector(expect) - for comp in range(4): - if value.value.u32v[comp] == 0xcccccccc: - debugged[comp] = expect[comp] + is_eq, diff_amt = util.value_compare_diff(expect, debugged, eps=5.0E-06) + if not is_eq: + raise TestFailureException( + f"Debugged value {name} at {ctx}: {debugged} doesn't exactly match postvs output {expect}. {diff_amt} difference") - is_eq, diff_amt = util.value_compare_diff(expect, debugged, eps=5.0E-06) - if not is_eq: - raise TestFailureException( - f"Debugged value {name} at {ctx}: {debugged} doesn't exactly match postvs output {expect}. {diff_amt} difference") - - log.success(f'Successfully debugged vertex {ctx} in {cycles} cycles') + log.success(f'Successfully debugged vertex {ctx} in {cycles} cycles') except TestFailureException as ex: if not fatal: return False, ex.message raise ex - finally: - if trace is not None: - self.controller.FreeTrace(trace) + return True, "" def run(self): diff --git a/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py b/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py index 7c493fb6a..5ba6db5eb 100644 --- a/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py +++ b/util/test/tests/D3D12/D3D12_Shader_DebugData_Zoo.py @@ -100,48 +100,47 @@ class D3D12_Shader_DebugData_Zoo(rdtest.TestCase): if pipe.GetShaderReflection(rd.ShaderStage.Vertex).debugInfo.debuggable: # Debug the vertex shader instId = 1 - trace = self.controller.DebugVertex(0, instId, 0, 0) - cycles, variables = self.process_trace(trace) - output = self.find_output_source_var(trace, rd.ShaderBuiltin.Undefined, 1) - assert output is not None - 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") - - # Look for MAT0 variable in the trace initial source variables - matched = True - varsToCheck: List[Tuple[str, str, rdtest.ScalarOrVectorValue]] = [] - 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 + with self.debug_vertex(0, instId, 0, 0) as debug: + cycles, variables = self.process_trace(debug.trace) + output = self.find_output_source_var(debug.trace, rd.ShaderBuiltin.Undefined, 1) + assert output is not None + 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 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 not failed: + rdtest.log.success("Basic VS debugging was successful") - self.controller.FreeTrace(trace) - if matched: - rdtest.log.success("VS MAT0 output source variable matched as expected") + # Look for MAT0 variable in the trace initial source variables + matched = True + varsToCheck: List[Tuple[str, str, rdtest.ScalarOrVectorValue]] = [] + 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(debug.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}") + + 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]}.")