xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/subgroups/glcSubgroupsShuffleTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * OpenGL Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017-2019 The Khronos Group Inc.
6  * Copyright (c) 2017 Codeplay Software Ltd.
7  * Copyright (c) 2019 NVIDIA Corporation.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */ /*!
22  * \file
23  * \brief Subgroups Tests
24  */ /*--------------------------------------------------------------------*/
25 
26 #include "glcSubgroupsShuffleTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
28 
29 #include <string>
30 #include <vector>
31 
32 using namespace tcu;
33 using namespace std;
34 
35 namespace glc
36 {
37 namespace subgroups
38 {
39 namespace
40 {
41 enum OpType
42 {
43     OPTYPE_SHUFFLE = 0,
44     OPTYPE_SHUFFLE_XOR,
45     OPTYPE_SHUFFLE_UP,
46     OPTYPE_SHUFFLE_DOWN,
47     OPTYPE_LAST
48 };
49 
checkVertexPipelineStages(std::vector<const void * > datas,uint32_t width,uint32_t)50 static bool checkVertexPipelineStages(std::vector<const void *> datas, uint32_t width, uint32_t)
51 {
52     return glc::subgroups::check(datas, width, 1);
53 }
54 
checkComputeStage(std::vector<const void * > datas,const uint32_t numWorkgroups[3],const uint32_t localSize[3],uint32_t)55 static bool checkComputeStage(std::vector<const void *> datas, const uint32_t numWorkgroups[3],
56                               const uint32_t localSize[3], uint32_t)
57 {
58     return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
59 }
60 
getOpTypeName(int opType)61 std::string getOpTypeName(int opType)
62 {
63     switch (opType)
64     {
65     default:
66         DE_FATAL("Unsupported op type");
67         return "";
68     case OPTYPE_SHUFFLE:
69         return "subgroupShuffle";
70     case OPTYPE_SHUFFLE_XOR:
71         return "subgroupShuffleXor";
72     case OPTYPE_SHUFFLE_UP:
73         return "subgroupShuffleUp";
74     case OPTYPE_SHUFFLE_DOWN:
75         return "subgroupShuffleDown";
76     }
77 }
78 
79 struct CaseDefinition
80 {
81     int opType;
82     ShaderStageFlags shaderStage;
83     Format format;
84 };
85 
to_string(int x)86 const std::string to_string(int x)
87 {
88     std::ostringstream oss;
89     oss << x;
90     return oss.str();
91 }
92 
DeclSource(CaseDefinition caseDef,int baseBinding)93 const std::string DeclSource(CaseDefinition caseDef, int baseBinding)
94 {
95     return "layout(binding = " + to_string(baseBinding) +
96            ", std430) readonly buffer BufferB0\n"
97            "{\n"
98            "  " +
99            subgroups::getFormatNameForGLSL(caseDef.format) +
100            " data1[];\n"
101            "};\n"
102            "layout(binding = " +
103            to_string(baseBinding + 1) +
104            ", std430) readonly buffer BufferB1\n"
105            "{\n"
106            "  uint data2[];\n"
107            "};\n";
108 }
109 
TestSource(CaseDefinition caseDef)110 const std::string TestSource(CaseDefinition caseDef)
111 {
112     std::string idTable[OPTYPE_LAST];
113     idTable[OPTYPE_SHUFFLE]      = "id_in";
114     idTable[OPTYPE_SHUFFLE_XOR]  = "gl_SubgroupInvocationID ^ id_in";
115     idTable[OPTYPE_SHUFFLE_UP]   = "gl_SubgroupInvocationID - id_in";
116     idTable[OPTYPE_SHUFFLE_DOWN] = "gl_SubgroupInvocationID + id_in";
117 
118     const std::string testSource =
119         "  uint temp_res;\n"
120         "  uvec4 mask = subgroupBallot(true);\n"
121         "  uint id_in = data2[gl_SubgroupInvocationID] & (gl_SubgroupSize - 1u);\n"
122         "  " +
123         subgroups::getFormatNameForGLSL(caseDef.format) + " op = " + getOpTypeName(caseDef.opType) +
124         "(data1[gl_SubgroupInvocationID], id_in);\n"
125         "  uint id = " +
126         idTable[caseDef.opType] +
127         ";\n"
128         "  if ((id < gl_SubgroupSize) && subgroupBallotBitExtract(mask, id))\n"
129         "  {\n"
130         "    temp_res = (op == data1[id]) ? 1u : 0u;\n"
131         "  }\n"
132         "  else\n"
133         "  {\n"
134         "    temp_res = 1u; // Invocation we read from was inactive, so we can't verify results!\n"
135         "  }\n";
136 
137     return testSource;
138 }
139 
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)140 void initFrameBufferPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
141 {
142     subgroups::setFragmentShaderFrameBuffer(programCollection);
143 
144     if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
145         subgroups::setVertexShaderFrameBuffer(programCollection);
146 
147     const std::string extSource = (OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType) ?
148                                       "#extension GL_KHR_shader_subgroup_shuffle: enable\n" :
149                                       "#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
150 
151     const std::string testSource = TestSource(caseDef);
152 
153     if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
154     {
155         std::ostringstream vertexSrc;
156         vertexSrc << "${VERSION_DECL}\n"
157                   << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
158                   << "layout(location = 0) in highp vec4 in_position;\n"
159                   << "layout(location = 0) out float result;\n"
160                   << "layout(binding = 0, std140) uniform Buffer0\n"
161                   << "{\n"
162                   << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
163                   << subgroups::maxSupportedSubgroupSize() << "];\n"
164                   << "};\n"
165                   << "layout(binding = 1, std140) uniform Buffer1\n"
166                   << "{\n"
167                   << "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
168                   << "};\n"
169                   << "\n"
170                   << "void main (void)\n"
171                   << "{\n"
172                   << testSource << "  result = float(temp_res);\n"
173                   << "  gl_Position = in_position;\n"
174                   << "  gl_PointSize = 1.0f;\n"
175                   << "}\n";
176         programCollection.add("vert") << glu::VertexSource(vertexSrc.str());
177     }
178     else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
179     {
180         std::ostringstream geometry;
181 
182         geometry << "${VERSION_DECL}\n"
183                  << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
184                  << "layout(points) in;\n"
185                  << "layout(points, max_vertices = 1) out;\n"
186                  << "layout(location = 0) out float out_color;\n"
187                  << "layout(binding = 0, std140) uniform Buffer0\n"
188                  << "{\n"
189                  << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
190                  << subgroups::maxSupportedSubgroupSize() << "];\n"
191                  << "};\n"
192                  << "layout(binding = 1, std140) uniform Buffer1\n"
193                  << "{\n"
194                  << "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
195                  << "};\n"
196                  << "\n"
197                  << "void main (void)\n"
198                  << "{\n"
199                  << testSource << "  out_color = float(temp_res);\n"
200                  << "  gl_Position = gl_in[0].gl_Position;\n"
201                  << "  EmitVertex();\n"
202                  << "  EndPrimitive();\n"
203                  << "}\n";
204 
205         programCollection.add("geometry") << glu::GeometrySource(geometry.str());
206     }
207     else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
208     {
209         std::ostringstream controlSource;
210 
211         controlSource << "${VERSION_DECL}\n"
212                       << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
213                       << "layout(vertices = 2) out;\n"
214                       << "layout(location = 0) out float out_color[];\n"
215                       << "layout(binding = 0, std140) uniform Buffer0\n"
216                       << "{\n"
217                       << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
218                       << subgroups::maxSupportedSubgroupSize() << "];\n"
219                       << "};\n"
220                       << "layout(binding = 1, std140) uniform Buffer1\n"
221                       << "{\n"
222                       << "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
223                       << "};\n"
224                       << "\n"
225                       << "void main (void)\n"
226                       << "{\n"
227                       << "  if (gl_InvocationID == 0)\n"
228                       << "  {\n"
229                       << "    gl_TessLevelOuter[0] = 1.0f;\n"
230                       << "    gl_TessLevelOuter[1] = 1.0f;\n"
231                       << "  }\n"
232                       << testSource << "  out_color[gl_InvocationID] = float(temp_res);\n"
233                       << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
234                       << "}\n";
235 
236         programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
237         subgroups::setTesEvalShaderFrameBuffer(programCollection);
238     }
239     else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
240     {
241         std::ostringstream evaluationSource;
242         evaluationSource << "${VERSION_DECL}\n"
243                          << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
244                          << "layout(isolines, equal_spacing, ccw ) in;\n"
245                          << "layout(location = 0) out float out_color;\n"
246                          << "layout(binding = 0, std140) uniform Buffer0\n"
247                          << "{\n"
248                          << "  " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
249                          << subgroups::maxSupportedSubgroupSize() << "];\n"
250                          << "};\n"
251                          << "layout(binding = 1, std140) uniform Buffer1\n"
252                          << "{\n"
253                          << "  uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
254                          << "};\n"
255                          << "\n"
256                          << "void main (void)\n"
257                          << "{\n"
258                          << testSource << "  out_color = float(temp_res);\n"
259                          << "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
260                          << "}\n";
261 
262         subgroups::setTesCtrlShaderFrameBuffer(programCollection);
263         programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
264     }
265     else
266     {
267         DE_FATAL("Unsupported shader stage");
268     }
269 }
270 
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)271 void initPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
272 {
273     const std::string versionSource = "${VERSION_DECL}\n";
274     const std::string vSource       = "#extension GL_KHR_shader_subgroup_ballot: enable\n";
275     const std::string eSource       = (OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType) ?
276                                           "#extension GL_KHR_shader_subgroup_shuffle: enable\n" :
277                                           "#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
278     const std::string extSource     = vSource + eSource;
279 
280     const std::string testSource = TestSource(caseDef);
281 
282     if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
283     {
284         std::ostringstream src;
285 
286         src << versionSource + extSource << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
287             << "layout(binding = 0, std430) buffer Buffer0\n"
288             << "{\n"
289             << "  uint result[];\n"
290             << "};\n"
291             << DeclSource(caseDef, 1) << "\n"
292             << "void main (void)\n"
293             << "{\n"
294             << "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
295             << "  highp uint offset = globalSize.x * ((globalSize.y * "
296                "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
297                "gl_GlobalInvocationID.x;\n"
298             << testSource << "  result[offset] = temp_res;\n"
299             << "}\n";
300 
301         programCollection.add("comp") << glu::ComputeSource(src.str());
302     }
303     else
304     {
305         const std::string declSource = DeclSource(caseDef, 4);
306 
307         {
308             const string vertex =
309                 versionSource + extSource +
310                 "layout(binding = 0, std430) buffer Buffer0\n"
311                 "{\n"
312                 "  uint result[];\n"
313                 "} b0;\n" +
314                 declSource +
315                 "\n"
316                 "void main (void)\n"
317                 "{\n" +
318                 testSource +
319                 "  b0.result[gl_VertexID] = temp_res;\n"
320                 "  float pixelSize = 2.0f/1024.0f;\n"
321                 "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
322                 "  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
323                 "  gl_PointSize = 1.0f;\n"
324                 "}\n";
325 
326             programCollection.add("vert") << glu::VertexSource(vertex);
327         }
328 
329         {
330             const string tesc = versionSource + extSource +
331                                 "layout(vertices=1) out;\n"
332                                 "layout(binding = 1, std430)  buffer Buffer1\n"
333                                 "{\n"
334                                 "  uint result[];\n"
335                                 "} b1;\n" +
336                                 declSource +
337                                 "\n"
338                                 "void main (void)\n"
339                                 "{\n" +
340                                 testSource +
341                                 "  b1.result[gl_PrimitiveID] = temp_res;\n"
342                                 "  if (gl_InvocationID == 0)\n"
343                                 "  {\n"
344                                 "    gl_TessLevelOuter[0] = 1.0f;\n"
345                                 "    gl_TessLevelOuter[1] = 1.0f;\n"
346                                 "  }\n"
347                                 "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
348                                 "}\n";
349 
350             programCollection.add("tesc") << glu::TessellationControlSource(tesc);
351         }
352 
353         {
354             const string tese = versionSource + extSource +
355                                 "layout(isolines) in;\n"
356                                 "layout(binding = 2, std430) buffer Buffer2\n"
357                                 "{\n"
358                                 "  uint result[];\n"
359                                 "} b2;\n" +
360                                 declSource +
361                                 "\n"
362                                 "void main (void)\n"
363                                 "{\n" +
364                                 testSource +
365                                 "  b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = temp_res;\n"
366                                 "  float pixelSize = 2.0f/1024.0f;\n"
367                                 "  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
368                                 "}\n";
369 
370             programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
371         }
372 
373         {
374             const string geometry =
375                 // version is added by addGeometryShadersFromTemplate
376                 extSource +
377                 "layout(${TOPOLOGY}) in;\n"
378                 "layout(points, max_vertices = 1) out;\n"
379                 "layout(binding = 3, std430) buffer Buffer3\n"
380                 "{\n"
381                 "  uint result[];\n"
382                 "} b3;\n" +
383                 declSource +
384                 "\n"
385                 "void main (void)\n"
386                 "{\n" +
387                 testSource +
388                 "  b3.result[gl_PrimitiveIDIn] = temp_res;\n"
389                 "  gl_Position = gl_in[0].gl_Position;\n"
390                 "  EmitVertex();\n"
391                 "  EndPrimitive();\n"
392                 "}\n";
393 
394             subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
395         }
396         {
397             const string fragment = versionSource + extSource +
398                                     "precision highp int;\n"
399                                     "precision highp float;\n"
400                                     "layout(location = 0) out uint result;\n" +
401                                     declSource +
402                                     "void main (void)\n"
403                                     "{\n" +
404                                     testSource +
405                                     "  result = temp_res;\n"
406                                     "}\n";
407 
408             programCollection.add("fragment") << glu::FragmentSource(fragment);
409         }
410 
411         subgroups::addNoSubgroupShader(programCollection);
412     }
413 }
414 
supportedCheck(Context & context,CaseDefinition caseDef)415 void supportedCheck(Context &context, CaseDefinition caseDef)
416 {
417     if (!subgroups::isSubgroupSupported(context))
418         TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
419 
420     switch (caseDef.opType)
421     {
422     case OPTYPE_SHUFFLE:
423     case OPTYPE_SHUFFLE_XOR:
424         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_BIT))
425         {
426             TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
427         }
428         break;
429     default:
430         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
431         {
432             TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
433         }
434         break;
435     }
436 
437     if (subgroups::isDoubleFormat(caseDef.format) && !subgroups::isDoubleSupportedForDevice(context))
438         TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
439 }
440 
noSSBOtest(Context & context,const CaseDefinition caseDef)441 tcu::TestStatus noSSBOtest(Context &context, const CaseDefinition caseDef)
442 {
443     if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
444     {
445         if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
446         {
447             return tcu::TestStatus::fail("Shader stage " + subgroups::getShaderStageName(caseDef.shaderStage) +
448                                          " is required to support subgroup operations!");
449         }
450         else
451         {
452             TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
453         }
454     }
455 
456     subgroups::SSBOData inputData[2];
457     inputData[0].format         = caseDef.format;
458     inputData[0].layout         = subgroups::SSBOData::LayoutStd140;
459     inputData[0].numElements    = subgroups::maxSupportedSubgroupSize();
460     inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
461     inputData[0].binding        = 0u;
462 
463     inputData[1].format         = FORMAT_R32_UINT;
464     inputData[1].layout         = subgroups::SSBOData::LayoutStd140;
465     inputData[1].numElements    = inputData[0].numElements;
466     inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
467     inputData[1].binding        = 1u;
468 
469     if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
470         return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages);
471     else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
472         return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, inputData, 2,
473                                                       checkVertexPipelineStages);
474     else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
475         return subgroups::makeTessellationEvaluationFrameBufferTest(
476             context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
477     else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
478         return subgroups::makeTessellationEvaluationFrameBufferTest(
479             context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
480     else
481         TCU_THROW(InternalError, "Unhandled shader stage");
482 }
483 
test(Context & context,const CaseDefinition caseDef)484 tcu::TestStatus test(Context &context, const CaseDefinition caseDef)
485 {
486     switch (caseDef.opType)
487     {
488     case OPTYPE_SHUFFLE:
489     case OPTYPE_SHUFFLE_XOR:
490         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_BIT))
491         {
492             TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
493         }
494         break;
495     default:
496         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
497         {
498             TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
499         }
500         break;
501     }
502 
503     if (subgroups::isDoubleFormat(caseDef.format) && !subgroups::isDoubleSupportedForDevice(context))
504     {
505         TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
506     }
507 
508     if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
509     {
510         if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
511         {
512             return tcu::TestStatus::fail("Shader stage " + subgroups::getShaderStageName(caseDef.shaderStage) +
513                                          " is required to support subgroup operations!");
514         }
515         subgroups::SSBOData inputData[2];
516         inputData[0].format         = caseDef.format;
517         inputData[0].layout         = subgroups::SSBOData::LayoutStd430;
518         inputData[0].numElements    = subgroups::maxSupportedSubgroupSize();
519         inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
520         inputData[0].binding        = 1u;
521 
522         inputData[1].format         = FORMAT_R32_UINT;
523         inputData[1].layout         = subgroups::SSBOData::LayoutStd430;
524         inputData[1].numElements    = inputData[0].numElements;
525         inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
526         inputData[1].binding        = 2u;
527 
528         return subgroups::makeComputeTest(context, FORMAT_R32_UINT, inputData, 2, checkComputeStage);
529     }
530 
531     else
532     {
533         int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
534 
535         ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
536 
537         if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
538         {
539             if ((stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
540                 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
541             else
542                 stages = SHADER_STAGE_FRAGMENT_BIT;
543         }
544 
545         if ((ShaderStageFlags)0u == stages)
546             TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
547 
548         subgroups::SSBOData inputData[2];
549         inputData[0].format         = caseDef.format;
550         inputData[0].layout         = subgroups::SSBOData::LayoutStd430;
551         inputData[0].numElements    = subgroups::maxSupportedSubgroupSize();
552         inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
553         inputData[0].binding        = 4u;
554         inputData[0].stages         = stages;
555 
556         inputData[1].format         = FORMAT_R32_UINT;
557         inputData[1].layout         = subgroups::SSBOData::LayoutStd430;
558         inputData[1].numElements    = inputData[0].numElements;
559         inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
560         inputData[1].binding        = 5u;
561         inputData[1].stages         = stages;
562 
563         return subgroups::allStages(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, stages);
564     }
565 }
566 } // namespace
567 
createSubgroupsShuffleTests(deqp::Context & testCtx)568 deqp::TestCaseGroup *createSubgroupsShuffleTests(deqp::Context &testCtx)
569 {
570 
571     de::MovePtr<deqp::TestCaseGroup> graphicGroup(
572         new deqp::TestCaseGroup(testCtx, "graphics", "Subgroup shuffle category tests: graphics"));
573     de::MovePtr<deqp::TestCaseGroup> computeGroup(
574         new deqp::TestCaseGroup(testCtx, "compute", "Subgroup shuffle category tests: compute"));
575     de::MovePtr<deqp::TestCaseGroup> framebufferGroup(
576         new deqp::TestCaseGroup(testCtx, "framebuffer", "Subgroup shuffle category tests: framebuffer"));
577 
578     const Format formats[] = {
579         FORMAT_R32_SINT,   FORMAT_R32G32_SINT,   FORMAT_R32G32B32_SINT,   FORMAT_R32G32B32A32_SINT,
580         FORMAT_R32_UINT,   FORMAT_R32G32_UINT,   FORMAT_R32G32B32_UINT,   FORMAT_R32G32B32A32_UINT,
581         FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT, FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
582         FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT, FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
583         FORMAT_R32_BOOL,   FORMAT_R32G32_BOOL,   FORMAT_R32G32B32_BOOL,   FORMAT_R32G32B32A32_BOOL,
584     };
585 
586     const ShaderStageFlags stages[] = {
587         SHADER_STAGE_VERTEX_BIT,
588         SHADER_STAGE_TESS_EVALUATION_BIT,
589         SHADER_STAGE_TESS_CONTROL_BIT,
590         SHADER_STAGE_GEOMETRY_BIT,
591     };
592 
593     for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
594     {
595         const Format format = formats[formatIndex];
596 
597         for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
598         {
599 
600             const string name = de::toLower(getOpTypeName(opTypeIndex)) + "_" + subgroups::getFormatNameForGLSL(format);
601 
602             {
603                 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS, format};
604                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(
605                     graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
606             }
607 
608             {
609                 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format};
610                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(
611                     computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
612             }
613 
614             for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
615             {
616                 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format};
617                 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(
618                     framebufferGroup.get(), name + "_" + getShaderStageName(caseDef.shaderStage), "", supportedCheck,
619                     initFrameBufferPrograms, noSSBOtest, caseDef);
620             }
621         }
622     }
623 
624     de::MovePtr<deqp::TestCaseGroup> group(
625         new deqp::TestCaseGroup(testCtx, "shuffle", "Subgroup shuffle category tests"));
626 
627     group->addChild(graphicGroup.release());
628     group->addChild(computeGroup.release());
629     group->addChild(framebufferGroup.release());
630 
631     return group.release();
632 }
633 
634 } // namespace subgroups
635 } // namespace glc
636