mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Add vk_subgroup_zoo tests for maximal reconvergence behaviour
Diverged threads which re-converge at expected points
This commit is contained in:
@@ -129,16 +129,136 @@ layout(binding = 0, std430) buffer outbuftype {
|
||||
|
||||
layout(local_size_x = GROUP_SIZE_X, local_size_y = GROUP_SIZE_Y, local_size_z = 1) in;
|
||||
|
||||
vec4 funcD(uint id)
|
||||
{
|
||||
return vec4(subgroupAdd(id/2));
|
||||
}
|
||||
|
||||
vec4 nestedFunc(uint id)
|
||||
{
|
||||
vec4 ret = funcD(id/3);
|
||||
ret.w = subgroupAdd(id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 funcA(uint id)
|
||||
{
|
||||
return nestedFunc(id*2);
|
||||
}
|
||||
|
||||
vec4 funcB(uint id)
|
||||
{
|
||||
return nestedFunc(id*4);
|
||||
}
|
||||
|
||||
vec4 funcTest(uint id)
|
||||
{
|
||||
if ((id % 2) == 0)
|
||||
{
|
||||
return vec4(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
float value = subgroupAdd(id);
|
||||
if (id < 10)
|
||||
{
|
||||
return vec4(value);
|
||||
}
|
||||
value += subgroupAdd(id/2);
|
||||
return vec4(value);
|
||||
}
|
||||
}
|
||||
|
||||
void SetOuput(vec4 data)
|
||||
{
|
||||
outbuf.data[push.test].vals[gl_LocalInvocationID.y * GROUP_SIZE_X + gl_LocalInvocationID.x] = data;
|
||||
}
|
||||
void main()
|
||||
{
|
||||
vec4 data = vec4(0);
|
||||
uint id = gl_SubgroupInvocationID;
|
||||
SetOuput(data);
|
||||
|
||||
if(IsTest(0))
|
||||
data = vec4(gl_SubgroupInvocationID, 0, 0, 0);
|
||||
{
|
||||
data.x = id;
|
||||
}
|
||||
else if(IsTest(1))
|
||||
data = vec4(subgroupAdd(gl_SubgroupInvocationID), 0, 0, 0);
|
||||
{
|
||||
data.x = subgroupAdd(id);
|
||||
}
|
||||
else if(IsTest(2))
|
||||
{
|
||||
// Diverged threads which reconverge
|
||||
if (id < 10)
|
||||
{
|
||||
// active threads 0-9
|
||||
data.x = subgroupAdd(id);
|
||||
|
||||
outbuf.data[push.test].vals[gl_LocalInvocationID.y * GROUP_SIZE_X + gl_LocalInvocationID.x] = data;
|
||||
if ((id % 2) == 0)
|
||||
data.y = subgroupAdd(id);
|
||||
else
|
||||
data.y = subgroupAdd(id);
|
||||
|
||||
data.x += subgroupAdd(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// active threads 10...
|
||||
data.x = subgroupAdd(id);
|
||||
}
|
||||
data.y = subgroupAdd(id);
|
||||
}
|
||||
else if(IsTest(3))
|
||||
{
|
||||
// Converged threads calling a function
|
||||
data = funcTest(id);
|
||||
data.y = subgroupAdd(id);
|
||||
}
|
||||
else if(IsTest(4))
|
||||
{
|
||||
// Converged threads calling a function which has a nested function call in it
|
||||
data = nestedFunc(id);
|
||||
data.y = subgroupAdd(id);
|
||||
}
|
||||
else if(IsTest(5))
|
||||
{
|
||||
// Diverged threads calling the same function
|
||||
if (id < 10)
|
||||
{
|
||||
data = funcD(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = funcD(id);
|
||||
}
|
||||
data.y = subgroupAdd(id);
|
||||
}
|
||||
else if(IsTest(6))
|
||||
{
|
||||
// Diverged threads calling the same function which has a nested function call in it
|
||||
if (id < 10)
|
||||
{
|
||||
data = funcA(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = funcB(id);
|
||||
}
|
||||
data.y = subgroupAdd(id);
|
||||
}
|
||||
else if(IsTest(7))
|
||||
{
|
||||
// Diverged threads which early exit
|
||||
if (id < 10)
|
||||
{
|
||||
data.x = subgroupAdd(id+10);
|
||||
SetOuput(data);
|
||||
return;
|
||||
}
|
||||
data.x = subgroupAdd(id);
|
||||
}
|
||||
SetOuput(data);
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
@@ -149,7 +149,7 @@ class VK_Subgroup_Zoo(rdtest.TestCase):
|
||||
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")
|
||||
@@ -175,6 +175,7 @@ class VK_Subgroup_Zoo(rdtest.TestCase):
|
||||
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]
|
||||
@@ -195,39 +196,51 @@ class VK_Subgroup_Zoo(rdtest.TestCase):
|
||||
if x >= dim[0] or y >= dim[1]:
|
||||
continue
|
||||
|
||||
real = struct.unpack_from(
|
||||
"4f", bufdata, 16*y*dim[0] + 16*x)
|
||||
try:
|
||||
real = struct.unpack_from(
|
||||
"4f", bufdata, 16*y*dim[0] + 16*x)
|
||||
|
||||
trace = self.controller.DebugThread(
|
||||
(0, 0, 0), (x, y, z))
|
||||
trace = self.controller.DebugThread(
|
||||
(0, 0, 0), (x, y, z))
|
||||
|
||||
_, variables = self.process_trace(trace)
|
||||
_, variables = self.process_trace(trace)
|
||||
|
||||
if trace.debugger is None:
|
||||
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)
|
||||
|
||||
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")
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user