porting changes for OpenGL Subgroup tests
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / subgroups / glcSubgroupsBallotBroadcastTests.cpp
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 "glcSubgroupsBallotBroadcastTests.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 {
41 enum OpType
42 {
43         OPTYPE_BROADCAST = 0,
44         OPTYPE_BROADCAST_FIRST,
45         OPTYPE_LAST
46 };
47
48 static bool checkVertexPipelineStages(std::vector<const void*> datas,
49                                                                           deUint32 width, deUint32)
50 {
51         return glc::subgroups::check(datas, width, 3);
52 }
53
54 static bool checkComputeStages(std::vector<const void*> datas,
55                                                  const deUint32 numWorkgroups[3], const deUint32 localSize[3],
56                                                  deUint32)
57 {
58         return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 3);
59 }
60
61 std::string getOpTypeName(int opType)
62 {
63         switch (opType)
64         {
65                 default:
66                         DE_FATAL("Unsupported op type");
67                         return "";
68                 case OPTYPE_BROADCAST:
69                         return "subgroupBroadcast";
70                 case OPTYPE_BROADCAST_FIRST:
71                         return "subgroupBroadcastFirst";
72         }
73 }
74
75 struct CaseDefinition
76 {
77         int                                     opType;
78         ShaderStageFlags        shaderStage;
79         Format                          format;
80 };
81
82 std::string getBodySource(CaseDefinition caseDef)
83 {
84         std::ostringstream bdy;
85
86         bdy << "  uvec4 mask = subgroupBallot(true);\n";
87         bdy << "  uint tempResult = 0;\n";
88
89         if (OPTYPE_BROADCAST == caseDef.opType)
90         {
91                 bdy     << "  tempResult = 0x3;\n";
92                 for (int i = 0; i < (int)subgroups::maxSupportedSubgroupSize(); i++)
93                 {
94                         bdy << "  {\n"
95                         << "    const uint id = "<< i << ";\n"
96                         << "    " << subgroups::getFormatNameForGLSL(caseDef.format)
97                         << " op = subgroupBroadcast(data1[gl_SubgroupInvocationID], id);\n"
98                         << "    if ((id < gl_SubgroupSize) && subgroupBallotBitExtract(mask, id))\n"
99                         << "    {\n"
100                         << "      if (op != data1[id])\n"
101                         << "      {\n"
102                         << "        tempResult = 0;\n"
103                         << "      }\n"
104                         << "    }\n"
105                         << "  }\n";
106                 }
107         }
108         else
109         {
110                 bdy     << "  uint firstActive = 0;\n"
111                         << "  for (uint i = 0; i < gl_SubgroupSize; i++)\n"
112                         << "  {\n"
113                         << "    if (subgroupBallotBitExtract(mask, i))\n"
114                         << "    {\n"
115                         << "      firstActive = i;\n"
116                         << "      break;\n"
117                         << "    }\n"
118                         << "  }\n"
119                         << "  tempResult |= (subgroupBroadcastFirst(data1[gl_SubgroupInvocationID]) == data1[firstActive]) ? 0x1 : 0;\n"
120                         << "  // make the firstActive invocation inactive now\n"
121                         << "  if (firstActive == gl_SubgroupInvocationID)\n"
122                         << "  {\n"
123                         << "    for (uint i = 0; i < gl_SubgroupSize; i++)\n"
124                         << "    {\n"
125                         << "      if (subgroupBallotBitExtract(mask, i))\n"
126                         << "      {\n"
127                         << "        firstActive = i;\n"
128                         << "        break;\n"
129                         << "      }\n"
130                         << "    }\n"
131                         << "    tempResult |= (subgroupBroadcastFirst(data1[gl_SubgroupInvocationID]) == data1[firstActive]) ? 0x2 : 0;\n"
132                         << "  }\n"
133                         << "  else\n"
134                         << "  {\n"
135                         << "    // the firstActive invocation didn't partake in the second result so set it to true\n"
136                         << "    tempResult |= 0x2;\n"
137                         << "  }\n";
138         }
139    return bdy.str();
140 }
141
142 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
143 {
144         subgroups::setFragmentShaderFrameBuffer(programCollection);
145
146         if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
147                 subgroups::setVertexShaderFrameBuffer(programCollection);
148
149         std::string bdyStr = getBodySource(caseDef);
150
151         if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
152         {
153                 std::ostringstream                              vertex;
154                 vertex << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
155                         << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
156                         << "layout(location = 0) in highp vec4 in_position;\n"
157                         << "layout(location = 0) out float out_color;\n"
158                         << "layout(binding = 0) uniform Buffer0\n"
159                         << "{\n"
160                         << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" << subgroups::maxSupportedSubgroupSize() << "];\n"
161                         << "};\n"
162                         << "\n"
163                         << "void main (void)\n"
164                         << "{\n"
165                         << bdyStr
166                         << "  out_color = float(tempResult);\n"
167                         << "  gl_Position = in_position;\n"
168                         << "  gl_PointSize = 1.0f;\n"
169                         << "}\n";
170                 programCollection.add("vert") << glu::VertexSource(vertex.str());
171         }
172         else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
173         {
174                 std::ostringstream geometry;
175
176                 geometry << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
177                         << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
178                         << "layout(points) in;\n"
179                         << "layout(points, max_vertices = 1) out;\n"
180                         << "layout(location = 0) out float out_color;\n"
181                         << "layout(binding = 0) uniform Buffer0\n"
182                         << "{\n"
183                         << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
184                         << "};\n"
185                         << "\n"
186                         << "void main (void)\n"
187                         << "{\n"
188                         << bdyStr
189                         << "  out_color = float(tempResult);\n"
190                         << "  gl_Position = gl_in[0].gl_Position;\n"
191                         << "  EmitVertex();\n"
192                         << "  EndPrimitive();\n"
193                         << "}\n";
194
195                 programCollection.add("geometry") << glu::GeometrySource(geometry.str());
196         }
197         else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
198         {
199                 std::ostringstream controlSource;
200
201                 controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
202                         << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
203                         << "layout(vertices = 2) out;\n"
204                         << "layout(location = 0) out float out_color[];\n"
205                         << "layout(binding = 0) uniform Buffer0\n"
206                         << "{\n"
207                         << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
208                         << "};\n"
209                         << "\n"
210                         << "void main (void)\n"
211                         << "{\n"
212                         << "  if (gl_InvocationID == 0)\n"
213                         << "  {\n"
214                         << "    gl_TessLevelOuter[0] = 1.0f;\n"
215                         << "    gl_TessLevelOuter[1] = 1.0f;\n"
216                         << "  }\n"
217                         << bdyStr
218                         << "  out_color[gl_InvocationID ] = float(tempResult);\n"
219                         << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
220                         << "}\n";
221
222                 programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
223                 subgroups::setTesEvalShaderFrameBuffer(programCollection);
224         }
225         else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
226         {
227                 std::ostringstream evaluationSource;
228                 evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
229                         << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
230                         << "layout(isolines, equal_spacing, ccw ) in;\n"
231                         << "layout(location = 0) out float out_color;\n"
232                         << "layout(binding = 0) uniform Buffer0\n"
233                         << "{\n"
234                         << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[" <<subgroups::maxSupportedSubgroupSize() << "];\n"
235                         << "};\n"
236                         << "\n"
237                         << "void main (void)\n"
238                         << "{\n"
239                         << bdyStr
240                         << "  out_color  = float(tempResult);\n"
241                         << "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
242                         << "}\n";
243
244                 subgroups::setTesCtrlShaderFrameBuffer(programCollection);
245                 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
246         }
247         else
248         {
249                 DE_FATAL("Unsupported shader stage");
250         }
251 }
252
253 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
254 {
255         std::string bdyStr = getBodySource(caseDef);
256
257         if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
258         {
259                 std::ostringstream src;
260
261                 src << "#version 450\n"
262                         << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
263                         << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
264                         << "layout(binding = 0, std430) buffer Buffer0\n"
265                         << "{\n"
266                         << "  uint result[];\n"
267                         << "};\n"
268                         << "layout(binding = 1, std430) buffer Buffer1\n"
269                         << "{\n"
270                         << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1[];\n"
271                         << "};\n"
272                         << "\n"
273                         << "void main (void)\n"
274                         << "{\n"
275                         << "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
276                         << "  highp uint offset = globalSize.x * ((globalSize.y * "
277                         "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
278                         "gl_GlobalInvocationID.x;\n"
279                         << bdyStr
280                         << "  result[offset] = tempResult;\n"
281                         << "}\n";
282
283                 programCollection.add("comp") << glu::ComputeSource(src.str());
284         }
285         else
286         {
287                 const string vertex =
288                         "#version 450\n"
289                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
290                         "layout(binding = 0, std430) buffer Buffer0\n"
291                         "{\n"
292                         "  uint result[];\n"
293                         "} b0;\n"
294                         "layout(set = 0, binding = 4, std430) readonly buffer Buffer4\n"
295                         "{\n"
296                         "  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data1[];\n"
297                         "};\n"
298                         "\n"
299                         "void main (void)\n"
300                         "{\n"
301                         + bdyStr +
302                         "  b0.result[gl_VertexID] = tempResult;\n"
303                         "  float pixelSize = 2.0f/1024.0f;\n"
304                         "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
305                         "  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
306                         "  gl_PointSize = 1.0f;\n"
307                         "}\n";
308
309                 const string tesc =
310                         "#version 450\n"
311                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
312                         "layout(vertices=1) out;\n"
313                         "layout(binding = 1, std430) buffer Buffer1\n"
314                         "{\n"
315                         "  uint result[];\n"
316                         "} b1;\n"
317                         "layout(binding = 4, std430) readonly buffer Buffer4\n"
318                         "{\n"
319                         "  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data1[];\n"
320                         "};\n"
321                         "\n"
322                         "void main (void)\n"
323                         "{\n"
324                         + bdyStr +
325                         "  b1.result[gl_PrimitiveID] = tempResult;\n"
326                         "  if (gl_InvocationID == 0)\n"
327                         "  {\n"
328                         "    gl_TessLevelOuter[0] = 1.0f;\n"
329                         "    gl_TessLevelOuter[1] = 1.0f;\n"
330                         "  }\n"
331                         "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
332                         "}\n";
333
334                 const string tese =
335                         "#version 450\n"
336                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
337                         "layout(isolines) in;\n"
338                         "layout(binding = 2, std430) buffer Buffer2\n"
339                         "{\n"
340                         "  uint result[];\n"
341                         "} b2;\n"
342                         "layout(binding = 4, std430) readonly buffer Buffer4\n"
343                         "{\n"
344                         "  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data1[];\n"
345                         "};\n"
346                         "\n"
347                         "void main (void)\n"
348                         "{\n"
349                         + bdyStr +
350                         "  b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
351                         "  float pixelSize = 2.0f/1024.0f;\n"
352                         "  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
353                         "}\n";
354
355                 const string geometry =
356                         "#version 450\n"
357                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
358                         "layout(${TOPOLOGY}) in;\n"
359                         "layout(points, max_vertices = 1) out;\n"
360                         "layout(binding = 3, std430) buffer Buffer3\n"
361                         "{\n"
362                         "  uint result[];\n"
363                         "} b3;\n"
364                         "layout(set = 0, binding = 4, std430) readonly buffer Buffer4\n"
365                         "{\n"
366                         "  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data1[];\n"
367                         "};\n"
368                         "\n"
369                         "void main (void)\n"
370                         "{\n"
371                         + bdyStr +
372                         "  b3.result[gl_PrimitiveIDIn] = tempResult;\n"
373                         "  gl_Position = gl_in[0].gl_Position;\n"
374                         "  EmitVertex();\n"
375                         "  EndPrimitive();\n"
376                         "}\n";
377
378                 const string fragment =
379                         "#version 450\n"
380                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
381                         "layout(location = 0) out uint result;\n"
382                         "layout(binding = 4, std430) readonly buffer Buffer4\n"
383                         "{\n"
384                         "  " + subgroups::getFormatNameForGLSL(caseDef.format) + " data1[];\n"
385                         "};\n"
386                         "void main (void)\n"
387                         "{\n"
388                         + bdyStr +
389                         "  result = tempResult;\n"
390                         "}\n";
391
392                 subgroups::addNoSubgroupShader(programCollection);
393
394                 programCollection.add("vert") << glu::VertexSource(vertex);
395                 programCollection.add("tesc") << glu::TessellationControlSource(tesc);
396                 programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
397                 subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
398                 programCollection.add("fragment") << glu::FragmentSource(fragment);
399         }
400 }
401
402 void supportedCheck (Context& context, CaseDefinition caseDef)
403 {
404         if (!subgroups::isSubgroupSupported(context))
405                 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
406
407         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_BALLOT_BIT))
408         {
409                 TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
410         }
411
412         if (subgroups::isDoubleFormat(caseDef.format) &&
413                 !subgroups::isDoubleSupportedForDevice(context))
414         {
415                 TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
416         }
417 }
418
419 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
420 {
421         if (!subgroups::areSubgroupOperationsSupportedForStage(
422                         context, caseDef.shaderStage))
423         {
424                 if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
425                 {
426                         return tcu::TestStatus::fail(
427                                            "Shader stage " +
428                                            subgroups::getShaderStageName(caseDef.shaderStage) +
429                                            " is required to support subgroup operations!");
430                 }
431                 else
432                 {
433                         TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
434                 }
435         }
436
437         subgroups::SSBOData inputData[1];
438         inputData[0].format = caseDef.format;
439         inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
440         inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
441
442         if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
443                 return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages);
444         else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
445                 return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages);
446         else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
447                 return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
448         else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
449                 return subgroups::makeTessellationEvaluationFrameBufferTest(context, FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
450         else
451                 TCU_THROW(InternalError, "Unhandled shader stage");
452 }
453
454
455 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
456 {
457         if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
458         {
459                 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
460                 {
461                         if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
462                         {
463                                 return tcu::TestStatus::fail(
464                                                    "Shader stage " +
465                                                    subgroups::getShaderStageName(caseDef.shaderStage) +
466                                                    " is required to support subgroup operations!");
467                         }
468                         else
469                         {
470                                 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
471                         }
472                 }
473                 subgroups::SSBOData inputData[1];
474                 inputData[0].format = caseDef.format;
475                 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
476                 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
477                 inputData[0].binding = 1u;
478
479                 return subgroups::makeComputeTest(context, FORMAT_R32_UINT, inputData, 1, checkComputeStages);
480         }
481         else
482         {
483                 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
484
485                 ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
486
487                 if ( SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
488                 {
489                         if ( (stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
490                                 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
491                         else
492                                 stages = SHADER_STAGE_FRAGMENT_BIT;
493                 }
494
495                 if ((ShaderStageFlags)0u == stages)
496                         TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
497
498                 subgroups::SSBOData inputData;
499                 inputData.format                        = caseDef.format;
500                 inputData.numElements           = subgroups::maxSupportedSubgroupSize();
501                 inputData.initializeType        = subgroups::SSBOData::InitializeNonZero;
502                 inputData.binding                       = 4u;
503                 inputData.stages                        = stages;
504
505                 return subgroups::allStages(context, FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages);
506         }
507 }
508 }
509
510 deqp::TestCaseGroup* createSubgroupsBallotBroadcastTests(deqp::Context& testCtx)
511 {
512         de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
513                 testCtx, "graphics", "Subgroup ballot broadcast category tests: graphics"));
514         de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
515                 testCtx, "compute", "Subgroup ballot broadcast category tests: compute"));
516         de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
517                 testCtx, "framebuffer", "Subgroup ballot broadcast category tests: framebuffer"));
518
519         const ShaderStageFlags stages[] =
520         {
521                 SHADER_STAGE_VERTEX_BIT,
522                 SHADER_STAGE_TESS_EVALUATION_BIT,
523                 SHADER_STAGE_TESS_CONTROL_BIT,
524                 SHADER_STAGE_GEOMETRY_BIT,
525         };
526
527         const Format formats[] =
528         {
529                 FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT,
530                 FORMAT_R32G32B32A32_SINT, FORMAT_R32_UINT, FORMAT_R32G32_UINT,
531                 FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT,
532                 FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT,
533                 FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
534                 FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT,
535                 FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
536                 FORMAT_R32_BOOL, FORMAT_R32G32_BOOL,
537                 FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL,
538         };
539
540         for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
541         {
542                 const Format format = formats[formatIndex];
543
544                 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
545                 {
546                         const std::string op = de::toLower(getOpTypeName(opTypeIndex));
547                         const std::string name = op + "_" + subgroups::getFormatNameForGLSL(format);
548
549                         {
550                                 CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format};
551                                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
552                         }
553
554                         {
555                                 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS, format};
556                                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
557                         }
558
559                         for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
560                         {
561                                 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format};
562                                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(), name + getShaderStageName(caseDef.shaderStage), "",
563                                                         supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
564                         }
565                 }
566         }
567
568         de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
569                 testCtx, "ballot_broadcast", "Subgroup ballot broadcast category tests"));
570
571         group->addChild(graphicGroup.release());
572         group->addChild(computeGroup.release());
573         group->addChild(framebufferGroup.release());
574         return group.release();
575 }
576
577 } // subgroups
578 } // glc