xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/subgroups/glcSubgroupsBallotTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * OpenGL Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017-2019 The Khronos Group Inc.
6  * Copyright (c) 2017 Codeplay Software Ltd.
7  * Copyright (c) 2019 NVIDIA Corporation.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */ /*!
22  * \file
23  * \brief Subgroups Tests
24  */ /*--------------------------------------------------------------------*/
25 
26 #include "glcSubgroupsBallotTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
28 
29 #include <string>
30 #include <vector>
31 
32 using namespace tcu;
33 using namespace std;
34 
35 namespace glc
36 {
37 namespace subgroups
38 {
39 namespace
40 {
checkVertexPipelineStages(std::vector<const void * > datas,uint32_t width,uint32_t)41 static bool checkVertexPipelineStages(std::vector<const void *> datas, uint32_t width, uint32_t)
42 {
43     return glc::subgroups::check(datas, width, 0x7);
44 }
45 
checkComputeStage(std::vector<const void * > datas,const uint32_t numWorkgroups[3],const uint32_t localSize[3],uint32_t)46 static bool checkComputeStage(std::vector<const void *> datas, const uint32_t numWorkgroups[3],
47                               const uint32_t localSize[3], uint32_t)
48 {
49     return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 0x7);
50 }
51 
52 struct CaseDefinition
53 {
54     glc::subgroups::ShaderStageFlags shaderStage;
55 };
56 
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)57 void initFrameBufferPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
58 {
59     std::ostringstream subgroupSizeStr;
60     subgroupSizeStr << subgroups::maxSupportedSubgroupSize();
61 
62     subgroups::setFragmentShaderFrameBuffer(programCollection);
63 
64     if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
65         subgroups::setVertexShaderFrameBuffer(programCollection);
66 
67     if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
68     {
69         const string vertexGLSL = "${VERSION_DECL}\n"
70                                   "#extension GL_KHR_shader_subgroup_ballot: enable\n"
71                                   "layout(location = 0) in highp vec4 in_position;\n"
72                                   "layout(location = 0) out float out_color;\n"
73                                   "layout(binding = 0, std140) uniform Buffer1\n"
74                                   "{\n"
75                                   "  uint data[" +
76                                   subgroupSizeStr.str() +
77                                   "];\n"
78                                   "};\n"
79                                   "\n"
80                                   "void main (void)\n"
81                                   "{\n"
82                                   "  uint tempResult = 0u;\n"
83                                   "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
84                                   "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
85                                   "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
86                                   "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
87                                   "  out_color = float(tempResult);\n"
88                                   "  gl_Position = in_position;\n"
89                                   "  gl_PointSize = 1.0f;\n"
90                                   "}\n";
91         programCollection.add("vert") << glu::VertexSource(vertexGLSL);
92     }
93     else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
94     {
95         const string geometryGLSL = "${VERSION_DECL}\n"
96                                     "#extension GL_KHR_shader_subgroup_ballot: enable\n"
97                                     "layout(points) in;\n"
98                                     "layout(points, max_vertices = 1) out;\n"
99                                     "layout(location = 0) out float out_color;\n"
100                                     "layout(binding = 0, std140) uniform Buffer1\n"
101                                     "{\n"
102                                     "  uint data[" +
103                                     subgroupSizeStr.str() +
104                                     "];\n"
105                                     "};\n"
106                                     "\n"
107                                     "void main (void)\n"
108                                     "{\n"
109                                     "  uint tempResult = 0u;\n"
110                                     "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
111                                     "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
112                                     "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
113                                     "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
114                                     "  out_color = float(tempResult);\n"
115                                     "  gl_Position = gl_in[0].gl_Position;\n"
116                                     "  EmitVertex();\n"
117                                     "  EndPrimitive();\n"
118                                     "}\n";
119         programCollection.add("geometry") << glu::GeometrySource(geometryGLSL);
120     }
121     else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
122     {
123         const string controlSourceGLSL = "${VERSION_DECL}\n"
124                                          "#extension GL_KHR_shader_subgroup_ballot: enable\n"
125                                          "layout(vertices = 2) out;\n"
126                                          "layout(location = 0) out float out_color[];\n"
127                                          "layout(binding = 0, std140) uniform Buffer1\n"
128                                          "{\n"
129                                          "  uint data[" +
130                                          subgroupSizeStr.str() +
131                                          "];\n"
132                                          "};\n"
133                                          "\n"
134                                          "void main (void)\n"
135                                          "{\n"
136                                          "  if (gl_InvocationID == 0)\n"
137                                          "  {\n"
138                                          "    gl_TessLevelOuter[0] = 1.0f;\n"
139                                          "    gl_TessLevelOuter[1] = 1.0f;\n"
140                                          "  }\n"
141                                          "  uint tempResult = 0u;\n"
142                                          "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
143                                          "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
144                                          "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
145                                          "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
146                                          "  out_color[gl_InvocationID] = float(tempResult);\n"
147                                          "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
148                                          "}\n";
149         programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
150         subgroups::setTesEvalShaderFrameBuffer(programCollection);
151     }
152     else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
153     {
154         const string evaluationSourceGLSL =
155             "${VERSION_DECL}\n"
156             "#extension GL_KHR_shader_subgroup_ballot: enable\n"
157             "layout(isolines, equal_spacing, ccw ) in;\n"
158             "layout(location = 0) out float out_color;\n"
159             "layout(binding = 0, std140) uniform Buffer1\n"
160             "{\n"
161             "  uint data[" +
162             subgroupSizeStr.str() +
163             "];\n"
164             "};\n"
165             "\n"
166             "void main (void)\n"
167             "{\n"
168             "  uint tempResult = 0u;\n"
169             "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
170             "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
171             "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
172             "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
173             "  out_color = float(tempResult);\n"
174             "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
175             "}\n";
176         programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
177 
178         subgroups::setTesCtrlShaderFrameBuffer(programCollection);
179     }
180     else
181     {
182         DE_FATAL("Unsupported shader stage");
183     }
184 }
185 
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)186 void initPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
187 {
188     if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
189     {
190         std::ostringstream src;
191 
192         src << "${VERSION_DECL}\n"
193             << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
194             << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
195             << "layout(binding = 0, std430) buffer Buffer1\n"
196             << "{\n"
197             << "  uint result[];\n"
198             << "};\n"
199             << "layout(binding = 1, std430) buffer Buffer2\n"
200             << "{\n"
201             << "  uint data[];\n"
202             << "};\n"
203             << "\n"
204             << subgroups::getSharedMemoryBallotHelper() << "void main (void)\n"
205             << "{\n"
206             << "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
207             << "  highp uint offset = globalSize.x * ((globalSize.y * "
208                "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
209                "gl_GlobalInvocationID.x;\n"
210             << "  uint tempResult = 0u;\n"
211             << "  tempResult |= sharedMemoryBallot(true) == subgroupBallot(true) ? 0x1u : 0u;\n"
212             << "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
213             << "  tempResult |= sharedMemoryBallot(bData) == subgroupBallot(bData) ? 0x2u : 0u;\n"
214             << "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
215             << "  result[offset] = tempResult;\n"
216             << "}\n";
217 
218         programCollection.add("comp") << glu::ComputeSource(src.str());
219     }
220     else
221     {
222         const string vertex =
223             "${VERSION_DECL}\n"
224             "#extension GL_KHR_shader_subgroup_ballot: enable\n"
225             "layout(binding = 0, std430) buffer Buffer0\n"
226             "{\n"
227             "  uint result[];\n"
228             "} b0;\n"
229             "layout(binding = 4, std430) readonly buffer Buffer4\n"
230             "{\n"
231             "  uint data[];\n"
232             "};\n"
233             "\n"
234             "void main (void)\n"
235             "{\n"
236             "  uint tempResult = 0u;\n"
237             "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
238             "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
239             "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
240             "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
241             "  b0.result[gl_VertexID] = tempResult;\n"
242             "  float pixelSize = 2.0f/1024.0f;\n"
243             "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
244             "  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
245             "  gl_PointSize = 1.0f;\n"
246             "}\n";
247 
248         const string tesc = "${VERSION_DECL}\n"
249                             "#extension GL_KHR_shader_subgroup_ballot: enable\n"
250                             "layout(vertices=1) out;\n"
251                             "layout(binding = 1, std430) buffer Buffer1\n"
252                             "{\n"
253                             "  uint result[];\n"
254                             "} b1;\n"
255                             "layout(binding = 4, std430) readonly buffer Buffer4\n"
256                             "{\n"
257                             "  uint data[];\n"
258                             "};\n"
259                             "\n"
260                             "void main (void)\n"
261                             "{\n"
262                             "  uint tempResult = 0u;\n"
263                             "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
264                             "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
265                             "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
266                             "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
267                             "  b1.result[gl_PrimitiveID] = tempResult;\n"
268                             "  if (gl_InvocationID == 0)\n"
269                             "  {\n"
270                             "    gl_TessLevelOuter[0] = 1.0f;\n"
271                             "    gl_TessLevelOuter[1] = 1.0f;\n"
272                             "  }\n"
273                             "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
274                             "}\n";
275 
276         const string tese = "${VERSION_DECL}\n"
277                             "#extension GL_KHR_shader_subgroup_ballot: enable\n"
278                             "layout(isolines) in;\n"
279                             "layout(binding = 2, std430) buffer Buffer2\n"
280                             "{\n"
281                             "  uint result[];\n"
282                             "} b2;\n"
283                             "layout(binding = 4, std430) readonly buffer Buffer4\n"
284                             "{\n"
285                             "  uint data[];\n"
286                             "};\n"
287                             "\n"
288                             "void main (void)\n"
289                             "{\n"
290                             "  uint tempResult = 0u;\n"
291                             "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
292                             "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
293                             "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
294                             "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
295                             "  b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = tempResult;\n"
296                             "  float pixelSize = 2.0f/1024.0f;\n"
297                             "  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
298                             "}\n";
299 
300         const string geometry =
301             // version string added by addGeometryShadersFromTemplate
302             "#extension GL_KHR_shader_subgroup_ballot: enable\n"
303             "layout(${TOPOLOGY}) in;\n"
304             "layout(points, max_vertices = 1) out;\n"
305             "layout(binding = 3, std430) buffer Buffer3\n"
306             "{\n"
307             "  uint result[];\n"
308             "} b3;\n"
309             "layout(binding = 4, std430) readonly buffer Buffer4\n"
310             "{\n"
311             "  uint data[];\n"
312             "};\n"
313             "\n"
314             "void main (void)\n"
315             "{\n"
316             "  uint tempResult = 0u;\n"
317             "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
318             "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
319             "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
320             "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
321             "  b3.result[gl_PrimitiveIDIn] = tempResult;\n"
322             "  gl_Position = gl_in[0].gl_Position;\n"
323             "  EmitVertex();\n"
324             "  EndPrimitive();\n"
325             "}\n";
326 
327         const string fragment = "${VERSION_DECL}\n"
328                                 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
329                                 "precision highp int;\n"
330                                 "layout(location = 0) out uint result;\n"
331                                 "layout(binding = 4, std430) readonly buffer Buffer4\n"
332                                 "{\n"
333                                 "  uint data[];\n"
334                                 "};\n"
335                                 "void main (void)\n"
336                                 "{\n"
337                                 "  uint tempResult = 0u;\n"
338                                 "  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1u : 0u;\n"
339                                 "  bool bData = data[gl_SubgroupInvocationID] != 0u;\n"
340                                 "  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2u : 0u;\n"
341                                 "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4u : 0u;\n"
342                                 "  result = tempResult;\n"
343                                 "}\n";
344 
345         subgroups::addNoSubgroupShader(programCollection);
346 
347         programCollection.add("vert") << glu::VertexSource(vertex);
348         programCollection.add("tesc") << glu::TessellationControlSource(tesc);
349         programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
350         subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
351         programCollection.add("fragment") << glu::FragmentSource(fragment);
352     }
353 }
354 
supportedCheck(Context & context,CaseDefinition caseDef)355 void supportedCheck(Context &context, CaseDefinition caseDef)
356 {
357     DE_UNREF(caseDef);
358     if (!subgroups::isSubgroupSupported(context))
359         TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
360 
361     if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_BALLOT_BIT))
362     {
363         TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
364     }
365 }
366 
noSSBOtest(Context & context,const CaseDefinition caseDef)367 tcu::TestStatus noSSBOtest(Context &context, const CaseDefinition caseDef)
368 {
369     if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
370     {
371         if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
372         {
373             return tcu::TestStatus::fail("Shader stage " + subgroups::getShaderStageName(caseDef.shaderStage) +
374                                          " is required to support subgroup operations!");
375         }
376         else
377         {
378             TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
379         }
380     }
381 
382     subgroups::SSBOData inputData[1];
383     inputData[0].format         = FORMAT_R32_UINT;
384     inputData[0].layout         = subgroups::SSBOData::LayoutStd140;
385     inputData[0].numElements    = subgroups::maxSupportedSubgroupSize();
386     inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
387     inputData[0].binding        = 0u;
388 
389     if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
390         return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages);
391     else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
392         return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, inputData, 1,
393                                                       checkVertexPipelineStages);
394     else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
395         return subgroups::makeTessellationEvaluationFrameBufferTest(
396             context, FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
397     else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
398         return subgroups::makeTessellationEvaluationFrameBufferTest(
399             context, FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
400     else
401         TCU_THROW(InternalError, "Unhandled shader stage");
402 }
403 
test(Context & context,const CaseDefinition caseDef)404 tcu::TestStatus test(Context &context, const CaseDefinition caseDef)
405 {
406     if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
407     {
408         if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
409         {
410             return tcu::TestStatus::fail("Shader stage " + subgroups::getShaderStageName(caseDef.shaderStage) +
411                                          " is required to support subgroup operations!");
412         }
413         subgroups::SSBOData inputData[1];
414         inputData[0].format         = FORMAT_R32_UINT;
415         inputData[0].layout         = subgroups::SSBOData::LayoutStd430;
416         inputData[0].numElements    = subgroups::maxSupportedSubgroupSize();
417         inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
418         inputData[0].binding        = 1u;
419 
420         return subgroups::makeComputeTest(context, FORMAT_R32_UINT, inputData, 1, checkComputeStage);
421     }
422     else
423     {
424         int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
425 
426         ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
427 
428         if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
429         {
430             if ((stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
431                 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
432             else
433                 stages = SHADER_STAGE_FRAGMENT_BIT;
434         }
435 
436         if ((ShaderStageFlags)0u == stages)
437             TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
438 
439         subgroups::SSBOData inputData;
440         inputData.format         = FORMAT_R32_UINT;
441         inputData.layout         = subgroups::SSBOData::LayoutStd430;
442         inputData.numElements    = subgroups::maxSupportedSubgroupSize();
443         inputData.initializeType = subgroups::SSBOData::InitializeNonZero;
444         inputData.binding        = 4u;
445         inputData.stages         = stages;
446 
447         return subgroups::allStages(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages);
448     }
449 }
450 } // namespace
451 
createSubgroupsBallotTests(deqp::Context & testCtx)452 deqp::TestCaseGroup *createSubgroupsBallotTests(deqp::Context &testCtx)
453 {
454     de::MovePtr<deqp::TestCaseGroup> graphicGroup(
455         new deqp::TestCaseGroup(testCtx, "graphics", "Subgroup ballot category tests: graphics"));
456     de::MovePtr<deqp::TestCaseGroup> computeGroup(
457         new deqp::TestCaseGroup(testCtx, "compute", "Subgroup ballot category tests: compute"));
458     de::MovePtr<deqp::TestCaseGroup> framebufferGroup(
459         new deqp::TestCaseGroup(testCtx, "framebuffer", "Subgroup ballot category tests: framebuffer"));
460 
461     const ShaderStageFlags stages[] = {SHADER_STAGE_TESS_EVALUATION_BIT, SHADER_STAGE_TESS_CONTROL_BIT,
462                                        SHADER_STAGE_GEOMETRY_BIT, SHADER_STAGE_VERTEX_BIT};
463 
464     {
465         const CaseDefinition caseDef = {SHADER_STAGE_COMPUTE_BIT};
466         SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(),
467                                                                      getShaderStageName(caseDef.shaderStage), "",
468                                                                      supportedCheck, initPrograms, test, caseDef);
469     }
470 
471     {
472         const CaseDefinition caseDef = {SHADER_STAGE_ALL_GRAPHICS};
473         SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(), "graphic", "", supportedCheck,
474                                                                      initPrograms, test, caseDef);
475     }
476 
477     for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
478     {
479         const CaseDefinition caseDef = {stages[stageIndex]};
480         SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(
481             framebufferGroup.get(), getShaderStageName(caseDef.shaderStage), "", supportedCheck,
482             initFrameBufferPrograms, noSSBOtest, caseDef);
483     }
484 
485     de::MovePtr<deqp::TestCaseGroup> group(
486         new deqp::TestCaseGroup(testCtx, "ballot", "Subgroup ballot category tests"));
487 
488     group->addChild(graphicGroup.release());
489     group->addChild(computeGroup.release());
490     group->addChild(framebufferGroup.release());
491 
492     return group.release();
493 }
494 
495 } // namespace subgroups
496 } // namespace glc
497