d39a19e344551b774d757ee78a3a51c39084e348
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / subgroups / glcSubgroupsBasicTests.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 "vktSubgroupsBasicTests.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 static const deUint32                   ELECTED_VALUE           = 42u;
39 static const deUint32                   UNELECTED_VALUE         = 13u;
40 static const vk::VkDeviceSize   SHADER_BUFFER_SIZE      = 4096ull; // min(maxUniformBufferRange, maxImageDimension1D)
41
42 static bool checkFragmentSubgroupBarriersNoSSBO(std::vector<const void*> datas,
43                 deUint32 width, deUint32 height, deUint32)
44 {
45         const float* const      resultData      = reinterpret_cast<const float*>(datas[0]);
46
47         for (deUint32 x = 0u; x < width; ++x)
48         {
49                 for (deUint32 y = 0u; y < height; ++y)
50                 {
51                         const deUint32 ndx = (x * height + y) * 4u;
52                         if (1.0f == resultData[ndx +2])
53                         {
54                                 if(resultData[ndx] != resultData[ndx +1])
55                                 {
56                                         return false;
57                                 }
58                         }
59                         else if (resultData[ndx] != resultData[ndx +3])
60                         {
61                                 return false;
62                         }
63                 }
64         }
65
66         return true;
67 }
68
69 static bool checkVertexPipelineStagesSubgroupElectNoSSBO(std::vector<const void*> datas,
70                 deUint32 width, deUint32)
71 {
72         const float* const      resultData                      = reinterpret_cast<const float*>(datas[0]);
73         float                           poisonValuesFound       = 0.0f;
74         float                           numSubgroupsUsed        = 0.0f;
75
76         for (deUint32 x = 0; x < width; ++x)
77         {
78                 deUint32 val = static_cast<deUint32>(resultData[x * 2]);
79                 numSubgroupsUsed += resultData[x * 2 + 1];
80
81                 switch (val)
82                 {
83                         default:
84                                 // some garbage value was found!
85                                 return false;
86                         case UNELECTED_VALUE:
87                                 break;
88                         case ELECTED_VALUE:
89                                 poisonValuesFound += 1.0f;
90                                 break;
91                 }
92         }
93         return numSubgroupsUsed == poisonValuesFound;
94 }
95
96 static bool checkVertexPipelineStagesSubgroupElect(std::vector<const void*> datas,
97                 deUint32 width, deUint32)
98 {
99         const deUint32* const resultData =
100                 reinterpret_cast<const deUint32*>(datas[0]);
101         deUint32 poisonValuesFound = 0;
102
103         for (deUint32 x = 0; x < width; ++x)
104         {
105                 deUint32 val = resultData[x];
106
107                 switch (val)
108                 {
109                         default:
110                                 // some garbage value was found!
111                                 return false;
112                         case UNELECTED_VALUE:
113                                 break;
114                         case ELECTED_VALUE:
115                                 poisonValuesFound++;
116                                 break;
117                 }
118         }
119
120         // we used an atomicly incremented counter to note how many subgroups we used for the vertex shader
121         const deUint32 numSubgroupsUsed =
122                 *reinterpret_cast<const deUint32*>(datas[1]);
123
124         return numSubgroupsUsed == poisonValuesFound;
125 }
126
127 static bool checkVertexPipelineStagesSubgroupBarriers(std::vector<const void*> datas,
128                 deUint32 width, deUint32)
129 {
130         const deUint32* const resultData = reinterpret_cast<const deUint32*>(datas[0]);
131
132         // We used this SSBO to generate our unique value!
133         const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[3]);
134
135         for (deUint32 x = 0; x < width; ++x)
136         {
137                 deUint32 val = resultData[x];
138
139                 if (val != ref)
140                         return false;
141         }
142
143         return true;
144 }
145
146 static bool checkVertexPipelineStagesSubgroupBarriersNoSSBO(std::vector<const void*> datas,
147                 deUint32 width, deUint32)
148 {
149         const float* const      resultData      = reinterpret_cast<const float*>(datas[0]);
150
151         for (deUint32 x = 0u; x < width; ++x)
152         {
153                 const deUint32 ndx = x*4u;
154                 if (1.0f == resultData[ndx +2])
155                 {
156                         if(resultData[ndx] != resultData[ndx +1])
157                                 return false;
158                 }
159                 else if (resultData[ndx] != resultData[ndx +3])
160                 {
161                         return false;
162                 }
163         }
164         return true;
165 }
166
167 static bool checkTessellationEvaluationSubgroupBarriersNoSSBO(std::vector<const void*> datas,
168                 deUint32 width, deUint32)
169 {
170         const float* const      resultData      = reinterpret_cast<const float*>(datas[0]);
171
172         for (deUint32 x = 0u; x < width; ++x)
173         {
174                 const deUint32 ndx = x*4u;
175                 if (0.0f == resultData[ndx +2] && resultData[ndx] != resultData[ndx +3])
176                 {
177                         return false;
178                 }
179         }
180         return true;
181 }
182
183 static bool checkComputeSubgroupElect(std::vector<const void*> datas,
184                                                                           const deUint32 numWorkgroups[3], const deUint32 localSize[3],
185                                                                           deUint32)
186 {
187         return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
188 }
189
190 static bool checkComputeSubgroupBarriers(std::vector<const void*> datas,
191                 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
192                 deUint32)
193 {
194         // We used this SSBO to generate our unique value!
195         const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[2]);
196         return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, ref);
197 }
198
199 enum OpType
200 {
201         OPTYPE_ELECT = 0,
202         OPTYPE_SUBGROUP_BARRIER,
203         OPTYPE_SUBGROUP_MEMORY_BARRIER,
204         OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER,
205         OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED,
206         OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE,
207         OPTYPE_LAST
208 };
209
210 std::string getOpTypeName(int opType)
211 {
212         switch (opType)
213         {
214                 default:
215                         DE_FATAL("Unsupported op type");
216                         return "";
217                 case OPTYPE_ELECT:
218                         return "subgroupElect";
219                 case OPTYPE_SUBGROUP_BARRIER:
220                         return "subgroupBarrier";
221                 case OPTYPE_SUBGROUP_MEMORY_BARRIER:
222                         return "subgroupMemoryBarrier";
223                 case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
224                         return "subgroupMemoryBarrierBuffer";
225                 case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
226                         return "subgroupMemoryBarrierShared";
227                 case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
228                         return "subgroupMemoryBarrierImage";
229         }
230 }
231
232 struct CaseDefinition
233 {
234         int                                     opType;
235         VkShaderStageFlags      shaderStage;
236 };
237
238 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
239 {
240         const vk::ShaderBuildOptions    buildOptions    (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
241         const vk::SpirVAsmBuildOptions  buildOptionsSpr (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3);
242
243         if(VK_SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage)
244         {
245                 /*
246                         "layout(location = 0) in vec4 in_color;\n"
247                         "layout(location = 0) out vec4 out_color;\n"
248                         "void main()\n"
249                         {\n"
250                         "       out_color = in_color;\n"
251                         "}\n";
252                 */
253                 const string fragment =
254                         "; SPIR-V\n"
255                         "; Version: 1.3\n"
256                         "; Generator: Khronos Glslang Reference Front End; 2\n"
257                         "; Bound: 13\n"
258                         "; Schema: 0\n"
259                         "OpCapability Shader\n"
260                         "%1 = OpExtInstImport \"GLSL.std.450\"\n"
261                         "OpMemoryModel Logical GLSL450\n"
262                         "OpEntryPoint Fragment %4 \"main\" %9 %11\n"
263                         "OpExecutionMode %4 OriginUpperLeft\n"
264                         "OpDecorate %9 Location 0\n"
265                         "OpDecorate %11 Location 0\n"
266                         "%2 = OpTypeVoid\n"
267                         "%3 = OpTypeFunction %2\n"
268                         "%6 = OpTypeFloat 32\n"
269                         "%7 = OpTypeVector %6 4\n"
270                         "%8 = OpTypePointer Output %7\n"
271                         "%9 = OpVariable %8 Output\n"
272                         "%10 = OpTypePointer Input %7\n"
273                         "%11 = OpVariable %10 Input\n"
274                         "%4 = OpFunction %2 None %3\n"
275                         "%5 = OpLabel\n"
276                         "%12 = OpLoad %7 %11\n"
277                         "OpStore %9 %12\n"
278                         "OpReturn\n"
279                         "OpFunctionEnd\n";
280                 programCollection.spirvAsmSources.add("fragment") << fragment;
281         }
282         if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
283         {
284                 /*
285                         "#version 450\n"
286                         "void main (void)\n"
287                         "{\n"
288                         "  vec2 uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);\n"
289                         "  gl_Position = vec4(uv * 2.0f + -1.0f, 0.0f, 1.0f);\n"
290                         "  gl_PointSize = 1.0f;\n"
291                         "}\n";
292                 */
293                 const string vertex =
294                         "; SPIR-V\n"
295                         "; Version: 1.3\n"
296                         "; Generator: Khronos Glslang Reference Front End; 2\n"
297                         "; Bound: 44\n"
298                         "; Schema: 0\n"
299                         "OpCapability Shader\n"
300                         "%1 = OpExtInstImport \"GLSL.std.450\"\n"
301                         "OpMemoryModel Logical GLSL450\n"
302                         "OpEntryPoint Vertex %4 \"main\" %12 %29\n"
303                         "OpDecorate %12 BuiltIn VertexIndex\n"
304                         "OpMemberDecorate %27 0 BuiltIn Position\n"
305                         "OpMemberDecorate %27 1 BuiltIn PointSize\n"
306                         "OpMemberDecorate %27 2 BuiltIn ClipDistance\n"
307                         "OpMemberDecorate %27 3 BuiltIn CullDistance\n"
308                         "OpDecorate %27 Block\n"
309                         "%2 = OpTypeVoid\n"
310                         "%3 = OpTypeFunction %2\n"
311                         "%6 = OpTypeFloat 32\n"
312                         "%7 = OpTypeVector %6 2\n"
313                         "%8 = OpTypePointer Function %7\n"
314                         "%10 = OpTypeInt 32 1\n"
315                         "%11 = OpTypePointer Input %10\n"
316                         "%12 = OpVariable %11 Input\n"
317                         "%14 = OpConstant %10 1\n"
318                         "%16 = OpConstant %10 2\n"
319                         "%23 = OpTypeVector %6 4\n"
320                         "%24 = OpTypeInt 32 0\n"
321                         "%25 = OpConstant %24 1\n"
322                         "%26 = OpTypeArray %6 %25\n"
323                         "%27 = OpTypeStruct %23 %6 %26 %26\n"
324                         "%28 = OpTypePointer Output %27\n"
325                         "%29 = OpVariable %28 Output\n"
326                         "%30 = OpConstant %10 0\n"
327                         "%32 = OpConstant %6 2\n"
328                         "%34 = OpConstant %6 -1\n"
329                         "%37 = OpConstant %6 0\n"
330                         "%38 = OpConstant %6 1\n"
331                         "%42 = OpTypePointer Output %23\n"
332                         "%44 = OpTypePointer Output %6\n"
333                         "%4 = OpFunction %2 None %3\n"
334                         "%5 = OpLabel\n"
335                         "%9 = OpVariable %8 Function\n"
336                         "%13 = OpLoad %10 %12\n"
337                         "%15 = OpShiftLeftLogical %10 %13 %14\n"
338                         "%17 = OpBitwiseAnd %10 %15 %16\n"
339                         "%18 = OpConvertSToF %6 %17\n"
340                         "%19 = OpLoad %10 %12\n"
341                         "%20 = OpBitwiseAnd %10 %19 %16\n"
342                         "%21 = OpConvertSToF %6 %20\n"
343                         "%22 = OpCompositeConstruct %7 %18 %21\n"
344                         "OpStore %9 %22\n"
345                         "%31 = OpLoad %7 %9\n"
346                         "%33 = OpVectorTimesScalar %7 %31 %32\n"
347                         "%35 = OpCompositeConstruct %7 %34 %34\n"
348                         "%36 = OpFAdd %7 %33 %35\n"
349                         "%39 = OpCompositeExtract %6 %36 0\n"
350                         "%40 = OpCompositeExtract %6 %36 1\n"
351                         "%41 = OpCompositeConstruct %23 %39 %40 %37 %38\n"
352                         "%43 = OpAccessChain %42 %29 %30\n"
353                         "OpStore %43 %41\n"
354                         "%45 = OpAccessChain %44 %29 %14\n"
355                         "OpStore %45 %38\n"
356                         "OpReturn\n"
357                         "OpFunctionEnd\n";
358                 programCollection.spirvAsmSources.add("vert") << vertex;
359         }
360         else if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
361                 subgroups::setVertexShaderFrameBuffer(programCollection);
362
363         if (OPTYPE_ELECT == caseDef.opType)
364         {
365                 std::ostringstream electedValue ;
366                 std::ostringstream unelectedValue;
367                 electedValue << ELECTED_VALUE;
368                 unelectedValue << UNELECTED_VALUE;
369
370                 if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
371                 {
372                         /*
373                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
374                                 "layout(location = 0) out vec4 out_color;\n"
375                                 "layout(location = 0) in highp vec4 in_position;\n"
376                                 "\n"
377                                 "void main (void)\n"
378                                 "{\n"
379                                 "  if (subgroupElect())\n"
380                                 "  {\n"
381                                 "    out_color.r = " << ELECTED_VALUE << ";\n"
382                                 "    out_color.g = 1.0f;\n"
383                                 "  }\n"
384                                 "  else\n"
385                                 "  {\n"
386                                 "    out_color.r = " << UNELECTED_VALUE << ";\n"
387                                 "    out_color.g = 0.0f;\n"
388                                 "  }\n"
389                                 "  gl_Position = in_position;\n"
390                                 "  gl_PointSize = 1.0f;\n"
391                                 "}\n";
392                         */
393                         const string vertex =
394                                 "; SPIR-V\n"
395                                 "; Version: 1.3\n"
396                                 "; Generator: Khronos Glslang Reference Front End; 2\n"
397                                 "; Bound: 38\n"
398                                 "; Schema: 0\n"
399                                 "OpCapability Shader\n"
400                                 "OpCapability GroupNonUniform\n"
401                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
402                                 "OpMemoryModel Logical GLSL450\n"
403                                 "OpEntryPoint Vertex %4 \"main\" %15 %31 %35\n"
404                                 "OpDecorate %15 Location 0\n"
405                                 "OpMemberDecorate %29 0 BuiltIn Position\n"
406                                 "OpMemberDecorate %29 1 BuiltIn PointSize\n"
407                                 "OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
408                                 "OpMemberDecorate %29 3 BuiltIn CullDistance\n"
409                                 "OpDecorate %29 Block\n"
410                                 "OpDecorate %35 Location 0\n"
411                                 "%2 = OpTypeVoid\n"
412                                 "%3 = OpTypeFunction %2\n"
413                                 "%6 = OpTypeBool\n"
414                                 "%7 = OpTypeInt 32 0\n"
415                                 "%8 = OpConstant %7 3\n"
416                                 "%12 = OpTypeFloat 32\n"
417                                 "%13 = OpTypeVector %12 4\n"
418                                 "%14 = OpTypePointer Output %13\n"
419                                 "%15 = OpVariable %14 Output\n"
420                                 "%16 = OpConstant %12 " + electedValue.str() + "\n"
421                                 "%17 = OpConstant %7 0\n"
422                                 "%18 = OpTypePointer Output %12\n"
423                                 "%20 = OpConstant %12 1\n"
424                                 "%21 = OpConstant %7 1\n"
425                                 "%24 = OpConstant %12 " + unelectedValue.str() + "\n"
426                                 "%26 = OpConstant %12 0\n"
427                                 "%28 = OpTypeArray %12 %21\n"
428                                 "%29 = OpTypeStruct %13 %12 %28 %28\n"
429                                 "%30 = OpTypePointer Output %29\n"
430                                 "%31 = OpVariable %30 Output\n"
431                                 "%32 = OpTypeInt 32 1\n"
432                                 "%33 = OpConstant %32 0\n"
433                                 "%34 = OpTypePointer Input %13\n"
434                                 "%35 = OpVariable %34 Input\n"
435                                 "%38 = OpConstant %32 1\n"
436                                 "%4 = OpFunction %2 None %3\n"
437                                 "%5 = OpLabel\n"
438                                 "%9 = OpGroupNonUniformElect %6 %8\n"
439                                 "OpSelectionMerge %11 None\n"
440                                 "OpBranchConditional %9 %10 %23\n"
441                                 "%10 = OpLabel\n"
442                                 "%19 = OpAccessChain %18 %15 %17\n"
443                                 "OpStore %19 %16\n"
444                                 "%22 = OpAccessChain %18 %15 %21\n"
445                                 "OpStore %22 %20\n"
446                                 "OpBranch %11\n"
447                                 "%23 = OpLabel\n"
448                                 "%25 = OpAccessChain %18 %15 %17\n"
449                                 "OpStore %25 %24\n"
450                                 "%27 = OpAccessChain %18 %15 %21\n"
451                                 "OpStore %27 %26\n"
452                                 "OpBranch %11\n"
453                                 "%11 = OpLabel\n"
454                                 "%36 = OpLoad %13 %35\n"
455                                 "%37 = OpAccessChain %14 %31 %33\n"
456                                 "OpStore %37 %36\n"
457                                 "%39 = OpAccessChain %18 %31 %38\n"
458                                 "OpStore %39 %20\n"
459                                 "OpReturn\n"
460                                 "OpFunctionEnd\n";
461                         programCollection.spirvAsmSources.add("vert") << vertex << buildOptionsSpr;
462                 }
463                 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
464                 {
465                         /*
466                                 "#version 450\n"
467                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
468                                 "layout(points) in;\n"
469                                 "layout(points, max_vertices = 1) out;\n"
470                                 "layout(location = 0) out vec4 out_color;\n"
471                                 "void main (void)\n"
472                                 "{\n"
473                                 "  if (subgroupElect())\n"
474                                 "  {\n"
475                                 "    out_color.r = " << ELECTED_VALUE << ";\n"
476                                 "    out_color.g = 1.0f;\n"
477                                 "  }\n"
478                                 "  else\n"
479                                 "  {\n"
480                                 "    out_color.r = " << UNELECTED_VALUE << ";\n"
481                                 "    out_color.g = 0.0f;\n"
482                                 "  }\n"
483                                 "  gl_Position = gl_in[0].gl_Position;\n"
484                                 "  EmitVertex();\n"
485                                 "  EndPrimitive();\n"
486                                 "}\n";
487                         */
488                         const string geometry =
489                                 "; SPIR-V\n"
490                                 "; Version: 1.3\n"
491                                 "; Generator: Khronos Glslang Reference Front End; 2\n"
492                                 "; Bound: 42\n"
493                                 "; Schema: 0\n"
494                                 "OpCapability Geometry\n"
495                                 "OpCapability GroupNonUniform\n"
496                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
497                                 "OpMemoryModel Logical GLSL450\n"
498                                 "OpEntryPoint Geometry %4 \"main\" %15 %31 %37\n"
499                                 "OpExecutionMode %4 InputPoints\n"
500                                 "OpExecutionMode %4 Invocations 1\n"
501                                 "OpExecutionMode %4 OutputPoints\n"
502                                 "OpExecutionMode %4 OutputVertices 1\n"
503                                 "OpDecorate %15 Location 0\n"
504                                 "OpMemberDecorate %29 0 BuiltIn Position\n"
505                                 "OpMemberDecorate %29 1 BuiltIn PointSize\n"
506                                 "OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
507                                 "OpMemberDecorate %29 3 BuiltIn CullDistance\n"
508                                 "OpDecorate %29 Block\n"
509                                 "OpMemberDecorate %34 0 BuiltIn Position\n"
510                                 "OpMemberDecorate %34 1 BuiltIn PointSize\n"
511                                 "OpMemberDecorate %34 2 BuiltIn ClipDistance\n"
512                                 "OpMemberDecorate %34 3 BuiltIn CullDistance\n"
513                                 "OpDecorate %34 Block\n"
514                                 "%2 = OpTypeVoid\n"
515                                 "%3 = OpTypeFunction %2\n"
516                                 "%6 = OpTypeBool\n"
517                                 "%7 = OpTypeInt 32 0\n"
518                                 "%8 = OpConstant %7 3\n"
519                                 "%12 = OpTypeFloat 32\n"
520                                 "%13 = OpTypeVector %12 4\n"
521                                 "%14 = OpTypePointer Output %13\n"
522                                 "%15 = OpVariable %14 Output\n"
523                                 "%16 = OpConstant %12 " + electedValue.str() + "\n"
524                                 "%17 = OpConstant %7 0\n"
525                                 "%18 = OpTypePointer Output %12\n"
526                                 "%20 = OpConstant %12 1\n"
527                                 "%21 = OpConstant %7 1\n"
528                                 "%24 = OpConstant %12 " + unelectedValue.str() + "\n"
529                                 "%26 = OpConstant %12 0\n"
530                                 "%28 = OpTypeArray %12 %21\n"
531                                 "%29 = OpTypeStruct %13 %12 %28 %28\n"
532                                 "%30 = OpTypePointer Output %29\n"
533                                 "%31 = OpVariable %30 Output\n"
534                                 "%32 = OpTypeInt 32 1\n"
535                                 "%33 = OpConstant %32 0\n"
536                                 "%34 = OpTypeStruct %13 %12 %28 %28\n"
537                                 "%35 = OpTypeArray %34 %21\n"
538                                 "%36 = OpTypePointer Input %35\n"
539                                 "%37 = OpVariable %36 Input\n"
540                                 "%38 = OpTypePointer Input %13\n"
541                                 "%4 = OpFunction %2 None %3\n"
542                                 "%5 = OpLabel\n"
543                                 "%9 = OpGroupNonUniformElect %6 %8\n"
544                                 "OpSelectionMerge %11 None\n"
545                                 "OpBranchConditional %9 %10 %23\n"
546                                 "%10 = OpLabel\n"
547                                 "%19 = OpAccessChain %18 %15 %17\n"
548                                 "OpStore %19 %16\n"
549                                 "%22 = OpAccessChain %18 %15 %21\n"
550                                 "OpStore %22 %20\n"
551                                 "OpBranch %11\n"
552                                 "%23 = OpLabel\n"
553                                 "%25 = OpAccessChain %18 %15 %17\n"
554                                 "OpStore %25 %24\n"
555                                 "%27 = OpAccessChain %18 %15 %21\n"
556                                 "OpStore %27 %26\n"
557                                 "OpBranch %11\n"
558                                 "%11 = OpLabel\n"
559                                 "%39 = OpAccessChain %38 %37 %33 %33\n"
560                                 "%40 = OpLoad %13 %39\n"
561                                 "%41 = OpAccessChain %14 %31 %33\n"
562                                 "OpStore %41 %40\n"
563                                 "OpEmitVertex\n"
564                                 "OpEndPrimitive\n"
565                                 "OpReturn\n"
566                                 "OpFunctionEnd\n";
567                         programCollection.spirvAsmSources.add("geometry") << geometry << buildOptionsSpr;
568                 }
569                 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
570                 {
571                         /*
572                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
573                                 << "#extension GL_EXT_tessellation_shader : require\n"
574                                 << "layout(vertices = 2) out;\n"
575                                 << "void main (void)\n"
576                                 << "{\n"
577                                 << "  if (gl_InvocationID == 0)\n"
578                                 <<"  {\n"
579                                 << "    gl_TessLevelOuter[0] = 1.0f;\n"
580                                 << "    gl_TessLevelOuter[1] = 1.0f;\n"
581                                 << "  }\n"
582                                 << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
583                                 << "}\n";
584                         */
585                         const string controlSource =
586                                 "; SPIR-V\n"
587                                 "; Version: 1.3\n"
588                                 "; Generator: Khronos Glslang Reference Front End; 2\n"
589                                 "; Bound: 46\n"
590                                 "; Schema: 0\n"
591                                 "OpCapability Tessellation\n"
592                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
593                                 "OpMemoryModel Logical GLSL450\n"
594                                 "OpEntryPoint TessellationControl %4 \"main\" %8 %20 %33 %39\n"
595                                 "OpExecutionMode %4 OutputVertices 2\n"
596                                 "OpDecorate %8 BuiltIn InvocationId\n"
597                                 "OpDecorate %20 Patch\n"
598                                 "OpDecorate %20 BuiltIn TessLevelOuter\n"
599                                 "OpMemberDecorate %29 0 BuiltIn Position\n"
600                                 "OpMemberDecorate %29 1 BuiltIn PointSize\n"
601                                 "OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
602                                 "OpMemberDecorate %29 3 BuiltIn CullDistance\n"
603                                 "OpDecorate %29 Block\n"
604                                 "OpMemberDecorate %35 0 BuiltIn Position\n"
605                                 "OpMemberDecorate %35 1 BuiltIn PointSize\n"
606                                 "OpMemberDecorate %35 2 BuiltIn ClipDistance\n"
607                                 "OpMemberDecorate %35 3 BuiltIn CullDistance\n"
608                                 "OpDecorate %35 Block\n"
609                                 "%2 = OpTypeVoid\n"
610                                 "%3 = OpTypeFunction %2\n"
611                                 "%6 = OpTypeInt 32 1\n"
612                                 "%7 = OpTypePointer Input %6\n"
613                                 "%8 = OpVariable %7 Input\n"
614                                 "%10 = OpConstant %6 0\n"
615                                 "%11 = OpTypeBool\n"
616                                 "%15 = OpTypeFloat 32\n"
617                                 "%16 = OpTypeInt 32 0\n"
618                                 "%17 = OpConstant %16 4\n"
619                                 "%18 = OpTypeArray %15 %17\n"
620                                 "%19 = OpTypePointer Output %18\n"
621                                 "%20 = OpVariable %19 Output\n"
622                                 "%21 = OpConstant %15 1\n"
623                                 "%22 = OpTypePointer Output %15\n"
624                                 "%24 = OpConstant %6 1\n"
625                                 "%26 = OpTypeVector %15 4\n"
626                                 "%27 = OpConstant %16 1\n"
627                                 "%28 = OpTypeArray %15 %27\n"
628                                 "%29 = OpTypeStruct %26 %15 %28 %28\n"
629                                 "%30 = OpConstant %16 2\n"
630                                 "%31 = OpTypeArray %29 %30\n"
631                                 "%32 = OpTypePointer Output %31\n"
632                                 "%33 = OpVariable %32 Output\n"
633                                 "%35 = OpTypeStruct %26 %15 %28 %28\n"
634                                 "%36 = OpConstant %16 32\n"
635                                 "%37 = OpTypeArray %35 %36\n"
636                                 "%38 = OpTypePointer Input %37\n"
637                                 "%39 = OpVariable %38 Input\n"
638                                 "%41 = OpTypePointer Input %26\n"
639                                 "%44 = OpTypePointer Output %26\n"
640                                 "%4 = OpFunction %2 None %3\n"
641                                 "%5 = OpLabel\n"
642                                 "%9 = OpLoad %6 %8\n"
643                                 "%12 = OpIEqual %11 %9 %10\n"
644                                 "OpSelectionMerge %14 None\n"
645                                 "OpBranchConditional %12 %13 %14\n"
646                                 "%13 = OpLabel\n"
647                                 "%23 = OpAccessChain %22 %20 %10\n"
648                                 "OpStore %23 %21\n"
649                                 "%25 = OpAccessChain %22 %20 %24\n"
650                                 "OpStore %25 %21\n"
651                                 "OpBranch %14\n"
652                                 "%14 = OpLabel\n"
653                                 "%34 = OpLoad %6 %8\n"
654                                 "%40 = OpLoad %6 %8\n"
655                                 "%42 = OpAccessChain %41 %39 %40 %10\n"
656                                 "%43 = OpLoad %26 %42\n"
657                                 "%45 = OpAccessChain %44 %33 %34 %10\n"
658                                 "OpStore %45 %43\n"
659                                 "OpReturn\n"
660                                 "OpFunctionEnd\n";
661                         programCollection.spirvAsmSources.add("tesc") << controlSource << buildOptionsSpr;
662
663                         /*
664                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
665                                 "#extension GL_EXT_tessellation_shader : require\n"
666                                 "layout(isolines, equal_spacing, ccw ) in;\n"
667                                 "layout(location = 0) out vec4 out_color;\n"
668                                 "\n"
669                                 "void main (void)\n"
670                                 "{\n"
671                                 "  if (subgroupElect())\n"
672                                 "  {\n"
673                                 "    out_color.r = " << 2 * ELECTED_VALUE - UNELECTED_VALUE << ";\n"
674                                 "    out_color.g = 2.0f;\n"
675                                 "  }\n"
676                                 "  else\n"
677                                 "  {\n"
678                                 "    out_color.r = " << UNELECTED_VALUE << ";\n"
679                                 "    out_color.g = 0.0f;\n"
680                                 "  }\n"
681                                 "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
682                                 "}\n";
683                         */
684
685                         const string evaluationSource =
686                                 "; SPIR-V\n"
687                                 "; Version: 1.3\n"
688                                 "; Generator: Khronos Glslang Reference Front End; 2\n"
689                                 "; Bound: 54\n"
690                                 "; Schema: 0\n"
691                                 "OpCapability Tessellation\n"
692                                 "OpCapability GroupNonUniform\n"
693                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
694                                 "OpMemoryModel Logical GLSL450\n"
695                                 "OpEntryPoint TessellationEvaluation %4 \"main\" %15 %31 %38 %47\n"
696                                 "OpExecutionMode %4 Isolines\n"
697                                 "OpExecutionMode %4 SpacingEqual\n"
698                                 "OpExecutionMode %4 VertexOrderCcw\n"
699                                 "OpDecorate %15 Location 0\n"
700                                 "OpMemberDecorate %29 0 BuiltIn Position\n"
701                                 "OpMemberDecorate %29 1 BuiltIn PointSize\n"
702                                 "OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
703                                 "OpMemberDecorate %29 3 BuiltIn CullDistance\n"
704                                 "OpDecorate %29 Block\n"
705                                 "OpMemberDecorate %34 0 BuiltIn Position\n"
706                                 "OpMemberDecorate %34 1 BuiltIn PointSize\n"
707                                 "OpMemberDecorate %34 2 BuiltIn ClipDistance\n"
708                                 "OpMemberDecorate %34 3 BuiltIn CullDistance\n"
709                                 "OpDecorate %34 Block\n"
710                                 "OpDecorate %47 BuiltIn TessCoord\n"
711                                 "%2 = OpTypeVoid\n"
712                                 "%3 = OpTypeFunction %2\n"
713                                 "%6 = OpTypeBool\n"
714                                 "%7 = OpTypeInt 32 0\n"
715                                 "%8 = OpConstant %7 3\n"
716                                 "%12 = OpTypeFloat 32\n"
717                                 "%13 = OpTypeVector %12 4\n"
718                                 "%14 = OpTypePointer Output %13\n"
719                                 "%15 = OpVariable %14 Output\n"
720                                 "%16 = OpConstant %12 71\n"//electedValue
721                                 "%17 = OpConstant %7 0\n"
722                                 "%18 = OpTypePointer Output %12\n"
723                                 "%20 = OpConstant %12 2\n"
724                                 "%21 = OpConstant %7 1\n"
725                                 "%24 = OpConstant %12 " + unelectedValue.str() + "\n"
726                                 "%26 = OpConstant %12 0\n"
727                                 "%28 = OpTypeArray %12 %21\n"
728                                 "%29 = OpTypeStruct %13 %12 %28 %28\n"
729                                 "%30 = OpTypePointer Output %29\n"
730                                 "%31 = OpVariable %30 Output\n"
731                                 "%32 = OpTypeInt 32 1\n"
732                                 "%33 = OpConstant %32 0\n"
733                                 "%34 = OpTypeStruct %13 %12 %28 %28\n"
734                                 "%35 = OpConstant %7 32\n"
735                                 "%36 = OpTypeArray %34 %35\n"
736                                 "%37 = OpTypePointer Input %36\n"
737                                 "%38 = OpVariable %37 Input\n"
738                                 "%39 = OpTypePointer Input %13\n"
739                                 "%42 = OpConstant %32 1\n"
740                                 "%45 = OpTypeVector %12 3\n"
741                                 "%46 = OpTypePointer Input %45\n"
742                                 "%47 = OpVariable %46 Input\n"
743                                 "%48 = OpTypePointer Input %12\n"
744                                 "%4 = OpFunction %2 None %3\n"
745                                 "%5 = OpLabel\n"
746                                 "%9 = OpGroupNonUniformElect %6 %8\n"
747                                 "OpSelectionMerge %11 None\n"
748                                 "OpBranchConditional %9 %10 %23\n"
749                                 "%10 = OpLabel\n"
750                                 "%19 = OpAccessChain %18 %15 %17\n"
751                                 "OpStore %19 %16\n"
752                                 "%22 = OpAccessChain %18 %15 %21\n"
753                                 "OpStore %22 %20\n"
754                                 "OpBranch %11\n"
755                                 "%23 = OpLabel\n"
756                                 "%25 = OpAccessChain %18 %15 %17\n"
757                                 "OpStore %25 %24\n"
758                                 "%27 = OpAccessChain %18 %15 %21\n"
759                                 "OpStore %27 %26\n"
760                                 "OpBranch %11\n"
761                                 "%11 = OpLabel\n"
762                                 "%40 = OpAccessChain %39 %38 %33 %33\n"
763                                 "%41 = OpLoad %13 %40\n"
764                                 "%43 = OpAccessChain %39 %38 %42 %33\n"
765                                 "%44 = OpLoad %13 %43\n"
766                                 "%49 = OpAccessChain %48 %47 %17\n"
767                                 "%50 = OpLoad %12 %49\n"
768                                 "%51 = OpCompositeConstruct %13 %50 %50 %50 %50\n"
769                                 "%52 = OpExtInst %13 %1 FMix %41 %44 %51\n"
770                                 "%53 = OpAccessChain %14 %31 %33\n"
771                                 "OpStore %53 %52\n"
772                                 "OpReturn\n"
773                                 "OpFunctionEnd\n";
774
775                         programCollection.spirvAsmSources.add("tese") << evaluationSource << buildOptionsSpr;
776                 }
777                 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
778                 {
779                         /*
780                                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
781                                 "#extension GL_EXT_tessellation_shader : require\n"
782                                 "layout(vertices = 2) out;\n"
783                                 "layout(location = 0) out vec4 out_color[];\n"
784                                 "void main (void)\n"
785                                 "{\n"
786                                 "  if (gl_InvocationID == 0)\n"
787                                   {\n"
788                                 "    gl_TessLevelOuter[0] = 1.0f;\n"
789                                 "    gl_TessLevelOuter[1] = 1.0f;\n"
790                                 "  }\n"
791                                 "  if (subgroupElect())\n"
792                                 "  {\n"
793                                 "    out_color[gl_InvocationID].r = " << ELECTED_VALUE << ";\n"
794                                 "    out_color[gl_InvocationID].g = 1.0f;\n"
795                                 "  }\n"
796                                 "  else\n"
797                                 "  {\n"
798                                 "    out_color[gl_InvocationID].r = " << UNELECTED_VALUE << ";\n"
799                                 "    out_color[gl_InvocationID].g = 0.0f;\n"
800                                 "  }\n"
801                                 "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
802                                 "}\n";
803                         */
804                         const string  controlSource =
805                                 "; SPIR-V\n"
806                                 "; Version: 1.3\n"
807                                 "; Generator: Khronos Glslang Reference Front End; 2\n"
808                                 "; Bound: 66\n"
809                                 "; Schema: 0\n"
810                                 "OpCapability Tessellation\n"
811                                 "OpCapability GroupNonUniform\n"
812                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
813                                 "OpMemoryModel Logical GLSL450\n"
814                                 "OpEntryPoint TessellationControl %4 \"main\" %8 %20 %34 %53 %59\n"
815                                 "OpExecutionMode %4 OutputVertices 2\n"
816                                 "OpDecorate %8 BuiltIn InvocationId\n"
817                                 "OpDecorate %20 Patch\n"
818                                 "OpDecorate %20 BuiltIn TessLevelOuter\n"
819                                 "OpDecorate %34 Location 0\n"
820                                 "OpMemberDecorate %50 0 BuiltIn Position\n"
821                                 "OpMemberDecorate %50 1 BuiltIn PointSize\n"
822                                 "OpMemberDecorate %50 2 BuiltIn ClipDistance\n"
823                                 "OpMemberDecorate %50 3 BuiltIn CullDistance\n"
824                                 "OpDecorate %50 Block\n"
825                                 "OpMemberDecorate %55 0 BuiltIn Position\n"
826                                 "OpMemberDecorate %55 1 BuiltIn PointSize\n"
827                                 "OpMemberDecorate %55 2 BuiltIn ClipDistance\n"
828                                 "OpMemberDecorate %55 3 BuiltIn CullDistance\n"
829                                 "OpDecorate %55 Block\n"
830                                 "%2 = OpTypeVoid\n"
831                                 "%3 = OpTypeFunction %2\n"
832                                 "%6 = OpTypeInt 32 1\n"
833                                 "%7 = OpTypePointer Input %6\n"
834                                 "%8 = OpVariable %7 Input\n"
835                                 "%10 = OpConstant %6 0\n"
836                                 "%11 = OpTypeBool\n"
837                                 "%15 = OpTypeFloat 32\n"
838                                 "%16 = OpTypeInt 32 0\n"
839                                 "%17 = OpConstant %16 4\n"
840                                 "%18 = OpTypeArray %15 %17\n"
841                                 "%19 = OpTypePointer Output %18\n"
842                                 "%20 = OpVariable %19 Output\n"
843                                 "%21 = OpConstant %15 1\n"
844                                 "%22 = OpTypePointer Output %15\n"
845                                 "%24 = OpConstant %6 1\n"
846                                 "%26 = OpConstant %16 3\n"
847                                 "%30 = OpTypeVector %15 4\n"
848                                 "%31 = OpConstant %16 2\n"
849                                 "%32 = OpTypeArray %30 %31\n"
850                                 "%33 = OpTypePointer Output %32\n"
851                                 "%34 = OpVariable %33 Output\n"
852                                 "%36 = OpConstant %15 " + electedValue.str() + "\n"
853                                 "%37 = OpConstant %16 0\n"
854                                 "%40 = OpConstant %16 1\n"
855                                 "%44 = OpConstant %15 " + unelectedValue.str() + "\n"
856                                 "%47 = OpConstant %15 0\n"
857                                 "%49 = OpTypeArray %15 %40\n"
858                                 "%50 = OpTypeStruct %30 %15 %49 %49\n"
859                                 "%51 = OpTypeArray %50 %31\n"
860                                 "%52 = OpTypePointer Output %51\n"
861                                 "%53 = OpVariable %52 Output\n"
862                                 "%55 = OpTypeStruct %30 %15 %49 %49\n"
863                                 "%56 = OpConstant %16 32\n"
864                                 "%57 = OpTypeArray %55 %56\n"
865                                 "%58 = OpTypePointer Input %57\n"
866                                 "%59 = OpVariable %58 Input\n"
867                                 "%61 = OpTypePointer Input %30\n"
868                                 "%64 = OpTypePointer Output %30\n"
869                                 "%4 = OpFunction %2 None %3\n"
870                                 "%5 = OpLabel\n"
871                                 "%9 = OpLoad %6 %8\n"
872                                 "%12 = OpIEqual %11 %9 %10\n"
873                                 "OpSelectionMerge %14 None\n"
874                                 "OpBranchConditional %12 %13 %14\n"
875                                 "%13 = OpLabel\n"
876                                 "%23 = OpAccessChain %22 %20 %10\n"
877                                 "OpStore %23 %21\n"
878                                 "%25 = OpAccessChain %22 %20 %24\n"
879                                 "OpStore %25 %21\n"
880                                 "OpBranch %14\n"
881                                 "%14 = OpLabel\n"
882                                 "%27 = OpGroupNonUniformElect %11 %26\n"
883                                 "OpSelectionMerge %29 None\n"
884                                 "OpBranchConditional %27 %28 %42\n"
885                                 "%28 = OpLabel\n"
886                                 "%35 = OpLoad %6 %8\n"
887                                 "%38 = OpAccessChain %22 %34 %35 %37\n"
888                                 "OpStore %38 %36\n"
889                                 "%39 = OpLoad %6 %8\n"
890                                 "%41 = OpAccessChain %22 %34 %39 %40\n"
891                                 "OpStore %41 %21\n"
892                                 "OpBranch %29\n"
893                                 "%42 = OpLabel\n"
894                                 "%43 = OpLoad %6 %8\n"
895                                 "%45 = OpAccessChain %22 %34 %43 %37\n"
896                                 "OpStore %45 %44\n"
897                                 "%46 = OpLoad %6 %8\n"
898                                 "%48 = OpAccessChain %22 %34 %46 %40\n"
899                                 "OpStore %48 %47\n"
900                                 "OpBranch %29\n"
901                                 "%29 = OpLabel\n"
902                                 "%54 = OpLoad %6 %8\n"
903                                 "%60 = OpLoad %6 %8\n"
904                                 "%62 = OpAccessChain %61 %59 %60 %10\n"
905                                 "%63 = OpLoad %30 %62\n"
906                                 "%65 = OpAccessChain %64 %53 %54 %10\n"
907                                 "OpStore %65 %63\n"
908                                 "OpReturn\n"
909                                 "OpFunctionEnd\n";
910                         programCollection.spirvAsmSources.add("tesc") << controlSource << buildOptionsSpr;
911
912                         /*
913                                 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
914                                 "#extension GL_EXT_tessellation_shader : require\n"
915                                 "layout(isolines, equal_spacing, ccw ) in;\n"
916                                 "layout(location = 0) in vec4 in_color[];\n"
917                                 "layout(location = 0) out vec4 out_color;\n"
918                                 "\n"
919                                 "void main (void)\n"
920                                 "{\n"
921                                 "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
922                                 "  out_color = in_color[0];\n"
923                                 "}\n";
924                         */
925
926                         const string evaluationSource =
927                                 "; SPIR-V\n"
928                                 "; Version: 1.3\n"
929                                 "; Generator: Khronos Glslang Reference Front End; 2\n"
930                                 "; Bound: 44\n"
931                                 "; Schema: 0\n"
932                                 "OpCapability Tessellation\n"
933                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
934                                 "OpMemoryModel Logical GLSL450\n"
935                                 "OpEntryPoint TessellationEvaluation %4 \"main\" %13 %20 %29 %38 %41\n"
936                                 "OpExecutionMode %4 Isolines\n"
937                                 "OpExecutionMode %4 SpacingEqual\n"
938                                 "OpExecutionMode %4 VertexOrderCcw\n"
939                                 "OpMemberDecorate %11 0 BuiltIn Position\n"
940                                 "OpMemberDecorate %11 1 BuiltIn PointSize\n"
941                                 "OpMemberDecorate %11 2 BuiltIn ClipDistance\n"
942                                 "OpMemberDecorate %11 3 BuiltIn CullDistance\n"
943                                 "OpDecorate %11 Block\n"
944                                 "OpMemberDecorate %16 0 BuiltIn Position\n"
945                                 "OpMemberDecorate %16 1 BuiltIn PointSize\n"
946                                 "OpMemberDecorate %16 2 BuiltIn ClipDistance\n"
947                                 "OpMemberDecorate %16 3 BuiltIn CullDistance\n"
948                                 "OpDecorate %16 Block\n"
949                                 "OpDecorate %29 BuiltIn TessCoord\n"
950                                 "OpDecorate %38 Location 0\n"
951                                 "OpDecorate %41 Location 0\n"
952                                 "%2 = OpTypeVoid\n"
953                                 "%3 = OpTypeFunction %2\n"
954                                 "%6 = OpTypeFloat 32\n"
955                                 "%7 = OpTypeVector %6 4\n"
956                                 "%8 = OpTypeInt 32 0\n"
957                                 "%9 = OpConstant %8 1\n"
958                                 "%10 = OpTypeArray %6 %9\n"
959                                 "%11 = OpTypeStruct %7 %6 %10 %10\n"
960                                 "%12 = OpTypePointer Output %11\n"
961                                 "%13 = OpVariable %12 Output\n"
962                                 "%14 = OpTypeInt 32 1\n"
963                                 "%15 = OpConstant %14 0\n"
964                                 "%16 = OpTypeStruct %7 %6 %10 %10\n"
965                                 "%17 = OpConstant %8 32\n"
966                                 "%18 = OpTypeArray %16 %17\n"
967                                 "%19 = OpTypePointer Input %18\n"
968                                 "%20 = OpVariable %19 Input\n"
969                                 "%21 = OpTypePointer Input %7\n"
970                                 "%24 = OpConstant %14 1\n"
971                                 "%27 = OpTypeVector %6 3\n"
972                                 "%28 = OpTypePointer Input %27\n"
973                                 "%29 = OpVariable %28 Input\n"
974                                 "%30 = OpConstant %8 0\n"
975                                 "%31 = OpTypePointer Input %6\n"
976                                 "%36 = OpTypePointer Output %7\n"
977                                 "%38 = OpVariable %36 Output\n"
978                                 "%39 = OpTypeArray %7 %17\n"
979                                 "%40 = OpTypePointer Input %39\n"
980                                 "%41 = OpVariable %40 Input\n"
981                                 "%4 = OpFunction %2 None %3\n"
982                                 "%5 = OpLabel\n"
983                                 "%22 = OpAccessChain %21 %20 %15 %15\n"
984                                 "%23 = OpLoad %7 %22\n"
985                                 "%25 = OpAccessChain %21 %20 %24 %15\n"
986                                 "%26 = OpLoad %7 %25\n"
987                                 "%32 = OpAccessChain %31 %29 %30\n"
988                                 "%33 = OpLoad %6 %32\n"
989                                 "%34 = OpCompositeConstruct %7 %33 %33 %33 %33\n"
990                                 "%35 = OpExtInst %7 %1 FMix %23 %26 %34\n"
991                                 "%37 = OpAccessChain %36 %13 %15\n"
992                                 "OpStore %37 %35\n"
993                                 "%42 = OpAccessChain %21 %41 %15\n"
994                                 "%43 = OpLoad %7 %42\n"
995                                 "OpStore %38 %43\n"
996                                 "OpReturn\n"
997                                 "OpFunctionEnd\n";
998                         programCollection.spirvAsmSources.add("tese") << evaluationSource << buildOptionsSpr;
999                 }
1000                 else
1001                 {
1002                         DE_FATAL("Unsupported shader stage");
1003                 }
1004         }
1005         else
1006         {
1007                 std::ostringstream bdy;
1008                 string color = (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) ? "out_color[gl_InvocationID].b = 1.0f;\n" : "out_color.b = 1.0f;\n";
1009                 switch (caseDef.opType)
1010                 {
1011                         default:
1012                                 DE_FATAL("Unhandled op type!");
1013                                 break;
1014                         case OPTYPE_SUBGROUP_BARRIER:
1015                         case OPTYPE_SUBGROUP_MEMORY_BARRIER:
1016                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
1017                         {
1018                                 bdy << " tempResult2 = tempBuffer[id];\n"
1019                                         << "  if (subgroupElect())\n"
1020                                         << "  {\n"
1021                                         << "    tempResult = value;\n"
1022                                         << "    " << color
1023                                         << "  }\n"
1024                                          << "  else\n"
1025                                         << "  {\n"
1026                                         << "    tempResult = tempBuffer[id];\n"
1027                                         << "  }\n"
1028                                         << "  " << getOpTypeName(caseDef.opType) << "();\n";
1029                                 break;
1030                         }
1031                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
1032                                 bdy <<"tempResult2 = imageLoad(tempImage, ivec2(id, 0)).x;\n"
1033                                         << "  if (subgroupElect())\n"
1034                                         << "  {\n"
1035                                         << "    tempResult = value;\n"
1036                                         << "     " << color
1037                                         << "  }\n"
1038                                         << "  else\n"
1039                                         << "  {\n"
1040                                         << "    tempResult = imageLoad(tempImage, ivec2(id, 0)).x;\n"
1041                                         << "  }\n"
1042                                         << "  subgroupMemoryBarrierImage();\n";
1043
1044                                 break;
1045                 }
1046
1047                 if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
1048                 {
1049                         std::ostringstream      fragment;
1050                         fragment        << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1051                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1052                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1053                                 << "layout(location = 0) out vec4 out_color;\n"
1054                                 << "\n"
1055                                 << "layout(set = 0, binding = 0) uniform Buffer1\n"
1056                                 << "{\n"
1057                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1058                                 << "};\n"
1059                                 << "\n"
1060                                 << "layout(set = 0, binding = 1) uniform Buffer2\n"
1061                                 << "{\n"
1062                                 << "  uint value;\n"
1063                                 << "};\n"
1064                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1065                                 << "void main (void)\n"
1066                                 << "{\n"
1067                                 << "  if (gl_HelperInvocation) return;\n"
1068                                 << "  uint id = 0;\n"
1069                                 << "  if (subgroupElect())\n"
1070                                 << "  {\n"
1071                                 << "    id = uint(gl_FragCoord.x);\n"
1072                                 << "  }\n"
1073                                 << "  id = subgroupBroadcastFirst(id);\n"
1074                                 << "  uint localId = id;\n"
1075                                 << "  uint tempResult = 0u;\n"
1076                                 << "  uint tempResult2 = 0u;\n"
1077                                 << "  out_color.b = 0.0f;\n"
1078                                 << bdy.str()
1079                                 << "  out_color.r = float(tempResult);\n"
1080                                 << "  out_color.g = float(value);\n"
1081                                 << "  out_color.a = float(tempResult2);\n"
1082                                 << "}\n";
1083                         programCollection.glslSources.add("fragment")
1084                                 << glu::FragmentSource(fragment.str()) << buildOptions;
1085                 }
1086                 else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
1087                 {
1088                         std::ostringstream      vertex;
1089                         vertex  << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1090                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1091                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1092                                 <<"\n"
1093                                 << "layout(location = 0) out vec4 out_color;\n"
1094                                 << "layout(location = 0) in highp vec4 in_position;\n"
1095                                 << "\n"
1096                                 << "layout(set = 0, binding = 0) uniform Buffer1\n"
1097                                 << "{\n"
1098                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1099                                 << "};\n"
1100                                 << "\n"
1101                                 << "layout(set = 0, binding = 1) uniform Buffer2\n"
1102                                 << "{\n"
1103                                 << "  uint value;\n"
1104                                 << "};\n"
1105                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1106                                 << "void main (void)\n"
1107                                 << "{\n"
1108                                 << "  uint id = 0;\n"
1109                                 << "  if (subgroupElect())\n"
1110                                 << "  {\n"
1111                                 << "    id = gl_VertexIndex;\n"
1112                                 << "  }\n"
1113                                 << "  id = subgroupBroadcastFirst(id);\n"
1114                                 << "  uint tempResult = 0u;\n"
1115                                 << "  uint tempResult2 = 0u;\n"
1116                                 << "  out_color.b = 0.0f;\n"
1117                                 << bdy.str()
1118                                 << "  out_color.r = float(tempResult);\n"
1119                                 << "  out_color.g = float(value);\n"
1120                                 << "  out_color.a = float(tempResult2);\n"
1121                                 << "  gl_Position = in_position;\n"
1122                                 << "  gl_PointSize = 1.0f;\n"
1123                                 << "}\n";
1124                         programCollection.glslSources.add("vert")
1125                                 << glu::VertexSource(vertex.str()) << buildOptions;
1126                 }
1127         else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
1128                 {
1129                         std::ostringstream geometry;
1130
1131                         geometry << "#version 450\n"
1132                                         << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1133                                         << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1134                                         << "layout(points) in;\n"
1135                                         << "layout(points, max_vertices = 1) out;\n"
1136                                         << "layout(location = 0) out vec4 out_color;\n"
1137                                         << "layout(set = 0, binding = 0) uniform Buffer1\n"
1138                                         << "{\n"
1139                                         << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1140                                         << "};\n"
1141                                         << "\n"
1142                                         << "layout(set = 0, binding = 1) uniform Buffer2\n"
1143                                         << "{\n"
1144                                         << "  uint value;\n"
1145                                         << "};\n"
1146                                         << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1147                                         << "void main (void)\n"
1148                                         << "{\n"
1149                                         << "  uint id = 0;\n"
1150                                         << "  if (subgroupElect())\n"
1151                                         << "  {\n"
1152                                         << "    id = gl_InvocationID;\n"
1153                                         << "  }\n"
1154                                         << "  id = subgroupBroadcastFirst(id);\n"
1155                                         << "  uint tempResult = 0u;\n"
1156                                         << "  uint tempResult2 = 0u;\n"
1157                                         << "  out_color.b = 0.0f;\n"
1158                                         << bdy.str()
1159                                         << "  out_color.r = float(tempResult);\n"
1160                                         << "  out_color.g = float(value);\n"
1161                                         << "  out_color.a = float(tempResult2);\n"
1162                                         << "  gl_Position = gl_in[0].gl_Position;\n"
1163                                         << "  EmitVertex();\n"
1164                                         << "  EndPrimitive();\n"
1165                                         << "}\n";
1166
1167                         programCollection.glslSources.add("geometry")
1168                                 << glu::GeometrySource(geometry.str()) << buildOptions;
1169                 }
1170                 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
1171                 {
1172                         std::ostringstream controlSource;
1173                         std::ostringstream evaluationSource;
1174
1175                         controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1176                                 << "#extension GL_EXT_tessellation_shader : require\n"
1177                                 << "layout(vertices = 2) out;\n"
1178                                 << "void main (void)\n"
1179                                 << "{\n"
1180                                 << "  if (gl_InvocationID == 0)\n"
1181                                 <<"  {\n"
1182                                 << "    gl_TessLevelOuter[0] = 1.0f;\n"
1183                                 << "    gl_TessLevelOuter[1] = 1.0f;\n"
1184                                 << "  }\n"
1185                                 << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1186                                 << "}\n";
1187
1188                         evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1189                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1190                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1191                                 << "#extension GL_EXT_tessellation_shader : require\n"
1192                                 << "layout(isolines, equal_spacing, ccw ) in;\n"
1193                                 << "layout(location = 0) out vec4 out_color;\n"
1194                                 << "layout(set = 0, binding = 0) uniform Buffer1\n"
1195                                 << "{\n"
1196                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1197                                 << "};\n"
1198                                 << "\n"
1199                                 << "layout(set = 0, binding = 1) uniform Buffer2\n"
1200                                 << "{\n"
1201                                 << "  uint value;\n"
1202                                 << "};\n"
1203                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1204                                 << "void main (void)\n"
1205                                 << "{\n"
1206                                 << "  uint id = 0;\n"
1207                                 << "  if (subgroupElect())\n"
1208                                 << "  {\n"
1209                                 << "    id = gl_PrimitiveID;\n"
1210                                 << "  }\n"
1211                                 << "  id = subgroupBroadcastFirst(id);\n"
1212                                 << "  uint tempResult = 0u;\n"
1213                                 << "  uint tempResult2 = 0u;\n"
1214                                 << "  out_color.b = 0.0f;\n"
1215                                 << bdy.str()
1216                                 << "  out_color.r = float(tempResult);\n"
1217                                 << "  out_color.g = float(value);\n"
1218                                 << "  out_color.a = float(tempResult2);\n"
1219                                 << "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
1220                                 << "}\n";
1221
1222                         programCollection.glslSources.add("tesc")
1223                                 << glu::TessellationControlSource(controlSource.str()) << buildOptions;
1224                         programCollection.glslSources.add("tese")
1225                                 << glu::TessellationEvaluationSource(evaluationSource.str()) << buildOptions;
1226                 }
1227                 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
1228                 {
1229                         std::ostringstream controlSource;
1230                         std::ostringstream evaluationSource;
1231
1232                         controlSource  << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1233                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1234                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1235                                 << "#extension GL_EXT_tessellation_shader : require\n"
1236                                 << "layout(vertices = 2) out;\n"
1237                                 << "layout(location = 0) out vec4 out_color[];\n"
1238                                 << "layout(set = 0, binding = 0) uniform Buffer1\n"
1239                                 << "{\n"
1240                                 << "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1241                                 << "};\n"
1242                                 << "\n"
1243                                 << "layout(set = 0, binding = 1) uniform Buffer2\n"
1244                                 << "{\n"
1245                                 << "  uint value;\n"
1246                                 << "};\n"
1247                                 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1248                                 << "void main (void)\n"
1249                                 << "{\n"
1250                                 << "  uint id = 0;\n"
1251                                 << "  if (gl_InvocationID == 0)\n"
1252                                 <<"  {\n"
1253                                 << "    gl_TessLevelOuter[0] = 1.0f;\n"
1254                                 << "    gl_TessLevelOuter[1] = 1.0f;\n"
1255                                 << "  }\n"
1256                                 << "  if (subgroupElect())\n"
1257                                 << "  {\n"
1258                                 << "    id = gl_InvocationID;\n"
1259                                 << "  }\n"
1260                                 << "  id = subgroupBroadcastFirst(id);\n"
1261                                 << "  uint tempResult = 0u;\n"
1262                                 << "  uint tempResult2 = 0u;\n"
1263                                 << "  out_color[gl_InvocationID].b = 0.0f;\n"
1264                                 << bdy.str()
1265                                 << "  out_color[gl_InvocationID].r = float(tempResult);\n"
1266                                 << "  out_color[gl_InvocationID].g = float(value);\n"
1267                                 << "  out_color[gl_InvocationID].a = float(tempResult2);\n"
1268                                 << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1269                                 << "}\n";
1270
1271                         evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1272                                 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1273                                 << "#extension GL_EXT_tessellation_shader : require\n"
1274                                 << "layout(isolines, equal_spacing, ccw ) in;\n"
1275                                 << "layout(location = 0) in vec4 in_color[];\n"
1276                                 << "layout(location = 0) out vec4 out_color;\n"
1277                                 << "\n"
1278                                 << "void main (void)\n"
1279                                 << "{\n"
1280                                 << "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
1281                                 << "  out_color = in_color[0];\n"
1282                                 << "}\n";
1283
1284                         programCollection.glslSources.add("tesc")
1285                                 << glu::TessellationControlSource(controlSource.str()) << buildOptions;
1286                         programCollection.glslSources.add("tese")
1287                                 << glu::TessellationEvaluationSource(evaluationSource.str()) << buildOptions;
1288                 }
1289                 else
1290                 {
1291                         DE_FATAL("Unsupported shader stage");
1292                 }
1293         }
1294 }
1295
1296 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
1297 {
1298         if (OPTYPE_ELECT == caseDef.opType)
1299         {
1300                 if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1301                 {
1302                         std::ostringstream src;
1303
1304                         src << "#version 450\n"
1305                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1306                                 << "layout (local_size_x_id = 0, local_size_y_id = 1, "
1307                                 "local_size_z_id = 2) in;\n"
1308                                 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1309                                 << "{\n"
1310                                 << "  uint result[];\n"
1311                                 << "};\n"
1312                                 << "\n"
1313                                 << subgroups::getSharedMemoryBallotHelper()
1314                                 << "void main (void)\n"
1315                                 << "{\n"
1316                                 << "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
1317                                 << "  highp uint offset = globalSize.x * ((globalSize.y * "
1318                                 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
1319                                 "gl_GlobalInvocationID.x;\n"
1320                                 << "  uint value = " << UNELECTED_VALUE << ";\n"
1321                                 << "  if (subgroupElect())\n"
1322                                 << "  {\n"
1323                                 << "    value = " << ELECTED_VALUE << ";\n"
1324                                 << "  }\n"
1325                                 << "  uvec4 bits = bitCount(sharedMemoryBallot(value == " << ELECTED_VALUE << "));\n"
1326                                 << "  result[offset] = bits.x + bits.y + bits.z + bits.w;\n"
1327                                 << "}\n";
1328
1329                         programCollection.glslSources.add("comp")
1330                                         << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1331                 }
1332                 else
1333                 {
1334                         {
1335                                 std::ostringstream  vertex;
1336                                 vertex  << "#version 450\n"
1337                                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1338                                                 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1339                                                 << "{\n"
1340                                                 << "  uint result[];\n"
1341                                                 << "};\n"
1342                                                 << "layout(set = 0, binding = 4, std430) buffer Buffer2\n"
1343                                                 << "{\n"
1344                                                 << "  uint numSubgroupsExecuted;\n"
1345                                                 << "};\n"
1346                                                 << "\n"
1347                                                 << "void main (void)\n"
1348                                                 << "{\n"
1349                                                 << "  if (subgroupElect())\n"
1350                                                 << "  {\n"
1351                                                 << "    result[gl_VertexIndex] = " << ELECTED_VALUE << ";\n"
1352                                                 << "    atomicAdd(numSubgroupsExecuted, 1);\n"
1353                                                 << "  }\n"
1354                                                 << "  else\n"
1355                                                 << "  {\n"
1356                                                 << "    result[gl_VertexIndex] = " << UNELECTED_VALUE << ";\n"
1357                                                 << "  }\n"
1358                                                 << "  float pixelSize = 2.0f/1024.0f;\n"
1359                                                 << "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
1360                                                 << "  gl_Position = vec4(float(gl_VertexIndex) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
1361                                                 << "  gl_PointSize = 1.0f;\n"
1362                                                 << "}\n";
1363                                 programCollection.glslSources.add("vert")
1364                                         << glu::VertexSource(vertex.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1365                         }
1366
1367                         {
1368                                 std::ostringstream tesc;
1369                                 tesc    << "#version 450\n"
1370                                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1371                                                 << "layout(vertices=1) out;\n"
1372                                                 << "layout(set = 0, binding = 1, std430) buffer Buffer1\n"
1373                                                 << "{\n"
1374                                                 << "  uint result[];\n"
1375                                                 << "};\n"
1376                                                 << "layout(set = 0, binding = 5, std430) buffer Buffer2\n"
1377                                                 << "{\n"
1378                                                 << "  uint numSubgroupsExecuted;\n"
1379                                                 << "};\n"
1380                                                 << "\n"
1381                                                 << "void main (void)\n"
1382                                                 << "{\n"
1383                                                 << "  if (subgroupElect())\n"
1384                                                 << "  {\n"
1385                                                 << "    result[gl_PrimitiveID] = " << ELECTED_VALUE << ";\n"
1386                                                 << "    atomicAdd(numSubgroupsExecuted, 1);\n"
1387                                                 << "  }\n"
1388                                                 << "  else\n"
1389                                                 << "  {\n"
1390                                                 << "    result[gl_PrimitiveID] = " << UNELECTED_VALUE << ";\n"
1391                                                 << "  }\n"
1392                                                 << "  if (gl_InvocationID == 0)\n"
1393                                                 << "  {\n"
1394                                                 << "    gl_TessLevelOuter[0] = 1.0f;\n"
1395                                                 << "    gl_TessLevelOuter[1] = 1.0f;\n"
1396                                                 << "  }\n"
1397                                                 << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1398                                                 << "}\n";
1399                                 programCollection.glslSources.add("tesc")
1400                                         << glu::TessellationControlSource(tesc.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1401                         }
1402
1403                         {
1404                                 std::ostringstream tese;
1405                                 tese    << "#version 450\n"
1406                                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1407                                                 << "layout(isolines) in;\n"
1408                                                 << "layout(set = 0, binding = 2, std430) buffer Buffer1\n"
1409                                                 << "{\n"
1410                                                 << "  uint result[];\n"
1411                                                 << "};\n"
1412                                                 << "layout(set = 0, binding = 6, std430) buffer Buffer2\n"
1413                                                 << "{\n"
1414                                                 << "  uint numSubgroupsExecuted;\n"
1415                                                 << "};\n"
1416                                                 << "\n"
1417                                                 << "void main (void)\n"
1418                                                 << "{\n"
1419                                                 << "  if (subgroupElect())\n"
1420                                                 << "  {\n"
1421                                                 << "    result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << ELECTED_VALUE << ";\n"
1422                                                 << "    atomicAdd(numSubgroupsExecuted, 1);\n"
1423                                                 << "  }\n"
1424                                                 << "  else\n"
1425                                                 << "  {\n"
1426                                                 << "    result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << UNELECTED_VALUE << ";\n"
1427                                                 << "  }\n"
1428                                                 << "  float pixelSize = 2.0f/1024.0f;\n"
1429                                                 << "  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
1430                                                 << "}\n";
1431                                 programCollection.glslSources.add("tese")
1432                                         << glu::TessellationEvaluationSource(tese.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1433                         }
1434
1435                         {
1436                                 std::ostringstream geometry;
1437                                 geometry        << "#version 450\n"
1438                                                         << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1439                                                         << "layout(${TOPOLOGY}) in;\n"
1440                                                         << "layout(points, max_vertices = 1) out;\n"
1441                                                         << "layout(set = 0, binding = 3, std430) buffer Buffer1\n"
1442                                                         << "{\n"
1443                                                         << "  uint result[];\n"
1444                                                         << "};\n"
1445                                                         << "layout(set = 0, binding = 7, std430) buffer Buffer2\n"
1446                                                         << "{\n"
1447                                                         << "  uint numSubgroupsExecuted;\n"
1448                                                         << "};\n"
1449                                                         << "\n"
1450                                                         << "void main (void)\n"
1451                                                         << "{\n"
1452                                                         << "  if (subgroupElect())\n"
1453                                                         << "  {\n"
1454                                                         << "    result[gl_PrimitiveIDIn] = " << ELECTED_VALUE << ";\n"
1455                                                         << "    atomicAdd(numSubgroupsExecuted, 1);\n"
1456                                                         << "  }\n"
1457                                                         << "  else\n"
1458                                                         << "  {\n"
1459                                                         << "    result[gl_PrimitiveIDIn] = " << UNELECTED_VALUE << ";\n"
1460                                                         << "  }\n"
1461                                                         << "  gl_Position = gl_in[0].gl_Position;\n"
1462                                                         << "  EmitVertex();\n"
1463                                                         << "  EndPrimitive();\n"
1464                                                         << "}\n";
1465                                 subgroups::addGeometryShadersFromTemplate(geometry.str(), vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u),
1466                                                                                                                   programCollection.glslSources);
1467                         }
1468
1469                         {
1470                                 std::ostringstream fragment;
1471                                 fragment        << "#version 450\n"
1472                                                         << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1473                                                         << "layout(location = 0) out uint data;\n"
1474                                                         << "layout(set = 0, binding = 8, std430) buffer Buffer\n"
1475                                                         << "{\n"
1476                                                         << "  uint numSubgroupsExecuted;\n"
1477                                                         << "};\n"
1478                                                         << "void main (void)\n"
1479                                                         << "{\n"
1480                                                         << "  if (gl_HelperInvocation) return;\n"
1481                                                         << "  if (subgroupElect())\n"
1482                                                         << "  {\n"
1483                                                         << "    data = " << ELECTED_VALUE << ";\n"
1484                                                         << "    atomicAdd(numSubgroupsExecuted, 1);\n"
1485                                                         << "  }\n"
1486                                                         << "  else\n"
1487                                                         << "  {\n"
1488                                                         << "    data = " << UNELECTED_VALUE << ";\n"
1489                                                         << "  }\n"
1490                                                         << "}\n";
1491                                 programCollection.glslSources.add("fragment")
1492                                         << glu::FragmentSource(fragment.str())<< vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1493                         }
1494                         subgroups::addNoSubgroupShader(programCollection);
1495                 }
1496         }
1497         else
1498         {
1499                 std::ostringstream bdy;
1500
1501                 switch (caseDef.opType)
1502                 {
1503                         default:
1504                                 DE_FATAL("Unhandled op type!");
1505                                 break;
1506                         case OPTYPE_SUBGROUP_BARRIER:
1507                         case OPTYPE_SUBGROUP_MEMORY_BARRIER:
1508                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
1509                                 bdy << "  if (subgroupElect())\n"
1510                                         << "  {\n"
1511                                         << "    tempBuffer[id] = value;\n"
1512                                         << "  }\n"
1513                                         << "  " << getOpTypeName(caseDef.opType) << "();\n"
1514                                         << "  tempResult = tempBuffer[id];\n";
1515                                 break;
1516                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
1517                                 bdy << "  if (subgroupElect())\n"
1518                                         << "  {\n"
1519                                         << "    tempShared[localId] = value;\n"
1520                                         << "  }\n"
1521                                         << "  subgroupMemoryBarrierShared();\n"
1522                                         << "  tempResult = tempShared[localId];\n";
1523                                 break;
1524                         case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
1525                                 bdy << "  if (subgroupElect())\n"
1526                                         << "  {\n"
1527                                         << "    imageStore(tempImage, ivec2(id, 0), ivec4(value));\n"
1528                                         << "  }\n"
1529                                         << "  subgroupMemoryBarrierImage();\n"
1530                                         << "  tempResult = imageLoad(tempImage, ivec2(id, 0)).x;\n";
1531                                 break;
1532                 }
1533
1534                 if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1535                 {
1536                         std::ostringstream src;
1537
1538                         src << "#version 450\n"
1539                                 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
1540                                 << "layout (local_size_x_id = 0, local_size_y_id = 1, "
1541                                 "local_size_z_id = 2) in;\n"
1542                                 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1543                                 << "{\n"
1544                                 << "  uint result[];\n"
1545                                 << "};\n"
1546                                 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
1547                                 << "{\n"
1548                                 << "  uint tempBuffer[];\n"
1549                                 << "};\n"
1550                                 << "layout(set = 0, binding = 2, std430) buffer Buffer3\n"
1551                                 << "{\n"
1552                                 << "  uint value;\n"
1553                                 << "};\n"
1554                                 << "layout(set = 0, binding = 3, r32ui) uniform uimage2D tempImage;\n"
1555                                 << "shared uint tempShared[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
1556                                 << "\n"
1557                                 << "void main (void)\n"
1558                                 << "{\n"
1559                                 << "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
1560                                 << "  highp uint offset = globalSize.x * ((globalSize.y * "
1561                                 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
1562                                 "gl_GlobalInvocationID.x;\n"
1563                                 << "  uint localId = gl_SubgroupID;\n"
1564                                 << "  uint id = globalSize.x * ((globalSize.y * "
1565                                 "gl_WorkGroupID.z) + gl_WorkGroupID.y) + "
1566                                 "gl_WorkGroupID.x + localId;\n"
1567                                 << "  uint tempResult = 0;\n"
1568                                 << bdy.str()
1569                                 << "  result[offset] = tempResult;\n"
1570                                 << "}\n";
1571
1572                         programCollection.glslSources.add("comp")
1573                                         << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1574                 }
1575                 else
1576                 {
1577                         {
1578                                 const string vertex =
1579                                         "#version 450\n"
1580                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1581                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1582                                         "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1583                                         "{\n"
1584                                         "  uint result[];\n"
1585                                         "};\n"
1586                                         "layout(set = 0, binding = 4, std430) buffer Buffer2\n"
1587                                         "{\n"
1588                                         "  uint tempBuffer[];\n"
1589                                         "};\n"
1590                                         "layout(set = 0, binding = 5, std430) buffer Buffer3\n"
1591                                         "{\n"
1592                                         "  uint subgroupID;\n"
1593                                         "};\n"
1594                                         "layout(set = 0, binding = 6, std430) buffer Buffer4\n"
1595                                         "{\n"
1596                                         "  uint value;\n"
1597                                         "};\n"
1598                                         "layout(set = 0, binding = 7, r32ui) uniform uimage2D tempImage;\n"
1599                                         "void main (void)\n"
1600                                         "{\n"
1601                                         "  uint id = 0;\n"
1602                                         "  if (subgroupElect())\n"
1603                                         "  {\n"
1604                                         "    id = atomicAdd(subgroupID, 1);\n"
1605                                         "  }\n"
1606                                         "  id = subgroupBroadcastFirst(id);\n"
1607                                         "  uint localId = id;\n"
1608                                         "  uint tempResult = 0;\n"
1609                                         + bdy.str() +
1610                                         "  result[gl_VertexIndex] = tempResult;\n"
1611                                         "  float pixelSize = 2.0f/1024.0f;\n"
1612                                         "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
1613                                         "  gl_Position = vec4(float(gl_VertexIndex) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
1614                                         "  gl_PointSize = 1.0f;\n"
1615                                         "}\n";
1616                                 programCollection.glslSources.add("vert")
1617                                         << glu::VertexSource(vertex) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1618                         }
1619
1620                         {
1621                                 const string tesc =
1622                                         "#version 450\n"
1623                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1624                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1625                                         "layout(vertices=1) out;\n"
1626                                         "layout(set = 0, binding = 1, std430) buffer Buffer1\n"
1627                                         "{\n"
1628                                         "  uint result[];\n"
1629                                         "};\n"
1630                                         "layout(set = 0, binding = 8, std430) buffer Buffer2\n"
1631                                         "{\n"
1632                                         "  uint tempBuffer[];\n"
1633                                         "};\n"
1634                                         "layout(set = 0, binding = 9, std430) buffer Buffer3\n"
1635                                         "{\n"
1636                                         "  uint subgroupID;\n"
1637                                         "};\n"
1638                                         "layout(set = 0, binding = 10, std430) buffer Buffer4\n"
1639                                         "{\n"
1640                                         "  uint value;\n"
1641                                         "};\n"
1642                                         "layout(set = 0, binding = 11, r32ui) uniform uimage2D tempImage;\n"
1643                                         "void main (void)\n"
1644                                         "{\n"
1645                                         "  uint id = 0;\n"
1646                                         "  if (subgroupElect())\n"
1647                                         "  {\n"
1648                                         "    id = atomicAdd(subgroupID, 1);\n"
1649                                         "  }\n"
1650                                         "  id = subgroupBroadcastFirst(id);\n"
1651                                         "  uint localId = id;\n"
1652                                         "  uint tempResult = 0;\n"
1653                                         + bdy.str() +
1654                                         "  result[gl_PrimitiveID] = tempResult;\n"
1655                                         "  if (gl_InvocationID == 0)\n"
1656                                         "  {\n"
1657                                         "    gl_TessLevelOuter[0] = 1.0f;\n"
1658                                         "    gl_TessLevelOuter[1] = 1.0f;\n"
1659                                         "  }\n"
1660                                         "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1661                                         "}\n";
1662                                 programCollection.glslSources.add("tesc")
1663                                         << glu::TessellationControlSource(tesc) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1664                         }
1665
1666                         {
1667                                 const string tese =
1668                                         "#version 450\n"
1669                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1670                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1671                                         "layout(isolines) in;\n"
1672                                         "layout(set = 0, binding = 2, std430) buffer Buffer1\n"
1673                                         "{\n"
1674                                         "  uint result[];\n"
1675                                         "};\n"
1676                                         "layout(set = 0, binding = 12, std430) buffer Buffer2\n"
1677                                         "{\n"
1678                                         "  uint tempBuffer[];\n"
1679                                         "};\n"
1680                                         "layout(set = 0, binding = 13, std430) buffer Buffer3\n"
1681                                         "{\n"
1682                                         "  uint subgroupID;\n"
1683                                         "};\n"
1684                                         "layout(set = 0, binding = 14, std430) buffer Buffer4\n"
1685                                         "{\n"
1686                                         "  uint value;\n"
1687                                         "};\n"
1688                                         "layout(set = 0, binding = 15, r32ui) uniform uimage2D tempImage;\n"
1689                                         "void main (void)\n"
1690                                         "{\n"
1691                                         "  uint id = 0;\n"
1692                                         "  if (subgroupElect())\n"
1693                                         "  {\n"
1694                                         "    id = atomicAdd(subgroupID, 1);\n"
1695                                         "  }\n"
1696                                         "  id = subgroupBroadcastFirst(id);\n"
1697                                         "  uint localId = id;\n"
1698                                         "  uint tempResult = 0;\n"
1699                                         + bdy.str() +
1700                                         "  result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
1701                                         "  float pixelSize = 2.0f/1024.0f;\n""  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
1702                                         "}\n";
1703                                 programCollection.glslSources.add("tese")
1704                                         << glu::TessellationEvaluationSource(tese) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1705                         }
1706
1707                         {
1708                                 const string geometry =
1709                                         "#version 450\n"
1710                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1711                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1712                                         "layout(${TOPOLOGY}) in;\n"
1713                                         "layout(points, max_vertices = 1) out;\n"
1714                                         "layout(set = 0, binding = 3, std430) buffer Buffer1\n"
1715                                         "{\n"
1716                                         "  uint result[];\n"
1717                                         "};\n"
1718                                         "layout(set = 0, binding = 16, std430) buffer Buffer2\n"
1719                                         "{\n"
1720                                         "  uint tempBuffer[];\n"
1721                                         "};\n"
1722                                         "layout(set = 0, binding = 17, std430) buffer Buffer3\n"
1723                                         "{\n"
1724                                         "  uint subgroupID;\n"
1725                                         "};\n"
1726                                         "layout(set = 0, binding = 18, std430) buffer Buffer4\n"
1727                                         "{\n"
1728                                         "  uint value;\n"
1729                                         "};\n"
1730                                         "layout(set = 0, binding = 19, r32ui) uniform uimage2D tempImage;\n"
1731                                         "void main (void)\n"
1732                                         "{\n"
1733                                         "  uint id = 0;\n"
1734                                         "  if (subgroupElect())\n"
1735                                         "  {\n"
1736                                         "    id = atomicAdd(subgroupID, 1);\n"
1737                                         "  }\n"
1738                                         "  id = subgroupBroadcastFirst(id);\n"
1739                                         "  uint localId = id;\n"
1740                                         "  uint tempResult = 0;\n"
1741                                          + bdy.str() +
1742                                         "  result[gl_PrimitiveIDIn] = tempResult;\n"
1743                                         "  gl_Position = gl_in[0].gl_Position;\n"
1744                                         "  EmitVertex();\n"
1745                                         "  EndPrimitive();\n"
1746                                         "}\n";
1747                                 subgroups::addGeometryShadersFromTemplate(geometry, vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u),
1748                                                                                                                   programCollection.glslSources);
1749                         }
1750
1751                         {
1752                                 const string fragment =
1753                                         "#version 450\n"
1754                                         "#extension GL_KHR_shader_subgroup_basic: enable\n"
1755                                         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1756                                         "layout(location = 0) out uint result;\n"
1757                                         "layout(set = 0, binding = 20, std430) buffer Buffer1\n"
1758                                         "{\n"
1759                                         "  uint tempBuffer[];\n"
1760                                         "};\n"
1761                                         "layout(set = 0, binding = 21, std430) buffer Buffer2\n"
1762                                         "{\n"
1763                                         "  uint subgroupID;\n"
1764                                         "};\n"
1765                                         "layout(set = 0, binding = 22, std430) buffer Buffer3\n"
1766                                         "{\n"
1767                                         "  uint value;\n"
1768                                         "};\n"
1769                                         "layout(set = 0, binding = 23, r32ui) uniform uimage2D tempImage;\n"
1770                                         "void main (void)\n"
1771                                         "{\n"
1772                                         "  if (gl_HelperInvocation) return;\n"
1773                                         "  uint id = 0;\n"
1774                                         "  if (subgroupElect())\n"
1775                                         "  {\n"
1776                                         "    id = atomicAdd(subgroupID, 1);\n"
1777                                         "  }\n"
1778                                         "  id = subgroupBroadcastFirst(id);\n"
1779                                         "  uint localId = id;\n"
1780                                         "  uint tempResult = 0;\n"
1781                                         + bdy.str() +
1782                                         "  result = tempResult;\n"
1783                                         "}\n";
1784                                 programCollection.glslSources.add("fragment")
1785                                         << glu::FragmentSource(fragment)<< vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1786                         }
1787
1788                 subgroups::addNoSubgroupShader(programCollection);
1789                 }
1790         }
1791 }
1792
1793 void supportedCheck (Context& context, CaseDefinition caseDef)
1794 {
1795         DE_UNREF(caseDef);
1796         if (!subgroups::isSubgroupSupported(context))
1797                 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
1798 }
1799
1800 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
1801 {
1802         if (!subgroups::areSubgroupOperationsSupportedForStage(
1803                                 context, caseDef.shaderStage))
1804         {
1805                 if (subgroups::areSubgroupOperationsRequiredForStage(
1806                                         caseDef.shaderStage))
1807                 {
1808                         return tcu::TestStatus::fail(
1809                                            "Shader stage " +
1810                                            subgroups::getShaderStageName(caseDef.shaderStage) +
1811                                            " is required to support subgroup operations!");
1812                 }
1813                 else
1814                 {
1815                         TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
1816                 }
1817         }
1818
1819         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BASIC_BIT))
1820         {
1821                 return tcu::TestStatus::fail(
1822                                    "Subgroup feature " +
1823                                    subgroups::getSubgroupFeatureName(VK_SUBGROUP_FEATURE_BASIC_BIT) +
1824                                    " is a required capability!");
1825         }
1826
1827         if (OPTYPE_ELECT != caseDef.opType && VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1828         {
1829                 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
1830                 {
1831                         TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1832                 }
1833         }
1834
1835         const deUint32                                          inputDatasCount = OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? 3u : 2u;
1836         std::vector<subgroups::SSBOData>        inputDatas              (inputDatasCount);
1837
1838         inputDatas[0].format = VK_FORMAT_R32_UINT;
1839         inputDatas[0].numElements = SHADER_BUFFER_SIZE/4ull;
1840         inputDatas[0].initializeType = subgroups::SSBOData::InitializeNonZero;
1841
1842         inputDatas[1].format = VK_FORMAT_R32_UINT;
1843         inputDatas[1].numElements = 1ull;
1844         inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1845
1846         if(OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType )
1847         {
1848                 inputDatas[2].format = VK_FORMAT_R32_UINT;
1849                 inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1850                 inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1851                 inputDatas[2].isImage = true;
1852         }
1853
1854         if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
1855         {
1856                 if (OPTYPE_ELECT == caseDef.opType)
1857                         return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1858                 else
1859                         return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkVertexPipelineStagesSubgroupBarriersNoSSBO);
1860         }
1861         else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
1862         {
1863                 return subgroups::makeFragmentFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkFragmentSubgroupBarriersNoSSBO);
1864         }
1865         else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
1866         {
1867                 if (OPTYPE_ELECT == caseDef.opType)
1868                         return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1869                 else
1870                         return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkVertexPipelineStagesSubgroupBarriersNoSSBO);
1871         }
1872
1873         if (OPTYPE_ELECT == caseDef.opType)
1874                 return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO, caseDef.shaderStage);
1875
1876         return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount,
1877                 (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)? checkVertexPipelineStagesSubgroupBarriersNoSSBO : checkTessellationEvaluationSubgroupBarriersNoSSBO,
1878                 caseDef.shaderStage);
1879 }
1880
1881 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
1882 {
1883         if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BASIC_BIT))
1884         {
1885                 return tcu::TestStatus::fail(
1886                                         "Subgroup feature " +
1887                                         subgroups::getSubgroupFeatureName(VK_SUBGROUP_FEATURE_BASIC_BIT) +
1888                                         " is a required capability!");
1889         }
1890
1891         if (OPTYPE_ELECT != caseDef.opType && VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1892         {
1893                 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
1894                 {
1895                         TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1896                 }
1897         }
1898
1899         if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1900         {
1901                 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
1902                 {
1903                                 return tcu::TestStatus::fail("Shader stage " +
1904                                                                                 subgroups::getShaderStageName(caseDef.shaderStage) +
1905                                                                                 " is required to support subgroup operations!");
1906                 }
1907
1908                 if (OPTYPE_ELECT == caseDef.opType)
1909                 {
1910                         return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkComputeSubgroupElect);
1911                 }
1912                 else
1913                 {
1914                         const deUint32 inputDatasCount = 3;
1915                         subgroups::SSBOData inputDatas[inputDatasCount];
1916                         inputDatas[0].format = VK_FORMAT_R32_UINT;
1917                         inputDatas[0].numElements = SHADER_BUFFER_SIZE;
1918                         inputDatas[0].initializeType = subgroups::SSBOData::InitializeNone;
1919
1920                         inputDatas[1].format = VK_FORMAT_R32_UINT;
1921                         inputDatas[1].numElements = 1;
1922                         inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1923
1924                         inputDatas[2].format = VK_FORMAT_R32_UINT;
1925                         inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1926                         inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1927                         inputDatas[2].isImage = true;
1928
1929                         return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, inputDatas, inputDatasCount, checkComputeSubgroupBarriers);
1930                 }
1931         }
1932         else
1933         {
1934                 if (!subgroups::isFragmentSSBOSupportedForDevice(context))
1935                 {
1936                         TCU_THROW(NotSupportedError, "Subgroup basic operation require that the fragment stage be able to write to SSBOs!");
1937                 }
1938
1939                 VkPhysicalDeviceSubgroupProperties subgroupProperties;
1940                 subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
1941                 subgroupProperties.pNext = DE_NULL;
1942
1943                 VkPhysicalDeviceProperties2 properties;
1944                 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1945                 properties.pNext = &subgroupProperties;
1946
1947                 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
1948
1949                 VkShaderStageFlagBits stages = (VkShaderStageFlagBits)(caseDef.shaderStage  & subgroupProperties.supportedStages);
1950
1951                 if ( VK_SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
1952                 {
1953                         if ( (stages & VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
1954                                 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
1955                         else
1956                                 stages = VK_SHADER_STAGE_FRAGMENT_BIT;
1957                 }
1958
1959                 if ((VkShaderStageFlagBits)0u == stages)
1960                         TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
1961
1962                 if (OPTYPE_ELECT == caseDef.opType)
1963                 {
1964                         const deUint32 inputCount = 5u;
1965                         subgroups::SSBOData inputData[inputCount];
1966
1967                         inputData[0].format                     = VK_FORMAT_R32_UINT;
1968                         inputData[0].numElements        = 1;
1969                         inputData[0].initializeType     = subgroups::SSBOData::InitializeZero;
1970                         inputData[0].binding            = 4u;
1971                         inputData[0].stages                     = VK_SHADER_STAGE_VERTEX_BIT;
1972
1973                         inputData[1].format                     = VK_FORMAT_R32_UINT;
1974                         inputData[1].numElements        = 1;
1975                         inputData[1].initializeType     = subgroups::SSBOData::InitializeZero;
1976                         inputData[1].binding            = 5u;
1977                         inputData[1].stages                     = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1978
1979                         inputData[2].format                     = VK_FORMAT_R32_UINT;
1980                         inputData[2].numElements        = 1;
1981                         inputData[2].initializeType     = subgroups::SSBOData::InitializeZero;
1982                         inputData[2].binding            = 6u;
1983                         inputData[2].stages                     = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1984
1985                         inputData[3].format                     = VK_FORMAT_R32_UINT;
1986                         inputData[3].numElements        = 1;
1987                         inputData[3].initializeType     = subgroups::SSBOData::InitializeZero;
1988                         inputData[3].binding            = 7u;
1989                         inputData[3].stages                     = VK_SHADER_STAGE_GEOMETRY_BIT;
1990
1991                         inputData[4].format                     = VK_FORMAT_R32_UINT;
1992                         inputData[4].numElements        = 1;
1993                         inputData[4].initializeType     = subgroups::SSBOData::InitializeZero;
1994                         inputData[4].binding            = 8u;
1995                         inputData[4].stages                     = VK_SHADER_STAGE_FRAGMENT_BIT;
1996
1997                         return subgroups::allStages(context, VK_FORMAT_R32_UINT, inputData, inputCount, checkVertexPipelineStagesSubgroupElect, stages);
1998                 }
1999                 else
2000                 {
2001                         const VkShaderStageFlagBits stagesBits[] =
2002                         {
2003                                 VK_SHADER_STAGE_VERTEX_BIT,
2004                                 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
2005                                 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
2006                                 VK_SHADER_STAGE_GEOMETRY_BIT,
2007                                 VK_SHADER_STAGE_FRAGMENT_BIT,
2008                         };
2009
2010                         const deUint32 inputDatasCount = DE_LENGTH_OF_ARRAY(stagesBits) * 4u;
2011                         subgroups::SSBOData inputDatas[inputDatasCount];
2012
2013                         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stagesBits); ++ndx)
2014                         {
2015                                 const deUint32 index = ndx*4;
2016                                 inputDatas[index].format                                = VK_FORMAT_R32_UINT;
2017                                 inputDatas[index].numElements                   = SHADER_BUFFER_SIZE;
2018                                 inputDatas[index].initializeType                = subgroups::SSBOData::InitializeNonZero;
2019                                 inputDatas[index].binding                               = index + 4u;
2020                                 inputDatas[index].stages                                = stagesBits[ndx];
2021
2022                                 inputDatas[index + 1].format                    = VK_FORMAT_R32_UINT;
2023                                 inputDatas[index + 1].numElements               = 1;
2024                                 inputDatas[index + 1].initializeType    = subgroups::SSBOData::InitializeZero;
2025                                 inputDatas[index + 1].binding                   = index + 5u;
2026                                 inputDatas[index + 1].stages                    = stagesBits[ndx];
2027
2028                                 inputDatas[index + 2].format                    = VK_FORMAT_R32_UINT;
2029                                 inputDatas[index + 2].numElements               = 1;
2030                                 inputDatas[index + 2].initializeType    = subgroups::SSBOData::InitializeNonZero;
2031                                 inputDatas[index + 2].binding                   = index + 6u;
2032                                 inputDatas[index + 2].stages                    = stagesBits[ndx];
2033
2034                                 inputDatas[index + 3].format                    = VK_FORMAT_R32_UINT;
2035                                 inputDatas[index + 3].numElements               = SHADER_BUFFER_SIZE;
2036                                 inputDatas[index + 3].initializeType    = subgroups::SSBOData::InitializeNone;
2037                                 inputDatas[index + 3].isImage                   = true;
2038                                 inputDatas[index + 3].binding                   = index + 7u;
2039                                 inputDatas[index + 3].stages                    = stagesBits[ndx];
2040                         }
2041
2042                         return subgroups::allStages(context, VK_FORMAT_R32_UINT, inputDatas, inputDatasCount, checkVertexPipelineStagesSubgroupBarriers, stages);
2043                 }
2044         }
2045 }
2046 }
2047
2048 namespace vkt
2049 {
2050 namespace subgroups
2051 {
2052 tcu::TestCaseGroup* createSubgroupsBasicTests(tcu::TestContext& testCtx)
2053 {
2054         de::MovePtr<tcu::TestCaseGroup> graphicGroup(new tcu::TestCaseGroup(
2055                 testCtx, "graphics", "Subgroup basic category tests: graphics"));
2056         de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(
2057                 testCtx, "compute", "Subgroup basic category tests: compute"));
2058         de::MovePtr<tcu::TestCaseGroup> framebufferGroup(new tcu::TestCaseGroup(
2059                 testCtx, "framebuffer", "Subgroup basic category tests: framebuffer"));
2060
2061
2062         const VkShaderStageFlags stages[] =
2063         {
2064                 VK_SHADER_STAGE_FRAGMENT_BIT,
2065                 VK_SHADER_STAGE_VERTEX_BIT,
2066                 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
2067                 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
2068                 VK_SHADER_STAGE_GEOMETRY_BIT,
2069         };
2070
2071         for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
2072         {
2073                 const std::string op = de::toLower(getOpTypeName(opTypeIndex));
2074
2075                 {
2076                         const CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_COMPUTE_BIT};
2077                         addFunctionCaseWithPrograms(computeGroup.get(), op, "",
2078                                                                                 supportedCheck, initPrograms, test, caseDef);
2079                 }
2080
2081                 if (OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED == opTypeIndex)
2082                 {
2083                         // Shared isn't available in non compute shaders.
2084                         continue;
2085                 }
2086
2087                 {
2088                         const CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_ALL_GRAPHICS};
2089                         addFunctionCaseWithPrograms(graphicGroup.get(),
2090                                                                                 op, "",
2091                                                                                 supportedCheck, initPrograms, test, caseDef);
2092                 }
2093
2094                 if (OPTYPE_ELECT == opTypeIndex)
2095                 {
2096                         for (int stageIndex = 1; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
2097                         {
2098                                 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex]};
2099                                 addFunctionCaseWithPrograms(framebufferGroup.get(),
2100                                                         op + "_" + getShaderStageName(caseDef.shaderStage), "",
2101                                                         supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
2102                         }
2103                 }
2104                 else
2105                 {
2106                         for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
2107                         {
2108                                 const CaseDefinition caseDefFrag = {opTypeIndex, stages[stageIndex]};
2109                                 addFunctionCaseWithPrograms(framebufferGroup.get(),
2110                                                         op + "_" + getShaderStageName(caseDefFrag.shaderStage), "",
2111                                                         supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDefFrag);
2112                         }
2113                 }
2114
2115         }
2116
2117         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
2118                 testCtx, "basic", "Subgroup basic category tests"));
2119
2120         group->addChild(graphicGroup.release());
2121         group->addChild(computeGroup.release());
2122         group->addChild(framebufferGroup.release());
2123
2124         return group.release();
2125 }
2126
2127 } // subgroups
2128 } // vkt