porting changes for OpenGL Subgroup tests
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / subgroups / glcSubgroupsBasicTests.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 "glcSubgroupsBasicTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
28 #include "gluContextInfo.hpp"
29
30 #include <string>
31 #include <vector>
32 #include "tcuStringTemplate.hpp"
33
34 using namespace tcu;
35 using namespace std;
36
37 namespace glc
38 {
39 namespace subgroups
40 {
41
42 namespace
43 {
44 static const deUint32                   ELECTED_VALUE           = 42u;
45 static const deUint32                   UNELECTED_VALUE         = 13u;
46 static const deUint64                   SHADER_BUFFER_SIZE      = 4096ull;
47
48 static bool checkFragmentSubgroupBarriersNoSSBO(std::vector<const void*> datas,
49                 deUint32 width, deUint32 height, deUint32)
50 {
51         const float* const      resultData      = reinterpret_cast<const float*>(datas[0]);
52
53         for (deUint32 x = 0u; x < width; ++x)
54         {
55                 for (deUint32 y = 0u; y < height; ++y)
56                 {
57                         const deUint32 ndx = (x * height + y) * 4u;
58                         if (1.0f == resultData[ndx +2])
59                         {
60                                 if(resultData[ndx] != resultData[ndx +1])
61                                 {
62                                         return false;
63                                 }
64                         }
65                         else if (resultData[ndx] != resultData[ndx +3])
66                         {
67                                 return false;
68                         }
69                 }
70         }
71
72         return true;
73 }
74
75 static bool checkVertexPipelineStagesSubgroupElectNoSSBO(std::vector<const void*> datas,
76                 deUint32 width, deUint32)
77 {
78         const float* const      resultData                      = reinterpret_cast<const float*>(datas[0]);
79         float                           poisonValuesFound       = 0.0f;
80         float                           numSubgroupsUsed        = 0.0f;
81
82         for (deUint32 x = 0; x < width; ++x)
83         {
84                 deUint32 val = static_cast<deUint32>(resultData[x * 2]);
85                 numSubgroupsUsed += resultData[x * 2 + 1];
86
87                 switch (val)
88                 {
89                         default:
90                                 // some garbage value was found!
91                                 return false;
92                         case UNELECTED_VALUE:
93                                 break;
94                         case ELECTED_VALUE:
95                                 poisonValuesFound += 1.0f;
96                                 break;
97                 }
98         }
99         return numSubgroupsUsed == poisonValuesFound;
100 }
101
102 static bool checkVertexPipelineStagesSubgroupElect(std::vector<const void*> datas,
103                 deUint32 width, deUint32)
104 {
105         const deUint32* const resultData =
106                 reinterpret_cast<const deUint32*>(datas[0]);
107         deUint32 poisonValuesFound = 0;
108
109         for (deUint32 x = 0; x < width; ++x)
110         {
111                 deUint32 val = resultData[x];
112
113                 switch (val)
114                 {
115                         default:
116                                 // some garbage value was found!
117                                 return false;
118                         case UNELECTED_VALUE:
119                                 break;
120                         case ELECTED_VALUE:
121                                 poisonValuesFound++;
122                                 break;
123                 }
124         }
125
126         // we used an atomicly incremented counter to note how many subgroups we used for the vertex shader
127         const deUint32 numSubgroupsUsed =
128                 *reinterpret_cast<const deUint32*>(datas[1]);
129
130         return numSubgroupsUsed == poisonValuesFound;
131 }
132
133 static bool checkVertexPipelineStagesSubgroupBarriers(std::vector<const void*> datas,
134                 deUint32 width, deUint32)
135 {
136         const deUint32* const resultData = reinterpret_cast<const deUint32*>(datas[0]);
137
138         // We used this SSBO to generate our unique value!
139         const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[3]);
140
141         for (deUint32 x = 0; x < width; ++x)
142         {
143                 deUint32 val = resultData[x];
144
145                 if (val != ref)
146                         return false;
147         }
148
149         return true;
150 }
151
152 static bool checkVertexPipelineStagesSubgroupBarriersNoSSBO(std::vector<const void*> datas,
153                 deUint32 width, deUint32)
154 {
155         const float* const      resultData      = reinterpret_cast<const float*>(datas[0]);
156
157         for (deUint32 x = 0u; x < width; ++x)
158         {
159                 const deUint32 ndx = x*4u;
160                 if (1.0f == resultData[ndx +2])
161                 {
162                         if(resultData[ndx] != resultData[ndx +1])
163                                 return false;
164                 }
165                 else if (resultData[ndx] != resultData[ndx +3])
166                 {
167                         return false;
168                 }
169         }
170         return true;
171 }
172
173 static bool checkTessellationEvaluationSubgroupBarriersNoSSBO(std::vector<const void*> datas,
174                 deUint32 width, deUint32)
175 {
176         const float* const      resultData      = reinterpret_cast<const float*>(datas[0]);
177
178         for (deUint32 x = 0u; x < width; ++x)
179         {
180                 const deUint32 ndx = x*4u;
181                 if (0.0f == resultData[ndx +2] && resultData[ndx] != resultData[ndx +3])
182                 {
183                         return false;
184                 }
185         }
186         return true;
187 }
188
189 static bool checkComputeSubgroupElect(std::vector<const void*> datas,
190                                                                           const deUint32 numWorkgroups[3], const deUint32 localSize[3],
191                                                                           deUint32)
192 {
193         return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
194 }
195
196 static bool checkComputeSubgroupBarriers(std::vector<const void*> datas,
197                 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
198                 deUint32)
199 {
200         // We used this SSBO to generate our unique value!
201         const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[2]);
202         return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, ref);
203 }
204
205 enum OpType
206 {
207         OPTYPE_ELECT = 0,
208         OPTYPE_SUBGROUP_BARRIER,
209         OPTYPE_SUBGROUP_MEMORY_BARRIER,
210         OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER,
211         OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED,
212         OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE,
213         OPTYPE_LAST
214 };
215
216 std::string getOpTypeName(int opType)
217 {
218         switch (opType)
219         {
220                 default:
221                         DE_FATAL("Unsupported op type");
222                         return "";
223                 case OPTYPE_ELECT:
224                         return "subgroupElect";
225                 case OPTYPE_SUBGROUP_BARRIER:
226                         return "subgroupBarrier";
227                 case OPTYPE_SUBGROUP_MEMORY_BARRIER:
228                         return "subgroupMemoryBarrier";
229                 case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
230                         return "subgroupMemoryBarrierBuffer";
231                 case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
232                         return "subgroupMemoryBarrierShared";
233                 case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
234                         return "subgroupMemoryBarrierImage";
235         }
236 }
237
238 struct CaseDefinition
239 {
240         int                                                     opType;
241         subgroups::ShaderStageFlags     shaderStage;
242 };
243
244 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
245 {
246         if(subgroups::SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage)
247         {
248                 const string fragmentGLSL =
249                         "#version 450\n"
250                         "layout(location = 0) in vec4 in_color;\n"
251                         "layout(location = 0) out vec4 out_color;\n"
252                         "void main()\n"
253                         "{\n"
254                         "       out_color = in_color;\n"
255                         "}\n";
256
257                 programCollection.add("fragment") << glu::FragmentSource(fragmentGLSL);
258         }
259         if (subgroups::SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
260         {
261                 const string vertexGLSL =
262                         "#version 450\n"
263                         "void main (void)\n"
264                         "{\n"
265                         "  vec2 uv = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);\n"
266                         "  gl_Position = vec4(uv * 2.0f + -1.0f, 0.0f, 1.0f);\n"
267                         "  gl_PointSize = 1.0f;\n"
268                         "}\n";
269
270                 programCollection.add("vert") << glu::VertexSource(vertexGLSL);
271         }
272         else if (subgroups::SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
273                 subgroups::setVertexShaderFrameBuffer(programCollection);
274
275         if (OPTYPE_ELECT == caseDef.opType)
276         {
277                 std::ostringstream electedValue ;
278                 std::ostringstream unelectedValue;
279                 electedValue << ELECTED_VALUE;
280                 unelectedValue << UNELECTED_VALUE;
281
282                 if (subgroups::SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
283                 {
284                         const string vertexGLSL =
285                                 "#version 450\n"
286                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
287                                 "layout(location = 0) out vec4 out_color;\n"
288                                 "layout(location = 0) in highp vec4 in_position;\n"
289                                 "\n"
290                                 "void main (void)\n"
291                                 "{\n"
292                                 "  if (subgroupElect())\n"
293                                 "  {\n"
294                                 "    out_color.r = " + electedValue.str() + ";\n"
295                                 "    out_color.g = 1.0f;\n"
296                                 "  }\n"
297                                 "  else\n"
298                                 "  {\n"
299                                 "    out_color.r = " + unelectedValue.str() + ";\n"
300                                 "    out_color.g = 0.0f;\n"
301                                 "  }\n"
302                                 "  gl_Position = in_position;\n"
303                                 "  gl_PointSize = 1.0f;\n"
304                                 "}\n";
305
306                         programCollection.add("vert") << glu::VertexSource(vertexGLSL);
307                 }
308                 else if (subgroups::SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
309                 {
310                         const string geometryGLSL =
311                                 "#version 450\n"
312                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
313                                 "layout(points) in;\n"
314                                 "layout(points, max_vertices = 1) out;\n"
315                                 "layout(location = 0) out vec4 out_color;\n"
316                                 "void main (void)\n"
317                                 "{\n"
318                                 "  if (subgroupElect())\n"
319                                 "  {\n"
320                                 "    out_color.r = " + electedValue.str() + ";\n"
321                                 "    out_color.g = 1.0f;\n"
322                                 "  }\n"
323                                 "  else\n"
324                                 "  {\n"
325                                 "    out_color.r = " + unelectedValue.str() + ";\n"
326                                 "    out_color.g = 0.0f;\n"
327                                 "  }\n"
328                                 "  gl_Position = gl_in[0].gl_Position;\n"
329                                 "  EmitVertex();\n"
330                                 "  EndPrimitive();\n"
331                                 "}\n";
332
333                         programCollection.add("geometry") << glu::GeometrySource(geometryGLSL);
334                 }
335                 else if (subgroups::SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
336                 {
337                         const string controlSourceGLSL =
338                                 "#version 450\n"
339                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
340                                 "#extension GL_EXT_tessellation_shader : require\n"
341                                 "layout(vertices = 2) out;\n"
342                                 "void main (void)\n"
343                                 "{\n"
344                                 "  if (gl_InvocationID == 0)\n"
345                                 "  {\n"
346                                 "    gl_TessLevelOuter[0] = 1.0f;\n"
347                                 "    gl_TessLevelOuter[1] = 1.0f;\n"
348                                 "  }\n"
349                                 "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
350                                 "}\n";
351
352                         programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
353
354                         const string evaluationSourceGLSL =
355                                 "#version 450\n"
356                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
357                                 "#extension GL_EXT_tessellation_shader : require\n"
358                                 "layout(isolines, equal_spacing, ccw ) in;\n"
359                                 "layout(location = 0) out vec4 out_color;\n"
360                                 "\n"
361                                 "void main (void)\n"
362                                 "{\n"
363                                 "  if (subgroupElect())\n"
364                                 "  {\n"
365                                 "    out_color.r = 71.f;\n" // << 2 * ELECTED_VALUE - UNELECTED_VALUE << ";\n"
366                                 "    out_color.g = 2.0f;\n"
367                                 "  }\n"
368                                 "  else\n"
369                                 "  {\n"
370                                 "    out_color.r = " + unelectedValue.str() + ";\n"
371                                 "    out_color.g = 0.0f;\n"
372                                 "  }\n"
373                                 "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
374                                 "}\n";
375
376                         programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
377                 }
378                 else if (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
379                 {
380                         const string  controlSourceGLSL =
381                                 "#version 450\n"
382                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
383                                 "#extension GL_EXT_tessellation_shader : require\n"
384                                 "layout(vertices = 2) out;\n"
385                                 "layout(location = 0) out vec4 out_color[];\n"
386                                 "void main (void)\n"
387                                 "{\n"
388                                 "  if (gl_InvocationID == 0)\n"
389                                 "  {\n"
390                                 "    gl_TessLevelOuter[0] = 1.0f;\n"
391                                 "    gl_TessLevelOuter[1] = 1.0f;\n"
392                                 "  }\n"
393                                 "  if (subgroupElect())\n"
394                                 "  {\n"
395                                 "    out_color[gl_InvocationID].r = " + electedValue.str() + ";\n"
396                                 "    out_color[gl_InvocationID].g = 1.0f;\n"
397                                 "  }\n"
398                                 "  else\n"
399                                 "  {\n"
400                                 "    out_color[gl_InvocationID].r = " + unelectedValue.str() + ";\n"
401                                 "    out_color[gl_InvocationID].g = 0.0f;\n"
402                                 "  }\n"
403                                 "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
404                                 "}\n";
405
406                         programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
407
408                         const string evaluationSourceGLSL =
409                                 "#version 450\n"
410                                 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
411                                 "#extension GL_EXT_tessellation_shader : require\n"
412                                 "layout(isolines, equal_spacing, ccw ) in;\n"
413                                 "layout(location = 0) in vec4 in_color[];\n"
414                                 "layout(location = 0) out vec4 out_color;\n"
415                                 "\n"
416                                 "void main (void)\n"
417                                 "{\n"
418                                 "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
419                                 "  out_color = in_color[0];\n"
420                                 "}\n";
421
422                         programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
423                 }
424                 else
425                 {
426                         DE_FATAL("Unsupported shader stage");
427                 }
428         }
429         else
430         {
431                 std::ostringstream bdy;
432                 string color = (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage) ? "out_color[gl_InvocationID].b = 1.0f;\n" : "out_color.b = 1.0f;\n";
433                 switch (caseDef.opType)
434                 {
435                         default:
436                                 DE_FATAL("Unhandled op type!");
437                                 break;
438                         case OPTYPE_SUBGROUP_BARRIER:
439                         case OPTYPE_SUBGROUP_MEMORY_BARRIER:
440                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
441                         {
442                                 bdy << "  tempResult2 = tempBuffer[id];\n"
443                                         << "  if (subgroupElect())\n"
444                                         << "  {\n"
445                                         << "    tempResult = value;\n"
446                                         << "    " << color
447                                         << "  }\n"
448                                         << "  else\n"
449                                         << "  {\n"
450                                         << "    tempResult = tempBuffer[id];\n"
451                                         << "  }\n"
452                                         << "  " << getOpTypeName(caseDef.opType) << "();\n";
453                                 break;
454                         }
455                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
456                                 bdy << "  tempResult2 = imageLoad(tempImage, ivec2(id, 0)).x;\n"
457                                         << "  if (subgroupElect())\n"
458                                         << "  {\n"
459                                         << "    tempResult = value;\n"
460                                         << "    " << color
461                                         << "  }\n"
462                                         << "  else\n"
463                                         << "  {\n"
464                                         << "    tempResult = imageLoad(tempImage, ivec2(id, 0)).x;\n"
465                                         << "  }\n"
466                                         << "  subgroupMemoryBarrierImage();\n";
467
468                                 break;
469                 }
470
471                 if (subgroups::SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
472                 {
473                         std::ostringstream      fragment;
474                         fragment        << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
475                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
476                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
477                                 << "layout(location = 0) out vec4 out_color;\n"
478                                 << "\n"
479                                 << "layout(binding = 0) uniform Buffer1\n"
480                                 << "{\n"
481                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
482                                 << "};\n"
483                                 << "\n"
484                                 << "layout(binding = 1) uniform Buffer2\n"
485                                 << "{\n"
486                                 << "  uint value;\n"
487                                 << "};\n"
488                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
489                                 << "void main (void)\n"
490                                 << "{\n"
491                                 << "  if (gl_HelperInvocation) return;\n"
492                                 << "  uint id = 0;\n"
493                                 << "  if (subgroupElect())\n"
494                                 << "  {\n"
495                                 << "    id = uint(gl_FragCoord.x);\n"
496                                 << "  }\n"
497                                 << "  id = subgroupBroadcastFirst(id);\n"
498                                 << "  uint localId = id;\n"
499                                 << "  uint tempResult = 0u;\n"
500                                 << "  uint tempResult2 = 0u;\n"
501                                 << "  out_color.b = 0.0f;\n"
502                                 << bdy.str()
503                                 << "  out_color.r = float(tempResult);\n"
504                                 << "  out_color.g = float(value);\n"
505                                 << "  out_color.a = float(tempResult2);\n"
506                                 << "}\n";
507                         programCollection.add("fragment") << glu::FragmentSource(fragment.str());
508                 }
509                 else if (subgroups::SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
510                 {
511                         std::ostringstream      vertex;
512                         vertex  << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
513                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
514                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
515                                 <<"\n"
516                                 << "layout(location = 0) out vec4 out_color;\n"
517                                 << "layout(location = 0) in highp vec4 in_position;\n"
518                                 << "\n"
519                                 << "layout(binding = 0) uniform Buffer1\n"
520                                 << "{\n"
521                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
522                                 << "};\n"
523                                 << "\n"
524                                 << "layout(binding = 1) uniform Buffer2\n"
525                                 << "{\n"
526                                 << "  uint value;\n"
527                                 << "};\n"
528                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
529                                 << "void main (void)\n"
530                                 << "{\n"
531                                 << "  uint id = 0;\n"
532                                 << "  if (subgroupElect())\n"
533                                 << "  {\n"
534                                 << "    id = gl_VertexID;\n"
535                                 << "  }\n"
536                                 << "  id = subgroupBroadcastFirst(id);\n"
537                                 << "  uint tempResult = 0u;\n"
538                                 << "  uint tempResult2 = 0u;\n"
539                                 << "  out_color.b = 0.0f;\n"
540                                 << bdy.str()
541                                 << "  out_color.r = float(tempResult);\n"
542                                 << "  out_color.g = float(value);\n"
543                                 << "  out_color.a = float(tempResult2);\n"
544                                 << "  gl_Position = in_position;\n"
545                                 << "  gl_PointSize = 1.0f;\n"
546                                 << "}\n";
547                         programCollection.add("vert") << glu::VertexSource(vertex.str());
548                 }
549         else if (subgroups::SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
550                 {
551                         std::ostringstream geometry;
552
553                         geometry << "#version 450\n"
554                                         << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
555                                         << "#extension GL_KHR_shader_subgroup_basic: enable\n"
556                                         << "layout(points) in;\n"
557                                         << "layout(points, max_vertices = 1) out;\n"
558                                         << "layout(location = 0) out vec4 out_color;\n"
559                                         << "layout(binding = 0) uniform Buffer1\n"
560                                         << "{\n"
561                                         << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
562                                         << "};\n"
563                                         << "\n"
564                                         << "layout(binding = 1) uniform Buffer2\n"
565                                         << "{\n"
566                                         << "  uint value;\n"
567                                         << "};\n"
568                                         << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
569                                         << "void main (void)\n"
570                                         << "{\n"
571                                         << "  uint id = 0;\n"
572                                         << "  if (subgroupElect())\n"
573                                         << "  {\n"
574                                         << "    id = gl_InvocationID;\n"
575                                         << "  }\n"
576                                         << "  id = subgroupBroadcastFirst(id);\n"
577                                         << "  uint tempResult = 0u;\n"
578                                         << "  uint tempResult2 = 0u;\n"
579                                         << "  out_color.b = 0.0f;\n"
580                                         << bdy.str()
581                                         << "  out_color.r = float(tempResult);\n"
582                                         << "  out_color.g = float(value);\n"
583                                         << "  out_color.a = float(tempResult2);\n"
584                                         << "  gl_Position = gl_in[0].gl_Position;\n"
585                                         << "  EmitVertex();\n"
586                                         << "  EndPrimitive();\n"
587                                         << "}\n";
588
589                         programCollection.add("geometry") << glu::GeometrySource(geometry.str());
590                 }
591                 else if (subgroups::SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
592                 {
593                         std::ostringstream controlSource;
594                         std::ostringstream evaluationSource;
595
596                         controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
597                                 << "#extension GL_EXT_tessellation_shader : require\n"
598                                 << "layout(vertices = 2) out;\n"
599                                 << "void main (void)\n"
600                                 << "{\n"
601                                 << "  if (gl_InvocationID == 0)\n"
602                                 <<"  {\n"
603                                 << "    gl_TessLevelOuter[0] = 1.0f;\n"
604                                 << "    gl_TessLevelOuter[1] = 1.0f;\n"
605                                 << "  }\n"
606                                 << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
607                                 << "}\n";
608
609                         evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
610                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
611                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
612                                 << "#extension GL_EXT_tessellation_shader : require\n"
613                                 << "layout(isolines, equal_spacing, ccw ) in;\n"
614                                 << "layout(location = 0) out vec4 out_color;\n"
615                                 << "layout(binding = 0) uniform Buffer1\n"
616                                 << "{\n"
617                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
618                                 << "};\n"
619                                 << "\n"
620                                 << "layout(binding = 1) uniform Buffer2\n"
621                                 << "{\n"
622                                 << "  uint value;\n"
623                                 << "};\n"
624                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
625                                 << "void main (void)\n"
626                                 << "{\n"
627                                 << "  uint id = 0;\n"
628                                 << "  if (subgroupElect())\n"
629                                 << "  {\n"
630                                 << "    id = gl_PrimitiveID;\n"
631                                 << "  }\n"
632                                 << "  id = subgroupBroadcastFirst(id);\n"
633                                 << "  uint tempResult = 0u;\n"
634                                 << "  uint tempResult2 = 0u;\n"
635                                 << "  out_color.b = 0.0f;\n"
636                                 << bdy.str()
637                                 << "  out_color.r = float(tempResult);\n"
638                                 << "  out_color.g = float(value);\n"
639                                 << "  out_color.a = float(tempResult2);\n"
640                                 << "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
641                                 << "}\n";
642
643                         programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
644                         programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
645                 }
646                 else if (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
647                 {
648                         std::ostringstream controlSource;
649                         std::ostringstream evaluationSource;
650
651                         controlSource  << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
652                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
653                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
654                                 << "#extension GL_EXT_tessellation_shader : require\n"
655                                 << "layout(vertices = 2) out;\n"
656                                 << "layout(location = 0) out vec4 out_color[];\n"
657                                 << "layout(binding = 0) uniform Buffer1\n"
658                                 << "{\n"
659                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
660                                 << "};\n"
661                                 << "\n"
662                                 << "layout(binding = 1) uniform Buffer2\n"
663                                 << "{\n"
664                                 << "  uint value;\n"
665                                 << "};\n"
666                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
667                                 << "void main (void)\n"
668                                 << "{\n"
669                                 << "  uint id = 0;\n"
670                                 << "  if (gl_InvocationID == 0)\n"
671                                 <<"  {\n"
672                                 << "    gl_TessLevelOuter[0] = 1.0f;\n"
673                                 << "    gl_TessLevelOuter[1] = 1.0f;\n"
674                                 << "  }\n"
675                                 << "  if (subgroupElect())\n"
676                                 << "  {\n"
677                                 << "    id = gl_InvocationID;\n"
678                                 << "  }\n"
679                                 << "  id = subgroupBroadcastFirst(id);\n"
680                                 << "  uint tempResult = 0u;\n"
681                                 << "  uint tempResult2 = 0u;\n"
682                                 << "  out_color[gl_InvocationID].b = 0.0f;\n"
683                                 << bdy.str()
684                                 << "  out_color[gl_InvocationID].r = float(tempResult);\n"
685                                 << "  out_color[gl_InvocationID].g = float(value);\n"
686                                 << "  out_color[gl_InvocationID].a = float(tempResult2);\n"
687                                 << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
688                                 << "}\n";
689
690                         evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
691                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
692                                 << "#extension GL_EXT_tessellation_shader : require\n"
693                                 << "layout(isolines, equal_spacing, ccw ) in;\n"
694                                 << "layout(location = 0) in vec4 in_color[];\n"
695                                 << "layout(location = 0) out vec4 out_color;\n"
696                                 << "\n"
697                                 << "void main (void)\n"
698                                 << "{\n"
699                                 << "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
700                                 << "  out_color = in_color[0];\n"
701                                 << "}\n";
702
703                         programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
704                         programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
705                 }
706                 else
707                 {
708                         DE_FATAL("Unsupported shader stage");
709                 }
710         }
711 }
712
713 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
714 {
715         if (OPTYPE_ELECT == caseDef.opType)
716         {
717                 if (subgroups::SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
718                 {
719                         std::ostringstream src;
720
721                         src << "#version 450\n"
722                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
723                                 << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
724                                 << "layout(binding = 0, std430) buffer Buffer1\n"
725                                 << "{\n"
726                                 << "  uint result[];\n"
727                                 << "};\n"
728                                 << "\n"
729                                 << subgroups::getSharedMemoryBallotHelper()
730                                 << "void main (void)\n"
731                                 << "{\n"
732                                 << "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
733                                 << "  highp uint offset = globalSize.x * ((globalSize.y * "
734                                 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
735                                 "gl_GlobalInvocationID.x;\n"
736                                 << "  uint value = " << UNELECTED_VALUE << ";\n"
737                                 << "  if (subgroupElect())\n"
738                                 << "  {\n"
739                                 << "    value = " << ELECTED_VALUE << ";\n"
740                                 << "  }\n"
741                                 << "  uvec4 bits = bitCount(sharedMemoryBallot(value == " << ELECTED_VALUE << "));\n"
742                                 << "  result[offset] = bits.x + bits.y + bits.z + bits.w;\n"
743                                 << "}\n";
744
745                         programCollection.add("comp") << glu::ComputeSource(src.str());
746                 }
747                 else
748                 {
749                         {
750                                 std::ostringstream  vertex;
751                                 vertex  << "#version 450\n"
752                                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
753                                                 << "layout(binding = 0, std430) buffer Buffer0\n"
754                                                 << "{\n"
755                                                 << "  uint result[];\n"
756                                                 << "} b0;\n"
757                                                 << "layout(binding = 4, std430) buffer Buffer4\n"
758                                                 << "{\n"
759                                                 << "  uint numSubgroupsExecuted;\n"
760                                                 << "} b4;\n"
761                                                 << "\n"
762                                                 << "void main (void)\n"
763                                                 << "{\n"
764                                                 << "  if (subgroupElect())\n"
765                                                 << "  {\n"
766                                                 << "    b0.result[gl_VertexID] = " << ELECTED_VALUE << ";\n"
767                                                 << "    atomicAdd(b4.numSubgroupsExecuted, 1);\n"
768                                                 << "  }\n"
769                                                 << "  else\n"
770                                                 << "  {\n"
771                                                 << "    b0.result[gl_VertexID] = " << UNELECTED_VALUE << ";\n"
772                                                 << "  }\n"
773                                                 << "  float pixelSize = 2.0f/1024.0f;\n"
774                                                 << "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
775                                                 << "  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
776                                                 << "  gl_PointSize = 1.0f;\n"
777                                                 << "}\n";
778                                 programCollection.add("vert") << glu::VertexSource(vertex.str());
779                         }
780
781                         {
782                                 std::ostringstream tesc;
783                                 tesc    << "#version 450\n"
784                                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
785                                                 << "layout(vertices=1) out;\n"
786                                                 << "layout(binding = 1, std430) buffer Buffer1\n"
787                                                 << "{\n"
788                                                 << "  uint result[];\n"
789                                                 << "} b1;\n"
790                                                 << "layout(binding = 5, std430) buffer Buffer5\n"
791                                                 << "{\n"
792                                                 << "  uint numSubgroupsExecuted;\n"
793                                                 << "} b5;\n"
794                                                 << "\n"
795                                                 << "void main (void)\n"
796                                                 << "{\n"
797                                                 << "  if (subgroupElect())\n"
798                                                 << "  {\n"
799                                                 << "    b1.result[gl_PrimitiveID] = " << ELECTED_VALUE << ";\n"
800                                                 << "    atomicAdd(b5.numSubgroupsExecuted, 1);\n"
801                                                 << "  }\n"
802                                                 << "  else\n"
803                                                 << "  {\n"
804                                                 << "    b1.result[gl_PrimitiveID] = " << UNELECTED_VALUE << ";\n"
805                                                 << "  }\n"
806                                                 << "  if (gl_InvocationID == 0)\n"
807                                                 << "  {\n"
808                                                 << "    gl_TessLevelOuter[0] = 1.0f;\n"
809                                                 << "    gl_TessLevelOuter[1] = 1.0f;\n"
810                                                 << "  }\n"
811                                                 << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
812                                                 << "}\n";
813                                 programCollection.add("tesc") << glu::TessellationControlSource(tesc.str());
814                         }
815
816                         {
817                                 std::ostringstream tese;
818                                 tese    << "#version 450\n"
819                                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
820                                                 << "layout(isolines) in;\n"
821                                                 << "layout(binding = 2, std430) buffer Buffer2\n"
822                                                 << "{\n"
823                                                 << "  uint result[];\n"
824                                                 << "} b2;\n"
825                                                 << "layout(binding = 6, std430) buffer Buffer6\n"
826                                                 << "{\n"
827                                                 << "  uint numSubgroupsExecuted;\n"
828                                                 << "} b6;\n"
829                                                 << "\n"
830                                                 << "void main (void)\n"
831                                                 << "{\n"
832                                                 << "  if (subgroupElect())\n"
833                                                 << "  {\n"
834                                                 << "    b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << ELECTED_VALUE << ";\n"
835                                                 << "    atomicAdd(b6.numSubgroupsExecuted, 1);\n"
836                                                 << "  }\n"
837                                                 << "  else\n"
838                                                 << "  {\n"
839                                                 << "    b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << UNELECTED_VALUE << ";\n"
840                                                 << "  }\n"
841                                                 << "  float pixelSize = 2.0f/1024.0f;\n"
842                                                 << "  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
843                                                 << "}\n";
844                                 programCollection.add("tese") << glu::TessellationEvaluationSource(tese.str());
845                         }
846                         {
847                                 std::ostringstream geometry;
848                                 geometry        << "#version 450\n"
849                                                         << "#extension GL_KHR_shader_subgroup_basic: enable\n"
850                                                         << "layout(${TOPOLOGY}) in;\n"
851                                                         << "layout(points, max_vertices = 1) out;\n"
852                                                         << "layout(binding = 3, std430) buffer Buffer3\n"
853                                                         << "{\n"
854                                                         << "  uint result[];\n"
855                                                         << "} b3;\n"
856                                                         << "layout(binding = 7, std430) buffer Buffer7\n"
857                                                         << "{\n"
858                                                         << "  uint numSubgroupsExecuted;\n"
859                                                         << "} b7;\n"
860                                                         << "\n"
861                                                         << "void main (void)\n"
862                                                         << "{\n"
863                                                         << "  if (subgroupElect())\n"
864                                                         << "  {\n"
865                                                         << "    b3.result[gl_PrimitiveIDIn] = " << ELECTED_VALUE << ";\n"
866                                                         << "    atomicAdd(b7.numSubgroupsExecuted, 1);\n"
867                                                         << "  }\n"
868                                                         << "  else\n"
869                                                         << "  {\n"
870                                                         << "    b3.result[gl_PrimitiveIDIn] = " << UNELECTED_VALUE << ";\n"
871                                                         << "  }\n"
872                                                         << "  gl_Position = gl_in[0].gl_Position;\n"
873                                                         << "  EmitVertex();\n"
874                                                         << "  EndPrimitive();\n"
875                                                         << "}\n";
876                                 subgroups::addGeometryShadersFromTemplate(geometry.str(), programCollection);
877                         }
878
879                         {
880                                 std::ostringstream fragment;
881                                 fragment        << "#version 450\n"
882                                                         << "#extension GL_KHR_shader_subgroup_basic: enable\n"
883                                                         << "layout(location = 0) out uint data;\n"
884                                                         << "layout(binding = 8, std430) buffer Buffer8\n"
885                                                         << "{\n"
886                                                         << "  uint numSubgroupsExecuted;\n"
887                                                         << "} b8;\n"
888                                                         << "void main (void)\n"
889                                                         << "{\n"
890                                                         << "  if (gl_HelperInvocation) return;\n"
891                                                         << "  if (subgroupElect())\n"
892                                                         << "  {\n"
893                                                         << "    data = " << ELECTED_VALUE << ";\n"
894                                                         << "    atomicAdd(b8.numSubgroupsExecuted, 1);\n"
895                                                         << "  }\n"
896                                                         << "  else\n"
897                                                         << "  {\n"
898                                                         << "    data = " << UNELECTED_VALUE << ";\n"
899                                                         << "  }\n"
900                                                         << "}\n";
901                                 programCollection.add("fragment") << glu::FragmentSource(fragment.str());
902                         }
903                         subgroups::addNoSubgroupShader(programCollection);
904                 }
905         }
906         else
907         {
908                 std::ostringstream bdy;
909
910                 switch (caseDef.opType)
911                 {
912                         default:
913                                 DE_FATAL("Unhandled op type!");
914                                 break;
915                         case OPTYPE_SUBGROUP_BARRIER:
916                         case OPTYPE_SUBGROUP_MEMORY_BARRIER:
917                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
918                                 bdy << "  if (subgroupElect())\n"
919                                         << "  {\n"
920                                         << "    b${SSBO1}.tempBuffer[id] = b${SSBO2}.value;\n"
921                                         << "  }\n"
922                                         << "  " << getOpTypeName(caseDef.opType) << "();\n"
923                                         << "  tempResult = b${SSBO1}.tempBuffer[id];\n";
924                                 break;
925                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
926                                 bdy << "  if (subgroupElect())\n"
927                                         << "  {\n"
928                                         << "    tempShared[localId] = b${SSBO2}.value;\n"
929                                         << "  }\n"
930                                         << "  subgroupMemoryBarrierShared();\n"
931                                         << "  tempResult = tempShared[localId];\n";
932                                 break;
933                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
934                                 bdy << "  if (subgroupElect())\n"
935                                         << "  {\n"
936                                         << "    imageStore(tempImage${IMG1}, ivec2(id, 0), ivec4(b${SSBO2}.value));\n"
937                                         << "  }\n"
938                                         << "  subgroupMemoryBarrierImage();\n"
939                                         << "  tempResult = imageLoad(tempImage${IMG1}, ivec2(id, 0)).x;\n";
940                                 break;
941                 }
942
943                 tcu::StringTemplate bdyTemplate(bdy.str());
944
945                 if (subgroups::SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
946                 {
947                         std::ostringstream src;
948                         map<string, string> bufferNameMapping;
949                         bufferNameMapping.insert(pair<string, string>("SSBO1", "1"));
950                         bufferNameMapping.insert(pair<string, string>("SSBO2", "2"));
951                         bufferNameMapping.insert(pair<string, string>("IMG1", "0"));
952
953                         src << "#version 450\n"
954                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
955                                 << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
956                                 << "layout(binding = 0, std430) buffer Buffer0\n"
957                                 << "{\n"
958                                 << "  uint result[];\n"
959                                 << "} b0;\n"
960                                 << "layout(binding = 1, std430) buffer Buffer1\n"
961                                 << "{\n"
962                                 << "  uint tempBuffer[];\n"
963                                 << "} b1;\n"
964                                 << "layout(binding = 2, std430) buffer Buffer2\n"
965                                 << "{\n"
966                                 << "  uint value;\n"
967                                 << "} b2;\n"
968                                 << "layout(binding = 0, r32ui) uniform uimage2D tempImage0;\n"
969                                 << "shared uint tempShared[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
970                                 << "\n"
971                                 << "void main (void)\n"
972                                 << "{\n"
973                                 << "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
974                                 << "  highp uint offset = globalSize.x * ((globalSize.y * "
975                                 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
976                                 "gl_GlobalInvocationID.x;\n"
977                                 << "  uint localId = gl_SubgroupID;\n"
978                                 << "  uint id = globalSize.x * ((globalSize.y * "
979                                 "gl_WorkGroupID.z) + gl_WorkGroupID.y) + "
980                                 "gl_WorkGroupID.x + localId;\n"
981                                 << "  uint tempResult = 0;\n"
982                                 << bdyTemplate.specialize(bufferNameMapping)
983                                 << "  b0.result[offset] = tempResult;\n"
984                                 << "}\n";
985
986                         programCollection.add("comp") << glu::ComputeSource(src.str());
987                 }
988                 else
989                 {
990                         {
991                                 map<string, string> bufferNameMapping;
992                                 bufferNameMapping.insert(pair<string, string>("SSBO1", "4"));
993                                 bufferNameMapping.insert(pair<string, string>("SSBO2", "6"));
994                                 bufferNameMapping.insert(pair<string, string>("IMG1", "0"));
995
996                                 const string vertex =
997                                         "#version 450\n"
998                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
999                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1000                                         "layout(binding = 0, std430) buffer Buffer0\n"
1001                                         "{\n"
1002                                         "  uint result[];\n"
1003                                         "} b0;\n"
1004                                         "layout(binding = 4, std430) buffer Buffer4\n"
1005                                         "{\n"
1006                                         "  uint tempBuffer[];\n"
1007                                         "} b4;\n"
1008                                         "layout(binding = 5, std430) buffer Buffer5\n"
1009                                         "{\n"
1010                                         "  uint subgroupID;\n"
1011                                         "} b5;\n"
1012                                         "layout(binding = 6, std430) buffer Buffer6\n"
1013                                         "{\n"
1014                                         "  uint value;\n"
1015                                         "} b6;\n"
1016                                         "layout(binding = 0, r32ui) uniform uimage2D tempImage0;\n"
1017                                         "void main (void)\n"
1018                                         "{\n"
1019                                         "  uint id = 0;\n"
1020                                         "  if (subgroupElect())\n"
1021                                         "  {\n"
1022                                         "    id = atomicAdd(b5.subgroupID, 1);\n"
1023                                         "  }\n"
1024                                         "  id = subgroupBroadcastFirst(id);\n"
1025                                         "  uint localId = id;\n"
1026                                         "  uint tempResult = 0;\n"
1027                                         + bdyTemplate.specialize(bufferNameMapping) +
1028                                         "  b0.result[gl_VertexID] = tempResult;\n"
1029                                         "  float pixelSize = 2.0f/1024.0f;\n"
1030                                         "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
1031                                         "  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
1032                                         "  gl_PointSize = 1.0f;\n"
1033                                         "}\n";
1034                                 programCollection.add("vert") << glu::VertexSource(vertex);
1035                         }
1036
1037                         {
1038                                 map<string, string> bufferNameMapping;
1039                                 bufferNameMapping.insert(pair<string, string>("SSBO1", "7"));
1040                                 bufferNameMapping.insert(pair<string, string>("SSBO2", "9"));
1041                                 bufferNameMapping.insert(pair<string, string>("IMG1", "1"));
1042
1043                                 const string tesc =
1044                                         "#version 450\n"
1045                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1046                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1047                                         "layout(vertices=1) out;\n"
1048                                         "layout(binding = 1, std430) buffer Buffer1\n"
1049                                         "{\n"
1050                                         "  uint result[];\n"
1051                                         "} b1;\n"
1052                                         "layout(binding = 7, std430) buffer Buffer7\n"
1053                                         "{\n"
1054                                         "  uint tempBuffer[];\n"
1055                                         "} b7;\n"
1056                                         "layout(binding = 8, std430) buffer Buffer8\n"
1057                                         "{\n"
1058                                         "  uint subgroupID;\n"
1059                                         "} b8;\n"
1060                                         "layout(binding = 9, std430) buffer Buffer9\n"
1061                                         "{\n"
1062                                         "  uint value;\n"
1063                                         "} b9;\n"
1064                                         "layout(binding = 1, r32ui) uniform uimage2D tempImage1;\n"
1065                                         "void main (void)\n"
1066                                         "{\n"
1067                                         "  uint id = 0;\n"
1068                                         "  if (subgroupElect())\n"
1069                                         "  {\n"
1070                                         "    id = atomicAdd(b8.subgroupID, 1);\n"
1071                                         "  }\n"
1072                                         "  id = subgroupBroadcastFirst(id);\n"
1073                                         "  uint localId = id;\n"
1074                                         "  uint tempResult = 0;\n"
1075                                         + bdyTemplate.specialize(bufferNameMapping) +
1076                                         "  b1.result[gl_PrimitiveID] = tempResult;\n"
1077                                         "  if (gl_InvocationID == 0)\n"
1078                                         "  {\n"
1079                                         "    gl_TessLevelOuter[0] = 1.0f;\n"
1080                                         "    gl_TessLevelOuter[1] = 1.0f;\n"
1081                                         "  }\n"
1082                                         "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1083                                         "}\n";
1084                                 programCollection.add("tesc") << glu::TessellationControlSource(tesc);
1085                         }
1086
1087                         {
1088                                 map<string, string> bufferNameMapping;
1089                                 bufferNameMapping.insert(pair<string, string>("SSBO1", "10"));
1090                                 bufferNameMapping.insert(pair<string, string>("SSBO2", "12"));
1091                                 bufferNameMapping.insert(pair<string, string>("IMG1", "2"));
1092
1093                                 const string tese =
1094                                         "#version 450\n"
1095                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1096                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1097                                         "layout(isolines) in;\n"
1098                                         "layout(binding = 2, std430) buffer Buffer2\n"
1099                                         "{\n"
1100                                         "  uint result[];\n"
1101                                         "} b2;\n"
1102                                         "layout(binding = 10, std430) buffer Buffer10\n"
1103                                         "{\n"
1104                                         "  uint tempBuffer[];\n"
1105                                         "} b10;\n"
1106                                         "layout(binding = 11, std430) buffer Buffer11\n"
1107                                         "{\n"
1108                                         "  uint subgroupID;\n"
1109                                         "} b11;\n"
1110                                         "layout(binding = 12, std430) buffer Buffer12\n"
1111                                         "{\n"
1112                                         "  uint value;\n"
1113                                         "} b12;\n"
1114                                         "layout(binding = 2, r32ui) uniform uimage2D tempImage2;\n"
1115                                         "void main (void)\n"
1116                                         "{\n"
1117                                         "  uint id = 0;\n"
1118                                         "  if (subgroupElect())\n"
1119                                         "  {\n"
1120                                         "    id = atomicAdd(b11.subgroupID, 1);\n"
1121                                         "  }\n"
1122                                         "  id = subgroupBroadcastFirst(id);\n"
1123                                         "  uint localId = id;\n"
1124                                         "  uint tempResult = 0;\n"
1125                                         + bdyTemplate.specialize(bufferNameMapping) +
1126                                         "  b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
1127                                         "  float pixelSize = 2.0f/1024.0f;\n""  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
1128                                         "}\n";
1129                                 programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
1130                         }
1131                         {
1132                                 map<string, string> bufferNameMapping;
1133                                 bufferNameMapping.insert(pair<string, string>("SSBO1", "13"));
1134                                 bufferNameMapping.insert(pair<string, string>("SSBO2", "15"));
1135                                 bufferNameMapping.insert(pair<string, string>("IMG1", "3"));
1136
1137                                 const string geometry =
1138                                         "#version 450\n"
1139                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1140                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1141                                         "layout(${TOPOLOGY}) in;\n"
1142                                         "layout(points, max_vertices = 1) out;\n"
1143                                         "layout(binding = 3, std430) buffer Buffer3\n"
1144                                         "{\n"
1145                                         "  uint result[];\n"
1146                                         "} b3;\n"
1147                                         "layout(binding = 13, std430) buffer Buffer13\n"
1148                                         "{\n"
1149                                         "  uint tempBuffer[];\n"
1150                                         "} b13;\n"
1151                                         "layout(binding = 14, std430) buffer Buffer14\n"
1152                                         "{\n"
1153                                         "  uint subgroupID;\n"
1154                                         "} b14;\n"
1155                                         "layout(binding = 15, std430) buffer Buffer15\n"
1156                                         "{\n"
1157                                         "  uint value;\n"
1158                                         "} b15;\n"
1159                                         "layout(binding = 3, r32ui) uniform uimage2D tempImage3;\n"
1160                                         "void main (void)\n"
1161                                         "{\n"
1162                                         "  uint id = 0;\n"
1163                                         "  if (subgroupElect())\n"
1164                                         "  {\n"
1165                                         "    id = atomicAdd(b14.subgroupID, 1);\n"
1166                                         "  }\n"
1167                                         "  id = subgroupBroadcastFirst(id);\n"
1168                                         "  uint localId = id;\n"
1169                                         "  uint tempResult = 0;\n"
1170                                          + bdyTemplate.specialize(bufferNameMapping) +
1171                                         "  b3.result[gl_PrimitiveIDIn] = tempResult;\n"
1172                                         "  gl_Position = gl_in[0].gl_Position;\n"
1173                                         "  EmitVertex();\n"
1174                                         "  EndPrimitive();\n"
1175                                         "}\n";
1176                                 subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
1177                         }
1178
1179                         {
1180                                 map<string, string> bufferNameMapping;
1181                                 bufferNameMapping.insert(pair<string, string>("SSBO1", "16"));
1182                                 bufferNameMapping.insert(pair<string, string>("SSBO2", "18"));
1183                                 bufferNameMapping.insert(pair<string, string>("IMG1", "4"));
1184
1185                                 const string fragment =
1186                                         "#version 450\n"
1187                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1188                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1189                                         "layout(location = 0) out uint result;\n"
1190                                         "layout(binding = 16, std430) buffer Buffer16\n"
1191                                         "{\n"
1192                                         "  uint tempBuffer[];\n"
1193                                         "} b16;\n"
1194                                         "layout(binding = 17, std430) buffer Buffer17\n"
1195                                         "{\n"
1196                                         "  uint subgroupID;\n"
1197                                         "} b17;\n"
1198                                         "layout(binding = 18, std430) buffer Buffer18\n"
1199                                         "{\n"
1200                                         "  uint value;\n"
1201                                         "} b18;\n"
1202                                         "layout(binding = 4, r32ui) uniform uimage2D tempImage4;\n"
1203                                         "void main (void)\n"
1204                                         "{\n"
1205                                         "  if (gl_HelperInvocation) return;\n"
1206                                         "  uint id = 0;\n"
1207                                         "  if (subgroupElect())\n"
1208                                         "  {\n"
1209                                         "    id = atomicAdd(b17.subgroupID, 1);\n"
1210                                         "  }\n"
1211                                         "  id = subgroupBroadcastFirst(id);\n"
1212                                         "  uint localId = id;\n"
1213                                         "  uint tempResult = 0;\n"
1214                                         + bdyTemplate.specialize(bufferNameMapping) +
1215                                         "  result = tempResult;\n"
1216                                         "}\n";
1217                                 programCollection.add("fragment") << glu::FragmentSource(fragment);
1218                         }
1219
1220                 subgroups::addNoSubgroupShader(programCollection);
1221                 }
1222         }
1223 }
1224
1225 void supportedCheck (Context& context, CaseDefinition caseDef)
1226 {
1227         DE_UNREF(caseDef);
1228         if (!subgroups::isSubgroupSupported(context))
1229                 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
1230 }
1231
1232 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
1233 {
1234         if (!subgroups::areSubgroupOperationsSupportedForStage(
1235                                 context, caseDef.shaderStage))
1236         {
1237                 if (subgroups::areSubgroupOperationsRequiredForStage(
1238                                         caseDef.shaderStage))
1239                 {
1240                         return tcu::TestStatus::fail(
1241                                            "Shader stage " +
1242                                            subgroups::getShaderStageName(caseDef.shaderStage) +
1243                                            " is required to support subgroup operations!");
1244                 }
1245                 else
1246                 {
1247                         TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
1248                 }
1249         }
1250
1251         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BASIC_BIT))
1252         {
1253                 return tcu::TestStatus::fail(
1254                                    "Subgroup feature " +
1255                                    subgroups::getSubgroupFeatureName(subgroups::SUBGROUP_FEATURE_BASIC_BIT) +
1256                                    " is a required capability!");
1257         }
1258
1259         if (OPTYPE_ELECT != caseDef.opType && subgroups::SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1260         {
1261                 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BALLOT_BIT))
1262                 {
1263                         TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1264                 }
1265         }
1266
1267         const deUint32                                          inputDatasCount = OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? 3u : 2u;
1268         std::vector<subgroups::SSBOData>        inputDatas              (inputDatasCount);
1269
1270         inputDatas[0].format = subgroups::FORMAT_R32_UINT;
1271         inputDatas[0].numElements = SHADER_BUFFER_SIZE/4ull;
1272         inputDatas[0].initializeType = subgroups::SSBOData::InitializeNonZero;
1273         inputDatas[0].binding = 0u;
1274
1275         inputDatas[1].format = subgroups::FORMAT_R32_UINT;
1276         inputDatas[1].numElements = 1ull;
1277         inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1278         inputDatas[1].binding = 1u;
1279
1280         if(OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType )
1281         {
1282                 inputDatas[2].format = subgroups::FORMAT_R32_UINT;
1283                 inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1284                 inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1285                 inputDatas[2].isImage = true;
1286                 inputDatas[2].binding = 0u;
1287         }
1288
1289         if (subgroups::SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
1290         {
1291                 if (OPTYPE_ELECT == caseDef.opType)
1292                         return subgroups::makeVertexFrameBufferTest(context, subgroups::FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1293                 else
1294                         return subgroups::makeVertexFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkVertexPipelineStagesSubgroupBarriersNoSSBO);
1295         }
1296         else if (subgroups::SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
1297         {
1298                 return subgroups::makeFragmentFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkFragmentSubgroupBarriersNoSSBO);
1299         }
1300         else if (subgroups::SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
1301         {
1302                 if (OPTYPE_ELECT == caseDef.opType)
1303                         return subgroups::makeGeometryFrameBufferTest(context, subgroups::FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1304                 else
1305                         return subgroups::makeGeometryFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkVertexPipelineStagesSubgroupBarriersNoSSBO);
1306         }
1307
1308         if (OPTYPE_ELECT == caseDef.opType)
1309                 return subgroups::makeTessellationEvaluationFrameBufferTest(context, subgroups::FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO, caseDef.shaderStage);
1310
1311         return subgroups::makeTessellationEvaluationFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount,
1312                 (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)? checkVertexPipelineStagesSubgroupBarriersNoSSBO : checkTessellationEvaluationSubgroupBarriersNoSSBO,
1313                 caseDef.shaderStage);
1314 }
1315
1316 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
1317 {
1318         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BASIC_BIT))
1319         {
1320                 return tcu::TestStatus::fail(
1321                                         "Subgroup feature " +
1322                                         subgroups::getSubgroupFeatureName(subgroups::SUBGROUP_FEATURE_BASIC_BIT) +
1323                                         " is a required capability!");
1324         }
1325
1326         if (OPTYPE_ELECT != caseDef.opType && subgroups::SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1327         {
1328                 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BALLOT_BIT))
1329                 {
1330                         TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1331                 }
1332         }
1333
1334         if (subgroups::SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1335         {
1336                 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
1337                 {
1338                                 return tcu::TestStatus::fail("Shader stage " +
1339                                                                                 subgroups::getShaderStageName(caseDef.shaderStage) +
1340                                                                                 " is required to support subgroup operations!");
1341                 }
1342
1343                 if (OPTYPE_ELECT == caseDef.opType)
1344                 {
1345                         return subgroups::makeComputeTest(context, subgroups::FORMAT_R32_UINT, DE_NULL, 0, checkComputeSubgroupElect);
1346                 }
1347                 else
1348                 {
1349                         const deUint32 inputDatasCount = 3;
1350                         subgroups::SSBOData inputDatas[inputDatasCount];
1351                         inputDatas[0].format = subgroups::FORMAT_R32_UINT;
1352                         inputDatas[0].numElements = SHADER_BUFFER_SIZE;
1353                         inputDatas[0].initializeType = subgroups::SSBOData::InitializeNone;
1354                         inputDatas[0].binding = 1u;
1355
1356                         inputDatas[1].format = subgroups::FORMAT_R32_UINT;
1357                         inputDatas[1].numElements = 1;
1358                         inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1359                         inputDatas[1].binding = 2u;
1360
1361                         inputDatas[2].format = subgroups::FORMAT_R32_UINT;
1362                         inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1363                         inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1364                         inputDatas[2].isImage = true;
1365                         inputDatas[2].binding = 0u;
1366
1367                         return subgroups::makeComputeTest(context, subgroups::FORMAT_R32_UINT, inputDatas, inputDatasCount, checkComputeSubgroupBarriers);
1368                 }
1369         }
1370         else
1371         {
1372                 if (!subgroups::isFragmentSSBOSupportedForDevice(context))
1373                 {
1374                         TCU_THROW(NotSupportedError, "Subgroup basic operation require that the fragment stage be able to write to SSBOs!");
1375                 }
1376
1377                 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
1378
1379                 subgroups::ShaderStageFlags stages = (subgroups::ShaderStageFlags)(caseDef.shaderStage & supportedStages);
1380
1381                 if ( subgroups::SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
1382                 {
1383                         if ( (stages & subgroups::SHADER_STAGE_FRAGMENT_BIT) == 0)
1384                                 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
1385                         else
1386                                 stages = subgroups::SHADER_STAGE_FRAGMENT_BIT;
1387                 }
1388
1389                 if ((subgroups::ShaderStageFlags)0u == stages)
1390                         TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
1391
1392                 if (OPTYPE_ELECT == caseDef.opType)
1393                 {
1394                         const deUint32 inputCount = 5u;
1395                         subgroups::SSBOData inputData[inputCount];
1396
1397                         inputData[0].format                     = subgroups::FORMAT_R32_UINT;
1398                         inputData[0].numElements        = 1;
1399                         inputData[0].initializeType     = subgroups::SSBOData::InitializeZero;
1400                         inputData[0].binding            = 4u;
1401                         inputData[0].stages                     = subgroups::SHADER_STAGE_VERTEX_BIT;
1402
1403                         inputData[1].format                     = subgroups::FORMAT_R32_UINT;
1404                         inputData[1].numElements        = 1;
1405                         inputData[1].initializeType     = subgroups::SSBOData::InitializeZero;
1406                         inputData[1].binding            = 5u;
1407                         inputData[1].stages                     = subgroups::SHADER_STAGE_TESS_CONTROL_BIT;
1408
1409                         inputData[2].format                     = subgroups::FORMAT_R32_UINT;
1410                         inputData[2].numElements        = 1;
1411                         inputData[2].initializeType     = subgroups::SSBOData::InitializeZero;
1412                         inputData[2].binding            = 6u;
1413                         inputData[2].stages                     = subgroups::SHADER_STAGE_TESS_EVALUATION_BIT;
1414
1415                         inputData[3].format                     = subgroups::FORMAT_R32_UINT;
1416                         inputData[3].numElements        = 1;
1417                         inputData[3].initializeType     = subgroups::SSBOData::InitializeZero;
1418                         inputData[3].binding            = 7u;
1419                         inputData[3].stages                     = subgroups::SHADER_STAGE_GEOMETRY_BIT;
1420
1421                         inputData[4].format                     = subgroups::FORMAT_R32_UINT;
1422                         inputData[4].numElements        = 1;
1423                         inputData[4].initializeType     = subgroups::SSBOData::InitializeZero;
1424                         inputData[4].binding            = 8u;
1425                         inputData[4].stages                     = subgroups::SHADER_STAGE_FRAGMENT_BIT;
1426
1427                         return subgroups::allStages(context, subgroups::FORMAT_R32_UINT, inputData, inputCount, checkVertexPipelineStagesSubgroupElect, stages);
1428                 }
1429                 else
1430                 {
1431                         const subgroups::ShaderStageFlags stagesBits[] =
1432                         {
1433                                 subgroups::SHADER_STAGE_VERTEX_BIT,
1434                                 subgroups::SHADER_STAGE_TESS_CONTROL_BIT,
1435                                 subgroups::SHADER_STAGE_TESS_EVALUATION_BIT,
1436                                 subgroups::SHADER_STAGE_GEOMETRY_BIT,
1437                                 subgroups::SHADER_STAGE_FRAGMENT_BIT,
1438                         };
1439
1440                         const deUint32 inputDatasCount = DE_LENGTH_OF_ARRAY(stagesBits) * 4u;
1441                         subgroups::SSBOData inputDatas[inputDatasCount];
1442
1443                         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stagesBits); ++ndx)
1444                         {
1445                                 const deUint32 index = ndx*4;
1446                                 const deUint32 ssboIndex = ndx*3;
1447                                 const deUint32 imgIndex = ndx;
1448                                 inputDatas[index].format                                = subgroups::FORMAT_R32_UINT;
1449                                 inputDatas[index].numElements                   = SHADER_BUFFER_SIZE;
1450                                 inputDatas[index].initializeType                = subgroups::SSBOData::InitializeNonZero;
1451                                 inputDatas[index].binding                               = ssboIndex + 4u;
1452                                 inputDatas[index].stages                                = stagesBits[ndx];
1453
1454                                 inputDatas[index + 1].format                    = subgroups::FORMAT_R32_UINT;
1455                                 inputDatas[index + 1].numElements               = 1;
1456                                 inputDatas[index + 1].initializeType    = subgroups::SSBOData::InitializeZero;
1457                                 inputDatas[index + 1].binding                   = ssboIndex + 5u;
1458                                 inputDatas[index + 1].stages                    = stagesBits[ndx];
1459
1460                                 inputDatas[index + 2].format                    = subgroups::FORMAT_R32_UINT;
1461                                 inputDatas[index + 2].numElements               = 1;
1462                                 inputDatas[index + 2].initializeType    = subgroups::SSBOData::InitializeNonZero;
1463                                 inputDatas[index + 2].binding                   = ssboIndex + 6u;
1464                                 inputDatas[index + 2].stages                    = stagesBits[ndx];
1465
1466                                 inputDatas[index + 3].format                    = subgroups::FORMAT_R32_UINT;
1467                                 inputDatas[index + 3].numElements               = SHADER_BUFFER_SIZE;
1468                                 inputDatas[index + 3].initializeType    = subgroups::SSBOData::InitializeNone;
1469                                 inputDatas[index + 3].isImage                   = true;
1470                                 inputDatas[index + 3].binding                   = imgIndex;
1471                                 inputDatas[index + 3].stages                    = stagesBits[ndx];
1472                         }
1473
1474                         return subgroups::allStages(context, subgroups::FORMAT_R32_UINT, inputDatas, inputDatasCount, checkVertexPipelineStagesSubgroupBarriers, stages);
1475                 }
1476         }
1477 }
1478 }
1479
1480 deqp::TestCaseGroup* createSubgroupsBasicTests(deqp::Context& testCtx)
1481 {
1482         de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
1483                 testCtx, "graphics", "Subgroup basic category tests: graphics"));
1484         de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
1485                 testCtx, "compute", "Subgroup basic category tests: compute"));
1486         de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
1487                 testCtx, "framebuffer", "Subgroup basic category tests: framebuffer"));
1488
1489         const subgroups::ShaderStageFlags stages[] =
1490         {
1491                 SHADER_STAGE_FRAGMENT_BIT,
1492                 SHADER_STAGE_VERTEX_BIT,
1493                 SHADER_STAGE_TESS_EVALUATION_BIT,
1494                 SHADER_STAGE_TESS_CONTROL_BIT,
1495                 SHADER_STAGE_GEOMETRY_BIT,
1496         };
1497
1498         for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
1499         {
1500                 const std::string op = de::toLower(getOpTypeName(opTypeIndex));
1501
1502                 {
1503                         const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT};
1504                         SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), op, "",
1505                                                                                 supportedCheck, initPrograms, test, caseDef);
1506                 }
1507
1508                 if (OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED == opTypeIndex)
1509                 {
1510                         // Shared isn't available in non compute shaders.
1511                         continue;
1512                 }
1513
1514                 {
1515                         const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS};
1516                         SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(),
1517                                                                                 op, "",
1518                                                                                 supportedCheck, initPrograms, test, caseDef);
1519                 }
1520
1521                 if (OPTYPE_ELECT == opTypeIndex)
1522                 {
1523                         for (int stageIndex = 1; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
1524                         {
1525                                 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex]};
1526                                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
1527                                                         op + "_" + getShaderStageName(caseDef.shaderStage), "",
1528                                                         supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
1529                         }
1530                 }
1531                 else
1532                 {
1533                         for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
1534                         {
1535                                 const CaseDefinition caseDefFrag = {opTypeIndex, stages[stageIndex]};
1536                                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
1537                                                         op + "_" + getShaderStageName(caseDefFrag.shaderStage), "",
1538                                                         supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDefFrag);
1539                         }
1540                 }
1541
1542         }
1543
1544         de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
1545                 testCtx, "basic", "Subgroup basic category tests"));
1546
1547         group->addChild(graphicGroup.release());
1548         group->addChild(computeGroup.release());
1549         group->addChild(framebufferGroup.release());
1550
1551         return group.release();
1552 }
1553
1554 } // subgroups
1555 } // glc