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