Add vk_subgroup_zoo tests for maximal reconvergence behaviour

Diverged threads which re-converge at expected points
This commit is contained in:
Jake Turner
2025-02-12 08:44:57 +00:00
parent 593e57f65b
commit 7f4098d835
2 changed files with 165 additions and 32 deletions
+123 -3
View File
@@ -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";
+42 -29
View File
@@ -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")