mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Unified Subgroup_Zoo VK and D3D12 python
Improved test failure reporting
This commit is contained in:
@@ -9,3 +9,4 @@ from .shared.Draw_Zoo import *
|
||||
from .shared.Overlay_Test import *
|
||||
from .shared.Buffer_Truncation import *
|
||||
from .shared.Discard_Zoo import *
|
||||
from .shared.Subgroup_Zoo import *
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
import renderdoc as rd
|
||||
import struct
|
||||
import rdtest
|
||||
|
||||
# Not a real test, re-used by API-specific tests
|
||||
class Subgroup_Zoo(rdtest.TestCase):
|
||||
internal = True
|
||||
demos_test_name = None
|
||||
|
||||
def check_support(self, **kwargs):
|
||||
# Only allow this if explicitly run
|
||||
if kwargs['test_include'] == self.demos_test_name:
|
||||
return True, ''
|
||||
return False, 'Disabled test'
|
||||
|
||||
def check_capture(self):
|
||||
graphics_tests = [a for a in self.find_action(
|
||||
"Graphics Tests").children if a.flags & rd.ActionFlags.Drawcall]
|
||||
compute_dims = [a for a in self.find_action(
|
||||
"Compute Tests").children if 'x' in a.customName]
|
||||
|
||||
rdtest.log.begin_section("Graphics tests")
|
||||
|
||||
# instances to check in instanced draws
|
||||
inst_checks = [0, 1, 5, 10]
|
||||
# pixels to check
|
||||
pixel_checks = [
|
||||
# top quad
|
||||
(0, 0), (1, 0), (0, 1), (1, 1),
|
||||
# middle quad (away from triangle border)
|
||||
(64, 56), (65, 56), (64, 57), (65, 57),
|
||||
# middle quad (on triangle border)
|
||||
(64, 64), (65, 64), (64, 65), (65, 65),
|
||||
# middle quad on other triangle
|
||||
(56, 64), (57, 64), (56, 65), (57, 65),
|
||||
]
|
||||
# threads to check. largest dimension only (all small dim checked)
|
||||
thread_checks = [
|
||||
# first few
|
||||
0, 1, 2,
|
||||
# near end of 32-subgroup and boundary
|
||||
30, 31, 32,
|
||||
# near end of 64-subgroup and boundary
|
||||
62, 63, 64,
|
||||
# near end of 64-subgroup and boundary
|
||||
62, 63, 64,
|
||||
# large values spaced out with one near the end of our unaligned size
|
||||
100, 110, 120, 140, 149, 150, 160, 200, 250,
|
||||
]
|
||||
clear_col = (123456.0, 789.0, 101112.0, 0.0)
|
||||
|
||||
overallFailed = False
|
||||
for idx, action in enumerate(graphics_tests):
|
||||
failed = False
|
||||
self.controller.SetFrameEvent(action.eventId, False)
|
||||
|
||||
pipe = self.controller.GetPipelineState()
|
||||
|
||||
# check vertex output for every vertex
|
||||
for inst in [inst for inst in inst_checks if inst < action.numInstances]:
|
||||
for view in range(pipe.MultiviewBroadcastCount()):
|
||||
|
||||
postvs = self.get_postvs(
|
||||
action, rd.MeshDataStage.VSOut, first_index=0, num_indices=action.numIndices, instance=inst)
|
||||
|
||||
for vtx in range(action.numIndices):
|
||||
trace = self.controller.DebugVertex(
|
||||
vtx, inst, vtx, view)
|
||||
|
||||
if trace.debugger is None:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} got no debug result at {vtx} inst {inst} view {view}")
|
||||
failed = True
|
||||
return
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
for var in trace.sourceVars:
|
||||
if var.name == 'vertdata':
|
||||
name = var.name
|
||||
|
||||
if var.name not in postvs[vtx].keys():
|
||||
rdtest.log.error(
|
||||
f"Don't have expected output for {var.name}")
|
||||
failed = True
|
||||
continue
|
||||
|
||||
real = postvs[vtx][name]
|
||||
debugged = self.evaluate_source_var(
|
||||
var, variables)
|
||||
|
||||
if debugged.columns != 4 or len(real) != 4:
|
||||
rdtest.log.error(
|
||||
f"Vertex output is not the right size ({len(real)} vs {debugged.columns})")
|
||||
failed = True
|
||||
continue
|
||||
|
||||
if not rdtest.value_compare(real, debugged.value.f32v[0:4], eps=5.0E-06):
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} debugged vertex value {debugged.value.f32v[0:4]} at {vtx} instance {inst} view {view} does not match output {real}")
|
||||
failed = True
|
||||
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
# check some assorted pixel outputs
|
||||
target = pipe.GetOutputTargets()[0].resource
|
||||
|
||||
for pixel in pixel_checks:
|
||||
for view in range(pipe.MultiviewBroadcastCount()):
|
||||
x, y = pixel
|
||||
|
||||
picked = self.controller.PickPixel(
|
||||
target, x, y, rd.Subresource(0, 0, 0), rd.CompType.Float)
|
||||
|
||||
real = picked.floatValue
|
||||
|
||||
# silently skip pixels that weren't written to
|
||||
if real == clear_col:
|
||||
continue
|
||||
|
||||
inputs = rd.DebugPixelInputs()
|
||||
inputs.sample = 0
|
||||
inputs.primitive = rd.ReplayController.NoPreference
|
||||
inputs.view = view
|
||||
trace = self.controller.DebugPixel(x, y, inputs)
|
||||
|
||||
if trace.debugger is None:
|
||||
self.controller.FreeTrace(trace)
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} got no debug result at {x},{y}")
|
||||
failed = True
|
||||
continue
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
output_sourcevar = self.find_output_source_var(
|
||||
trace, rd.ShaderBuiltin.ColorOutput, 0)
|
||||
|
||||
if output_sourcevar is None:
|
||||
rdtest.log.error("No output variable found")
|
||||
failed = True
|
||||
continue
|
||||
|
||||
debugged = self.evaluate_source_var(
|
||||
output_sourcevar, variables)
|
||||
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
debuggedValue = list(debugged.value.f32v[0:4])
|
||||
|
||||
if not rdtest.value_compare(real, debuggedValue, eps=5.0E-06):
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} debugged pixel value {debuggedValue} at {x},{y} in {view} does not match output {real}")
|
||||
failed = True
|
||||
|
||||
overallFailed |= failed
|
||||
if not failed:
|
||||
rdtest.log.success(f"Test {idx} successful")
|
||||
else:
|
||||
rdtest.log.error(f"Test {idx} failed")
|
||||
|
||||
rdtest.log.end_section("Graphics tests")
|
||||
|
||||
for comp_dim in compute_dims:
|
||||
rdtest.log.begin_section(
|
||||
f"Compute tests with {comp_dim.customName} workgroup")
|
||||
|
||||
compute_tests = [
|
||||
a for a in comp_dim.children if a.flags & rd.ActionFlags.Dispatch]
|
||||
|
||||
for test, action in enumerate(compute_tests):
|
||||
failed = False
|
||||
self.controller.SetFrameEvent(action.eventId, False)
|
||||
|
||||
pipe = self.controller.GetPipelineState()
|
||||
csrefl = pipe.GetShaderReflection(rd.ShaderStage.Compute)
|
||||
|
||||
dim = csrefl.dispatchThreadsDimension
|
||||
|
||||
rw = pipe.GetReadWriteResources(rd.ShaderStage.Compute)
|
||||
|
||||
if len(rw) != 1:
|
||||
rdtest.log.error("Unexpected number of RW resources")
|
||||
continue
|
||||
|
||||
# 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)
|
||||
|
||||
for t in thread_checks:
|
||||
xrange = 1
|
||||
yrange = dim[1]
|
||||
xbase = t
|
||||
ybase = 0
|
||||
|
||||
# vertical orientation
|
||||
if dim[1] > dim[0]:
|
||||
xrange = dim[0]
|
||||
yrange = 1
|
||||
xbase = 0
|
||||
ybase = t
|
||||
|
||||
for x in range(xbase, xbase+xrange):
|
||||
for y in range(ybase, ybase+yrange):
|
||||
z = 0
|
||||
|
||||
if x >= dim[0] or y >= dim[1]:
|
||||
continue
|
||||
|
||||
try:
|
||||
real = struct.unpack_from(
|
||||
"4f", bufdata, 16*y*dim[0] + 16*x)
|
||||
|
||||
trace = self.controller.DebugThread(
|
||||
(0, 0, 0), (x, y, z))
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
if trace.debugger is None:
|
||||
raise rdtest.TestFailureException(f"Test {test} at {action.eventId} got no debug result at {x},{y},{z}")
|
||||
|
||||
# Find the source variable 'data' at the highest instruction index
|
||||
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 == 'data']
|
||||
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}")
|
||||
|
||||
debuggedValue = list(debugged.value.f32v[0:4])
|
||||
|
||||
if not rdtest.value_compare(real, debuggedValue, eps=5.0E-06):
|
||||
raise rdtest.TestFailureException(f"EID:{action.eventId} TID:{x},{y},{z} debugged thread value {debuggedValue} does not match output {real}")
|
||||
|
||||
except rdtest.TestFailureException as ex:
|
||||
rdtest.log.error(f"Test {test} failed {ex}")
|
||||
failed = True
|
||||
continue
|
||||
finally:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
overallFailed |= failed
|
||||
if not failed:
|
||||
rdtest.log.success(f"Test {test} successful")
|
||||
else:
|
||||
rdtest.log.error(f"Test {test} failed")
|
||||
|
||||
rdtest.log.end_section(
|
||||
f"Compute tests with {comp_dim.customName} workgroup")
|
||||
|
||||
if overallFailed:
|
||||
raise rdtest.TestFailureException("Some tests were not as expected")
|
||||
@@ -1,233 +1,5 @@
|
||||
import renderdoc as rd
|
||||
import struct
|
||||
import rdtest
|
||||
|
||||
|
||||
class D3D12_Subgroup_Zoo(rdtest.TestCase):
|
||||
class D3D12_Subgroup_Zoo(rdtest.Subgroup_Zoo):
|
||||
demos_test_name = 'D3D12_Subgroup_Zoo'
|
||||
|
||||
def check_support(self, **kwargs):
|
||||
# Only allow this if explicitly run
|
||||
if kwargs['test_include'] == 'D3D12_Subgroup_Zoo':
|
||||
return True, ''
|
||||
return False, 'Disabled test'
|
||||
|
||||
def check_capture(self):
|
||||
graphics_tests = [a for a in self.find_action(
|
||||
"Graphics Tests").children if a.flags & rd.ActionFlags.Drawcall]
|
||||
compute_dims = [a for a in self.find_action(
|
||||
"Compute Tests").children if 'x' in a.customName]
|
||||
|
||||
rdtest.log.begin_section("Graphics tests")
|
||||
|
||||
# instances to check in instanced draws
|
||||
inst_checks = [0, 1, 5, 10]
|
||||
# pixels to check
|
||||
pixel_checks = [
|
||||
# top quad
|
||||
(0, 0), (1, 0), (0, 1), (1, 1),
|
||||
# middle quad (away from triangle border)
|
||||
(64, 56), (65, 56), (64, 57), (65, 57),
|
||||
# middle quad (on triangle border)
|
||||
(64, 64), (65, 64), (64, 65), (65, 65),
|
||||
# middle quad on other triangle
|
||||
(56, 64), (57, 64), (56, 65), (57, 65),
|
||||
]
|
||||
# threads to check. largest dimension only (all small dim checked)
|
||||
thread_checks = [
|
||||
# first few
|
||||
0, 1, 2,
|
||||
# near end of 32-subgroup and boundary
|
||||
30, 31, 32,
|
||||
# near end of 64-subgroup and boundary
|
||||
62, 63, 64,
|
||||
# near end of 64-subgroup and boundary
|
||||
62, 63, 64,
|
||||
# large values spaced out with one near the end of our unaligned size
|
||||
100, 110, 120, 140, 149, 150, 160, 200, 250,
|
||||
]
|
||||
clear_col = (123456.0, 789.0, 101112.0, 0.0)
|
||||
|
||||
for idx, action in enumerate(graphics_tests):
|
||||
self.controller.SetFrameEvent(action.eventId, False)
|
||||
|
||||
pipe = self.controller.GetPipelineState()
|
||||
|
||||
# check vertex output for every vertex
|
||||
for inst in [inst for inst in inst_checks if inst < action.numInstances]:
|
||||
for view in range(pipe.MultiviewBroadcastCount()):
|
||||
|
||||
postvs = self.get_postvs(
|
||||
action, rd.MeshDataStage.VSOut, first_index=0, num_indices=action.numIndices, instance=inst)
|
||||
|
||||
for vtx in range(action.numIndices):
|
||||
trace = self.controller.DebugVertex(
|
||||
vtx, inst, vtx, view)
|
||||
|
||||
if trace.debugger is None:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} got no debug result at {vtx} inst {inst} view {view}")
|
||||
return
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
for var in trace.sourceVars:
|
||||
if var.name == 'vertdata':
|
||||
name = var.name
|
||||
|
||||
if var.name not in postvs[vtx].keys():
|
||||
rdtest.log.error(
|
||||
f"Don't have expected output for {var.name}")
|
||||
continue
|
||||
|
||||
real = postvs[vtx][name]
|
||||
debugged = self.evaluate_source_var(
|
||||
var, variables)
|
||||
|
||||
if debugged.columns != 4 or len(real) != 4:
|
||||
rdtest.log.error(
|
||||
f"Vertex output is not the right size ({len(real)} vs {debugged.columns})")
|
||||
continue
|
||||
|
||||
if not rdtest.value_compare(real, debugged.value.f32v[0:4], eps=5.0E-06):
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} debugged vertex value {debugged.value.f32v[0:4]} at {vtx} instance {inst} view {view} does not match output {real}")
|
||||
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
# check some assorted pixel outputs
|
||||
target = pipe.GetOutputTargets()[0].resource
|
||||
|
||||
for pixel in pixel_checks:
|
||||
for view in range(pipe.MultiviewBroadcastCount()):
|
||||
x, y = pixel
|
||||
|
||||
picked = self.controller.PickPixel(
|
||||
target, x, y, rd.Subresource(0, 0, 0), rd.CompType.Float)
|
||||
|
||||
real = picked.floatValue
|
||||
|
||||
# silently skip pixels that weren't written to
|
||||
if real == clear_col:
|
||||
continue
|
||||
|
||||
inputs = rd.DebugPixelInputs()
|
||||
inputs.sample = 0
|
||||
inputs.primitive = rd.ReplayController.NoPreference
|
||||
inputs.view = view
|
||||
trace = self.controller.DebugPixel(x, y, inputs)
|
||||
|
||||
if trace.debugger is None:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} got no debug result at {x},{y}")
|
||||
continue
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
output_sourcevar = self.find_output_source_var(
|
||||
trace, rd.ShaderBuiltin.ColorOutput, 0)
|
||||
|
||||
if output_sourcevar is None:
|
||||
rdtest.log.error("No output variable found")
|
||||
continue
|
||||
|
||||
debugged = self.evaluate_source_var(
|
||||
output_sourcevar, variables)
|
||||
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
debuggedValue = list(debugged.value.f32v[0:4])
|
||||
|
||||
if not rdtest.value_compare(real, debuggedValue, eps=5.0E-06):
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} debugged pixel value {debuggedValue} at {x},{y} in {view} does not match output {real}")
|
||||
|
||||
rdtest.log.success(f"Test {idx} successful")
|
||||
|
||||
rdtest.log.end_section("Graphics tests")
|
||||
|
||||
for comp_dim in compute_dims:
|
||||
rdtest.log.begin_section(
|
||||
f"Compute tests with {comp_dim.customName} workgroup")
|
||||
|
||||
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)
|
||||
|
||||
dim = csrefl.dispatchThreadsDimension
|
||||
|
||||
rw = pipe.GetReadWriteResources(rd.ShaderStage.Compute)
|
||||
|
||||
if len(rw) != 1:
|
||||
rdtest.log.error("Unexpected number of RW resources")
|
||||
continue
|
||||
|
||||
# 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)
|
||||
|
||||
for t in thread_checks:
|
||||
xrange = 1
|
||||
yrange = dim[1]
|
||||
xbase = t
|
||||
ybase = 0
|
||||
|
||||
# vertical orientation
|
||||
if dim[1] > dim[0]:
|
||||
xrange = dim[0]
|
||||
yrange = 1
|
||||
xbase = 0
|
||||
ybase = t
|
||||
|
||||
for x in range(xbase, xbase+xrange):
|
||||
for y in range(ybase, ybase+yrange):
|
||||
z = 0
|
||||
|
||||
if x >= dim[0] or y >= dim[1]:
|
||||
continue
|
||||
|
||||
real = struct.unpack_from(
|
||||
"4f", bufdata, 16*y*dim[0] + 16*x)
|
||||
|
||||
trace = self.controller.DebugThread(
|
||||
(0, 0, 0), (x, y, z))
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
if trace.debugger is None:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
rdtest.log.error(
|
||||
f"Test {test} at {action.eventId} got no debug result at {x},{y},{z}")
|
||||
continue
|
||||
|
||||
sourceVars = [
|
||||
v for v in trace.instInfo[-1].sourceVars if v.name == 'data']
|
||||
|
||||
if len(sourceVars) != 1:
|
||||
rdtest.log.error(
|
||||
"Couldn't find compute data variable")
|
||||
continue
|
||||
|
||||
debugged = self.evaluate_source_var(
|
||||
sourceVars[0], variables)
|
||||
|
||||
debuggedValue = list(debugged.value.f32v[0:4])
|
||||
|
||||
if not rdtest.value_compare(real, debuggedValue, eps=5.0E-06):
|
||||
rdtest.log.error(
|
||||
f"Test {test} at {action.eventId} debugged thread value {debuggedValue} at {x},{y},{z} does not match output {real}")
|
||||
|
||||
rdtest.log.success(f"Test {test} successful")
|
||||
|
||||
rdtest.log.end_section(
|
||||
f"Compute tests with {comp_dim.customName} workgroup")
|
||||
internal = False
|
||||
@@ -1,246 +1,5 @@
|
||||
import renderdoc as rd
|
||||
import struct
|
||||
import rdtest
|
||||
|
||||
|
||||
class VK_Subgroup_Zoo(rdtest.TestCase):
|
||||
class VK_Subgroup_Zoo(rdtest.Subgroup_Zoo):
|
||||
demos_test_name = 'VK_Subgroup_Zoo'
|
||||
|
||||
def check_support(self, **kwargs):
|
||||
# Only allow this if explicitly run
|
||||
if kwargs['test_include'] == 'VK_Subgroup_Zoo':
|
||||
return True, ''
|
||||
return False, 'Disabled test'
|
||||
|
||||
def check_capture(self):
|
||||
graphics_tests = [a for a in self.find_action(
|
||||
"Graphics Tests").children if a.flags & rd.ActionFlags.Drawcall]
|
||||
compute_dims = [a for a in self.find_action(
|
||||
"Compute Tests").children if 'x' in a.customName]
|
||||
|
||||
rdtest.log.begin_section("Graphics tests")
|
||||
|
||||
# instances to check in instanced draws
|
||||
inst_checks = [0, 1, 5, 10]
|
||||
# pixels to check
|
||||
pixel_checks = [
|
||||
# top quad
|
||||
(0, 0), (1, 0), (0, 1), (1, 1),
|
||||
# middle quad (away from triangle border)
|
||||
(64, 56), (65, 56), (64, 57), (65, 57),
|
||||
# middle quad (on triangle border)
|
||||
(64, 64), (65, 64), (64, 65), (65, 65),
|
||||
# middle quad on other triangle
|
||||
(56, 64), (57, 64), (56, 65), (57, 65),
|
||||
]
|
||||
# threads to check. largest dimension only (all small dim checked)
|
||||
thread_checks = [
|
||||
# first few
|
||||
0, 1, 2,
|
||||
# near end of 32-subgroup and boundary
|
||||
30, 31, 32,
|
||||
# near end of 64-subgroup and boundary
|
||||
62, 63, 64,
|
||||
# near end of 64-subgroup and boundary
|
||||
62, 63, 64,
|
||||
# large values spaced out with one near the end of our unaligned size
|
||||
100, 110, 120, 140, 149, 150, 160, 200, 250,
|
||||
]
|
||||
clear_col = (123456.0, 789.0, 101112.0, 0.0)
|
||||
|
||||
for idx, action in enumerate(graphics_tests):
|
||||
self.controller.SetFrameEvent(action.eventId, False)
|
||||
|
||||
pipe = self.controller.GetPipelineState()
|
||||
|
||||
# check vertex output for every vertex
|
||||
for inst in [inst for inst in inst_checks if inst < action.numInstances]:
|
||||
for view in range(pipe.MultiviewBroadcastCount()):
|
||||
|
||||
postvs = self.get_postvs(
|
||||
action, rd.MeshDataStage.VSOut, first_index=0, num_indices=action.numIndices, instance=inst)
|
||||
|
||||
for vtx in range(action.numIndices):
|
||||
trace = self.controller.DebugVertex(
|
||||
vtx, inst, vtx, view)
|
||||
|
||||
if trace.debugger is None:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} got no debug result at {vtx} inst {inst} view {view}")
|
||||
return
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
for var in trace.sourceVars:
|
||||
if var.name == 'vertdata':
|
||||
name = var.name
|
||||
|
||||
if var.name not in postvs[vtx].keys():
|
||||
rdtest.log.error(
|
||||
f"Don't have expected output for {var.name}")
|
||||
continue
|
||||
|
||||
real = postvs[vtx][name]
|
||||
debugged = self.evaluate_source_var(
|
||||
var, variables)
|
||||
|
||||
if debugged.columns != 4 or len(real) != 4:
|
||||
rdtest.log.error(
|
||||
f"Vertex output is not the right size ({len(real)} vs {debugged.columns})")
|
||||
continue
|
||||
|
||||
if not rdtest.value_compare(real, debugged.value.f32v[0:4], eps=5.0E-06):
|
||||
rdtest.log.error(
|
||||
f"{idx} at {action.eventId} debugged vertex value {debugged.value.f32v[0:4]} at {vtx} instance {inst} view {view} does not match output {real}")
|
||||
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
# check some assorted pixel outputs
|
||||
target = pipe.GetOutputTargets()[0].resource
|
||||
|
||||
for pixel in pixel_checks:
|
||||
for view in range(pipe.MultiviewBroadcastCount()):
|
||||
x, y = pixel
|
||||
|
||||
picked = self.controller.PickPixel(
|
||||
target, x, y, rd.Subresource(0, 0, 0), rd.CompType.Float)
|
||||
|
||||
real = picked.floatValue
|
||||
|
||||
# silently skip pixels that weren't written to
|
||||
if real == clear_col:
|
||||
continue
|
||||
|
||||
inputs = rd.DebugPixelInputs()
|
||||
inputs.sample = 0
|
||||
inputs.primitive = rd.ReplayController.NoPreference
|
||||
inputs.view = view
|
||||
trace = self.controller.DebugPixel(x, y, inputs)
|
||||
|
||||
if trace.debugger is None:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} got no debug result at {x},{y}")
|
||||
continue
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
output_sourcevar = self.find_output_source_var(
|
||||
trace, rd.ShaderBuiltin.ColorOutput, 0)
|
||||
|
||||
if output_sourcevar is None:
|
||||
rdtest.log.error("No output variable found")
|
||||
continue
|
||||
|
||||
debugged = self.evaluate_source_var(
|
||||
output_sourcevar, variables)
|
||||
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
debuggedValue = list(debugged.value.f32v[0:4])
|
||||
|
||||
if not rdtest.value_compare(real, debuggedValue, eps=5.0E-06):
|
||||
rdtest.log.error(
|
||||
f"Test {idx} at {action.eventId} debugged pixel value {debuggedValue} at {x},{y} in {view} does not match output {real}")
|
||||
|
||||
rdtest.log.success(f"Test {idx} successful")
|
||||
|
||||
rdtest.log.end_section("Graphics tests")
|
||||
overallFailed = False
|
||||
for comp_dim in compute_dims:
|
||||
rdtest.log.begin_section(
|
||||
f"Compute tests with {comp_dim.customName} workgroup")
|
||||
|
||||
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)
|
||||
|
||||
dim = csrefl.dispatchThreadsDimension
|
||||
|
||||
rw = pipe.GetReadWriteResources(rd.ShaderStage.Compute)
|
||||
|
||||
if len(rw) != 1:
|
||||
rdtest.log.error("Unexpected number of RW resources")
|
||||
continue
|
||||
|
||||
# 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)
|
||||
|
||||
failed = False
|
||||
for t in thread_checks:
|
||||
xrange = 1
|
||||
yrange = dim[1]
|
||||
xbase = t
|
||||
ybase = 0
|
||||
|
||||
# vertical orientation
|
||||
if dim[1] > dim[0]:
|
||||
xrange = dim[0]
|
||||
yrange = 1
|
||||
xbase = 0
|
||||
ybase = t
|
||||
|
||||
for x in range(xbase, xbase+xrange):
|
||||
for y in range(ybase, ybase+yrange):
|
||||
z = 0
|
||||
|
||||
if x >= dim[0] or y >= dim[1]:
|
||||
continue
|
||||
|
||||
try:
|
||||
real = struct.unpack_from(
|
||||
"4f", bufdata, 16*y*dim[0] + 16*x)
|
||||
|
||||
trace = self.controller.DebugThread(
|
||||
(0, 0, 0), (x, y, z))
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
if trace.debugger is None:
|
||||
raise rdtest.TestFailureException(f"Test {test} at {action.eventId} got no debug result at {x},{y},{z}")
|
||||
|
||||
# Find the source variable 'data' at the highest instruction index
|
||||
maxInstInfo = None
|
||||
for instInfo in trace.instInfo:
|
||||
for v in instInfo.sourceVars:
|
||||
if v.name == 'data':
|
||||
maxInstInfo = instInfo
|
||||
break
|
||||
|
||||
sourceVars = [v for v in maxInstInfo.sourceVars if v.name == 'data']
|
||||
if len(sourceVars) != 1:
|
||||
raise rdtest.TestFailureException(f"Couldn't find compute source variable 'data' {x}, {y}, {z}")
|
||||
|
||||
debugged = self.evaluate_source_var(
|
||||
sourceVars[0], variables)
|
||||
|
||||
debuggedValue = list(debugged.value.f32v[0:4])
|
||||
|
||||
if not rdtest.value_compare(real, debuggedValue, eps=5.0E-06):
|
||||
raise rdtest.TestFailureException(f"EID:{action.eventId} TID:{x},{y},{z} debugged thread value {debuggedValue} does not match output {real}")
|
||||
|
||||
except rdtest.TestFailureException as ex:
|
||||
rdtest.log.error(f"Test {test} failed {ex}")
|
||||
failed = True
|
||||
continue
|
||||
finally:
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
overallFailed |= failed
|
||||
if not failed:
|
||||
rdtest.log.success(f"Test {test} successful")
|
||||
|
||||
rdtest.log.end_section(
|
||||
f"Compute tests with {comp_dim.customName} workgroup")
|
||||
|
||||
if overallFailed:
|
||||
raise rdtest.TestFailureException("Some tests were not as expected")
|
||||
internal = False
|
||||
|
||||
Reference in New Issue
Block a user