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