mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
9c4a62397e
Compute tests were resetting "failed" to False
177 lines
7.9 KiB
Python
177 lines
7.9 KiB
Python
import renderdoc as rd
|
|
from typing import List
|
|
import rdtest
|
|
import struct
|
|
|
|
class VK_Shader_Debug_Zoo(rdtest.TestCase):
|
|
demos_test_name = 'VK_Shader_Debug_Zoo'
|
|
|
|
def check_capture(self):
|
|
if not self.controller.GetAPIProperties().shaderDebugging:
|
|
rdtest.log.success("Shader debugging not enabled, skipping test")
|
|
return
|
|
|
|
failed = False
|
|
|
|
for test_name in ["GLSL1 tests", "GLSL2 tests", "ASM tests"]:
|
|
rdtest.log.begin_section(test_name)
|
|
action = self.find_action(test_name)
|
|
for child in range(len(action.children)):
|
|
section = action.children[child]
|
|
self.controller.SetFrameEvent(section.eventId, False)
|
|
pipe: rd.PipeState = self.controller.GetPipelineState()
|
|
|
|
if not pipe.GetShaderReflection(rd.ShaderStage.Pixel).debugInfo.debuggable:
|
|
rdtest.log.print("Skipping undebuggable shader at {} in {}.".format(child, test_name))
|
|
return
|
|
|
|
for test in range(section.numInstances):
|
|
x = 4 * test + 1
|
|
y = 4 * child + 1
|
|
|
|
# Debug the shader
|
|
trace: rd.ShaderDebugTrace = self.controller.DebugPixel(x, y, rd.DebugPixelInputs())
|
|
|
|
if trace.debugger is None:
|
|
failed = True
|
|
rdtest.log.error("Test {} in sub-section {} did not debug at all".format(test, child))
|
|
self.controller.FreeTrace(trace)
|
|
continue
|
|
|
|
_, variables = self.process_trace(trace)
|
|
|
|
output: rd.SourceVariableMapping = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0)
|
|
|
|
debugged = self.evaluate_source_var(output, variables)
|
|
|
|
try:
|
|
self.check_pixel_value(pipe.GetOutputTargets()[0].resource, x, y, debugged.value.f32v[0:4])
|
|
except rdtest.TestFailureException as ex:
|
|
failed = True
|
|
rdtest.log.error("Test {} in sub-section {} did not match. {}".format(test, child, str(ex)))
|
|
continue
|
|
finally:
|
|
self.controller.FreeTrace(trace)
|
|
|
|
rdtest.log.success("Test {} in sub-section {} matched as expected".format(test, child))
|
|
rdtest.log.end_section(test_name)
|
|
|
|
test_name = "Disassembly Tests"
|
|
rdtest.log.begin_section(test_name)
|
|
|
|
action = self.find_action("ASM tests")
|
|
self.controller.SetFrameEvent(action.children[0].eventId, False)
|
|
pipe: rd.PipeState = self.controller.GetPipelineState()
|
|
refl: rd.ShaderReflection = pipe.GetShaderReflection(rd.ShaderStage.Pixel)
|
|
disasm = self.controller.DisassembleShader(pipe.GetGraphicsPipelineObject(), refl, "")
|
|
# Test for some expected strings in the disassembly
|
|
expectedStrings = []
|
|
# OpSwitch disassembly of 32-bit and 64-bit literals
|
|
expectedStrings.append("case 305419896:")
|
|
expectedStrings.append("case 4063516280:")
|
|
expectedStrings.append("case 1311768465173141112:")
|
|
expectedStrings.append("case 17452669529668998776:")
|
|
for exp in expectedStrings:
|
|
if exp not in disasm:
|
|
failed = True
|
|
rdtest.log.error("Failed to find `{}` in disassembly".format(exp))
|
|
|
|
rdtest.log.end_section(test_name)
|
|
|
|
# CS is 8x4x1
|
|
thread_checks = [
|
|
(0,0,0),
|
|
(1,1,0),
|
|
(2,2,0),
|
|
(3,3,0),
|
|
(4,2,0),
|
|
(5,1,0),
|
|
(6,0,0),
|
|
(7,1,0),
|
|
]
|
|
compute_dims = [a for a in self.find_action(
|
|
"Compute Tests").children if 'x' in a.customName]
|
|
for comp_dim in compute_dims:
|
|
section = f"Compute tests with {comp_dim.customName}"
|
|
rdtest.log.begin_section(section)
|
|
|
|
compute_tests = [
|
|
a for a in comp_dim.children if a.flags & rd.ActionFlags.Dispatch]
|
|
|
|
for test, action in enumerate(compute_tests):
|
|
self.controller.SetFrameEvent(action.eventId, False)
|
|
pipe = self.controller.GetPipelineState()
|
|
csrefl = pipe.GetShaderReflection(rd.ShaderStage.Compute)
|
|
if not csrefl.debugInfo.debuggable:
|
|
rdtest.log.print(f"Compute shader is undebuggable at {action.eventId} for {test}.")
|
|
failed = True
|
|
continue
|
|
|
|
rw = pipe.GetReadWriteResources(rd.ShaderStage.Compute)
|
|
if len(rw) != 1:
|
|
rdtest.log.error("Unexpected number of RW resources")
|
|
self.controller.FreeTrace(trace)
|
|
failed = True
|
|
continue
|
|
|
|
groupid = (1, 0, 0)
|
|
dim = csrefl.dispatchThreadsDimension
|
|
|
|
# Debug the shader
|
|
for threadid in thread_checks:
|
|
# each test writes up to 16k data, one vec4 per thread * up to 1024 threads
|
|
bufdata = self.controller.GetBufferData(
|
|
rw[0].descriptor.resource, test*16*1024, 16*1024)
|
|
try:
|
|
expectedValue = struct.unpack_from(
|
|
"4f", bufdata, 16*threadid[1]*dim[0] + 16*threadid[0])
|
|
except Exception as ex:
|
|
rdtest.log.error(f"Exception Test {test} failed {ex}")
|
|
failed = True
|
|
continue
|
|
|
|
# Debug the shader
|
|
trace: rd.ShaderDebugTrace = self.controller.DebugThread(groupid, threadid)
|
|
cycles, variables = self.process_trace(trace)
|
|
# Check for non-zero cycles
|
|
if cycles == 0:
|
|
rdtest.log.success(f"Test {test} Group:{groupid} Thread:{threadid} : Shader debug cycle count was zero")
|
|
self.controller.FreeTrace(trace)
|
|
failed = True
|
|
continue
|
|
|
|
# Find the source variable 'testResult' at the highest instruction index
|
|
name = 'testResult'
|
|
debugged = None
|
|
countInst = len(trace.instInfo)
|
|
for inst in range(countInst):
|
|
sourceVars = trace.instInfo[countInst-1-inst].sourceVars
|
|
try:
|
|
dataVars = [v for v in sourceVars if v.name == name]
|
|
if len(dataVars) == 0:
|
|
continue
|
|
debugged = self.evaluate_source_var(dataVars[0], variables)
|
|
except KeyError as ex:
|
|
continue
|
|
except rdtest.TestFailureException as ex:
|
|
continue
|
|
break
|
|
if debugged is None:
|
|
raise rdtest.TestFailureException(f"Couldn't find source variable {name} at {test}")
|
|
debuggedValue = list(debugged.value.f32v[0:4])
|
|
|
|
if not rdtest.value_compare(expectedValue, debuggedValue, eps=5.0E-06):
|
|
rdtest.log.error(f"Test {test} Group:{groupid} Thread:{threadid} EID:{action.eventId} failed {name} debugger {debuggedValue} doesn't match expected {expectedValue}")
|
|
self.controller.FreeTrace(trace)
|
|
failed = True
|
|
continue
|
|
|
|
rdtest.log.success(f"Test {test} Group:{groupid} Thread:{threadid} as expected")
|
|
|
|
rdtest.log.end_section(section)
|
|
|
|
if failed:
|
|
raise rdtest.TestFailureException("Some tests were not as expected")
|
|
|
|
rdtest.log.success("All tests matched")
|