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 "vktSubgroupsBuiltinMaskVarTests.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_EQ_MASK = 0,
44 TEST_TYPE_SUBGROUP_GE_MASK = 1,
45 TEST_TYPE_SUBGROUP_GT_MASK = 2,
46 TEST_TYPE_SUBGROUP_LE_MASK = 3,
47 TEST_TYPE_SUBGROUP_LT_MASK = 4,
48 TEST_TYPE_LAST
49 };
50
51 const char *TestTypeSpirvBuiltins[] = {
52 "SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask", "SubgroupLeMask", "SubgroupLtMask",
53 };
54 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(TestTypeSpirvBuiltins) == TEST_TYPE_LAST);
55
56 const char *TestTypeMathOps[] = {
57 "==", ">=", ">", "<=", "<",
58 };
59 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(TestTypeMathOps) == TEST_TYPE_LAST);
60
61 const char *TestTypeSpirvOps[] = {
62 "OpIEqual", "OpUGreaterThanEqual", "OpUGreaterThan", "OpULessThanEqual", "OpULessThan",
63 };
64 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(TestTypeSpirvOps) == TEST_TYPE_LAST);
65
66 namespace
67 {
68 struct CaseDefinition
69 {
70 TestType testType;
71 VkShaderStageFlags shaderStage;
72 de::SharedPtr<bool> geometryPointSizeSupported;
73 bool requiredSubgroupSize;
74 };
75 } // namespace
76
getTestSpirvBuiltinName(TestType testType)77 static inline string getTestSpirvBuiltinName(TestType testType)
78 {
79 return TestTypeSpirvBuiltins[static_cast<uint32_t>(testType)];
80 }
81
getTestName(TestType testType)82 static inline string getTestName(TestType testType)
83 {
84 return de::toLower(getTestSpirvBuiltinName(testType));
85 }
86
getTestVarName(TestType testType)87 static inline string getTestVarName(TestType testType)
88 {
89 return string("gl_") + getTestSpirvBuiltinName(testType);
90 }
91
getTestMathOp(TestType testType)92 static inline string getTestMathOp(TestType testType)
93 {
94 return TestTypeMathOps[static_cast<uint32_t>(testType)];
95 }
96
getTestSpirvOp(TestType testType)97 static inline string getTestSpirvOp(TestType testType)
98 {
99 return TestTypeSpirvOps[static_cast<uint32_t>(testType)];
100 }
101
checkVertexPipelineStages(const void * internalData,vector<const void * > datas,uint32_t width,uint32_t)102 static bool checkVertexPipelineStages(const void *internalData, vector<const void *> datas, uint32_t width, uint32_t)
103 {
104 DE_UNREF(internalData);
105
106 return check(datas, width, 1);
107 }
108
checkComputeOrMeshStage(const void * internalData,vector<const void * > datas,const uint32_t numWorkgroups[3],const uint32_t localSize[3],uint32_t)109 static bool checkComputeOrMeshStage(const void *internalData, vector<const void *> datas,
110 const uint32_t numWorkgroups[3], const uint32_t localSize[3], uint32_t)
111 {
112 DE_UNREF(internalData);
113
114 return checkComputeOrMesh(datas, numWorkgroups, localSize, 1);
115 }
116
subgroupComparison(const CaseDefinition & caseDef)117 static inline string subgroupComparison(const CaseDefinition &caseDef)
118 {
119 const string spirvOp = getTestSpirvOp(caseDef.testType);
120 const string result = (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) ?
121 "%56 = " + spirvOp + " %11 %53 %55\n" :
122 "%38 = " + spirvOp + " %16 %35 %37\n";
123
124 return result;
125 }
126
varSubgroupMask(const CaseDefinition & caseDef)127 static inline string varSubgroupMask(const CaseDefinition &caseDef)
128 {
129 const string spirvBuiltin = getTestSpirvBuiltinName(caseDef.testType);
130 const string result = (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) ?
131 "OpDecorate %40 BuiltIn " + spirvBuiltin + "\n" :
132 "OpDecorate %22 BuiltIn " + spirvBuiltin + "\n";
133
134 return result;
135 }
136
subgroupMask(const CaseDefinition & caseDef)137 string subgroupMask(const CaseDefinition &caseDef)
138 {
139 const string varName = getTestVarName(caseDef.testType);
140 const string comp = getTestMathOp(caseDef.testType);
141 ostringstream bdy;
142
143 bdy << " uint tempResult = 0x1;\n"
144 << " uvec4 mask = subgroupBallot(true);\n"
145 << " const uvec4 var = " << varName << ";\n"
146 << " for (uint i = 0; i < gl_SubgroupSize; i++)\n"
147 << " {\n"
148 << " if ((i " << comp << " gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
149 << " {\n"
150 << " tempResult = 0;\n"
151 << " }\n"
152 << " }\n"
153 << " uint c = bitCount(var.x) + bitCount(var.y) + bitCount(var.z) + bitCount(var.w);\n"
154 << " if (subgroupBallotBitCount(var) != c)\n"
155 << " {\n"
156 << " tempResult = 0;\n"
157 << " }\n"
158 << " tempRes = tempResult;\n";
159
160 return bdy.str();
161 }
162
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)163 void initFrameBufferPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
164 {
165 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
166 const string comparison = subgroupComparison(caseDef);
167 const string mask = varSubgroupMask(caseDef);
168
169 subgroups::setFragmentShaderFrameBuffer(programCollection);
170
171 if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
172 subgroups::setVertexShaderFrameBuffer(programCollection);
173
174 if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
175 {
176 /*
177 const string bdy = subgroupMask(caseDef);
178 const string vertex =
179 "#version 450\n"
180 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
181 "layout(location = 0) out float out_color;\n"
182 "layout(location = 0) in highp vec4 in_position;\n"
183 "\n"
184 "void main (void)\n"
185 "{\n"
186 + bdy +
187 " out_color = float(tempResult);\n"
188 " gl_Position = in_position;\n"
189 " gl_PointSize = 1.0f;\n"
190 "}\n";
191 programCollection.glslSources.add("vert")
192 << glu::VertexSource(vertex) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
193 */
194
195 const string vertex = "; SPIR-V\n"
196 "; Version: 1.3\n"
197 "; Generator: Khronos Glslang Reference Front End; 2\n"
198 "; Bound: 123\n"
199 "; Schema: 0\n"
200 "OpCapability Shader\n"
201 "OpCapability GroupNonUniform\n"
202 "OpCapability GroupNonUniformBallot\n"
203 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
204 "OpMemoryModel Logical GLSL450\n"
205 "OpEntryPoint Vertex %4 \"main\" %22 %32 %36 %107 %114 %117\n" +
206 mask +
207 "OpDecorate %32 RelaxedPrecision\n"
208 "OpDecorate %32 BuiltIn SubgroupSize\n"
209 "OpDecorate %33 RelaxedPrecision\n"
210 "OpDecorate %36 RelaxedPrecision\n"
211 "OpDecorate %36 BuiltIn SubgroupLocalInvocationId\n"
212 "OpDecorate %37 RelaxedPrecision\n"
213 "OpDecorate %107 Location 0\n"
214 "OpMemberDecorate %112 0 BuiltIn Position\n"
215 "OpMemberDecorate %112 1 BuiltIn PointSize\n"
216 "OpMemberDecorate %112 2 BuiltIn ClipDistance\n"
217 "OpMemberDecorate %112 3 BuiltIn CullDistance\n"
218 "OpDecorate %112 Block\n"
219 "OpDecorate %117 Location 0\n"
220 "%2 = OpTypeVoid\n"
221 "%3 = OpTypeFunction %2\n"
222 "%6 = OpTypeInt 32 0\n"
223 "%7 = OpTypePointer Function %6\n"
224 "%9 = OpConstant %6 1\n"
225 "%12 = OpConstant %6 0\n"
226 "%13 = OpTypeVector %6 4\n"
227 "%14 = OpTypePointer Function %13\n"
228 "%16 = OpTypeBool\n"
229 "%17 = OpConstantTrue %16\n"
230 "%18 = OpConstant %6 3\n"
231 "%21 = OpTypePointer Input %13\n"
232 "%22 = OpVariable %21 Input\n"
233 "%31 = OpTypePointer Input %6\n"
234 "%32 = OpVariable %31 Input\n"
235 "%36 = OpVariable %31 Input\n"
236 "%46 = OpTypeInt 32 1\n"
237 "%47 = OpConstant %46 1\n"
238 "%56 = OpConstant %6 32\n"
239 "%76 = OpConstant %6 2\n"
240 "%105 = OpTypeFloat 32\n"
241 "%106 = OpTypePointer Output %105\n"
242 "%107 = OpVariable %106 Output\n"
243 "%110 = OpTypeVector %105 4\n"
244 "%111 = OpTypeArray %105 %9\n"
245 "%112 = OpTypeStruct %110 %105 %111 %111\n"
246 "%113 = OpTypePointer Output %112\n"
247 "%114 = OpVariable %113 Output\n"
248 "%115 = OpConstant %46 0\n"
249 "%116 = OpTypePointer Input %110\n"
250 "%117 = OpVariable %116 Input\n"
251 "%119 = OpTypePointer Output %110\n"
252 "%121 = OpConstant %105 1\n"
253 "%4 = OpFunction %2 None %3\n"
254 "%5 = OpLabel\n"
255 "%8 = OpVariable %7 Function\n"
256 "%10 = OpVariable %7 Function\n"
257 "%11 = OpVariable %7 Function\n"
258 "%15 = OpVariable %14 Function\n"
259 "%20 = OpVariable %14 Function\n"
260 "%24 = OpVariable %7 Function\n"
261 "%49 = OpVariable %7 Function\n"
262 "OpStore %8 %9\n"
263 "OpStore %10 %9\n"
264 "OpStore %11 %12\n"
265 "%19 = OpGroupNonUniformBallot %13 %18 %17\n"
266 "OpStore %15 %19\n"
267 "%23 = OpLoad %13 %22\n"
268 "OpStore %20 %23\n"
269 "OpStore %24 %12\n"
270 "OpBranch %25\n"
271 "%25 = OpLabel\n"
272 "OpLoopMerge %27 %28 None\n"
273 "OpBranch %29\n"
274 "%29 = OpLabel\n"
275 "%30 = OpLoad %6 %24\n"
276 "%33 = OpLoad %6 %32\n"
277 "%34 = OpULessThan %16 %30 %33\n"
278 "OpBranchConditional %34 %26 %27\n"
279 "%26 = OpLabel\n"
280 "%35 = OpLoad %6 %24\n"
281 "%37 = OpLoad %6 %36\n" +
282 comparison +
283 "%39 = OpLoad %13 %20\n"
284 "%40 = OpLoad %6 %24\n"
285 "%41 = OpGroupNonUniformBallotBitExtract %16 %18 %39 %40\n"
286 "%42 = OpLogicalNotEqual %16 %38 %41\n"
287 "OpSelectionMerge %44 None\n"
288 "OpBranchConditional %42 %43 %44\n"
289 "%43 = OpLabel\n"
290 "OpStore %8 %12\n"
291 "OpBranch %44\n"
292 "%44 = OpLabel\n"
293 "OpBranch %28\n"
294 "%28 = OpLabel\n"
295 "%45 = OpLoad %6 %24\n"
296 "%48 = OpIAdd %6 %45 %47\n"
297 "OpStore %24 %48\n"
298 "OpBranch %25\n"
299 "%27 = OpLabel\n"
300 "OpStore %49 %12\n"
301 "OpBranch %50\n"
302 "%50 = OpLabel\n"
303 "OpLoopMerge %52 %53 None\n"
304 "OpBranch %54\n"
305 "%54 = OpLabel\n"
306 "%55 = OpLoad %6 %49\n"
307 "%57 = OpULessThan %16 %55 %56\n"
308 "OpBranchConditional %57 %51 %52\n"
309 "%51 = OpLabel\n"
310 "%58 = OpAccessChain %7 %20 %12\n"
311 "%59 = OpLoad %6 %58\n"
312 "%60 = OpLoad %6 %10\n"
313 "%61 = OpBitwiseAnd %6 %59 %60\n"
314 "%62 = OpUGreaterThan %16 %61 %12\n"
315 "OpSelectionMerge %64 None\n"
316 "OpBranchConditional %62 %63 %64\n"
317 "%63 = OpLabel\n"
318 "%65 = OpLoad %6 %11\n"
319 "%66 = OpIAdd %6 %65 %47\n"
320 "OpStore %11 %66\n"
321 "OpBranch %64\n"
322 "%64 = OpLabel\n"
323 "%67 = OpAccessChain %7 %20 %9\n"
324 "%68 = OpLoad %6 %67\n"
325 "%69 = OpLoad %6 %10\n"
326 "%70 = OpBitwiseAnd %6 %68 %69\n"
327 "%71 = OpUGreaterThan %16 %70 %12\n"
328 "OpSelectionMerge %73 None\n"
329 "OpBranchConditional %71 %72 %73\n"
330 "%72 = OpLabel\n"
331 "%74 = OpLoad %6 %11\n"
332 "%75 = OpIAdd %6 %74 %47\n"
333 "OpStore %11 %75\n"
334 "OpBranch %73\n"
335 "%73 = OpLabel\n"
336 "%77 = OpAccessChain %7 %20 %76\n"
337 "%78 = OpLoad %6 %77\n"
338 "%79 = OpLoad %6 %10\n"
339 "%80 = OpBitwiseAnd %6 %78 %79\n"
340 "%81 = OpUGreaterThan %16 %80 %12\n"
341 "OpSelectionMerge %83 None\n"
342 "OpBranchConditional %81 %82 %83\n"
343 "%82 = OpLabel\n"
344 "%84 = OpLoad %6 %11\n"
345 "%85 = OpIAdd %6 %84 %47\n"
346 "OpStore %11 %85\n"
347 "OpBranch %83\n"
348 "%83 = OpLabel\n"
349 "%86 = OpAccessChain %7 %20 %18\n"
350 "%87 = OpLoad %6 %86\n"
351 "%88 = OpLoad %6 %10\n"
352 "%89 = OpBitwiseAnd %6 %87 %88\n"
353 "%90 = OpUGreaterThan %16 %89 %12\n"
354 "OpSelectionMerge %92 None\n"
355 "OpBranchConditional %90 %91 %92\n"
356 "%91 = OpLabel\n"
357 "%93 = OpLoad %6 %11\n"
358 "%94 = OpIAdd %6 %93 %47\n"
359 "OpStore %11 %94\n"
360 "OpBranch %92\n"
361 "%92 = OpLabel\n"
362 "%95 = OpLoad %6 %10\n"
363 "%96 = OpShiftLeftLogical %6 %95 %47\n"
364 "OpStore %10 %96\n"
365 "OpBranch %53\n"
366 "%53 = OpLabel\n"
367 "%97 = OpLoad %6 %49\n"
368 "%98 = OpIAdd %6 %97 %47\n"
369 "OpStore %49 %98\n"
370 "OpBranch %50\n"
371 "%52 = OpLabel\n"
372 "%99 = OpLoad %13 %20\n"
373 "%100 = OpGroupNonUniformBallotBitCount %6 %18 Reduce %99\n"
374 "%101 = OpLoad %6 %11\n"
375 "%102 = OpINotEqual %16 %100 %101\n"
376 "OpSelectionMerge %104 None\n"
377 "OpBranchConditional %102 %103 %104\n"
378 "%103 = OpLabel\n"
379 "OpStore %8 %12\n"
380 "OpBranch %104\n"
381 "%104 = OpLabel\n"
382 "%108 = OpLoad %6 %8\n"
383 "%109 = OpConvertUToF %105 %108\n"
384 "OpStore %107 %109\n"
385 "%118 = OpLoad %110 %117\n"
386 "%120 = OpAccessChain %119 %114 %115\n"
387 "OpStore %120 %118\n"
388 "%122 = OpAccessChain %106 %114 %47\n"
389 "OpStore %122 %121\n"
390 "OpReturn\n"
391 "OpFunctionEnd\n";
392 programCollection.spirvAsmSources.add("vert") << vertex << buildOptionsSpr;
393 }
394 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
395 {
396 /*
397 const string bdy = subgroupMask(caseDef);
398 const string evaluationSource =
399 "#version 450\n"
400 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
401 "#extension GL_EXT_tessellation_shader : require\n"
402 "layout(isolines, equal_spacing, ccw ) in;\n"
403 "layout(location = 0) out float out_color;\n"
404 "\n"
405 "void main (void)\n"
406 "{\n"
407 + bdy +
408 " out_color = float(tempResult);\n"
409 " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
410 "}\n";
411 programCollection.glslSources.add("tese")
412 << glu::TessellationEvaluationSource(evaluationSource) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
413 */
414 const string evaluationSource =
415 "; SPIR-V\n"
416 "; Version: 1.3\n"
417 "; Generator: Khronos Glslang Reference Front End; 2\n"
418 "; Bound: 136\n"
419 "; Schema: 0\n"
420 "OpCapability Tessellation\n"
421 "OpCapability GroupNonUniform\n"
422 "OpCapability GroupNonUniformBallot\n"
423 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
424 "OpMemoryModel Logical GLSL450\n"
425 "OpEntryPoint TessellationEvaluation %4 \"main\" %22 %32 %36 %107 %114 %120 %128\n"
426 "OpExecutionMode %4 Isolines\n"
427 "OpExecutionMode %4 SpacingEqual\n"
428 "OpExecutionMode %4 VertexOrderCcw\n" +
429 mask +
430 "OpDecorate %32 RelaxedPrecision\n"
431 "OpDecorate %32 BuiltIn SubgroupSize\n"
432 "OpDecorate %33 RelaxedPrecision\n"
433 "OpDecorate %36 RelaxedPrecision\n"
434 "OpDecorate %36 BuiltIn SubgroupLocalInvocationId\n"
435 "OpDecorate %37 RelaxedPrecision\n"
436 "OpDecorate %107 Location 0\n"
437 "OpMemberDecorate %112 0 BuiltIn Position\n"
438 "OpMemberDecorate %112 1 BuiltIn PointSize\n"
439 "OpMemberDecorate %112 2 BuiltIn ClipDistance\n"
440 "OpMemberDecorate %112 3 BuiltIn CullDistance\n"
441 "OpDecorate %112 Block\n"
442 "OpMemberDecorate %116 0 BuiltIn Position\n"
443 "OpMemberDecorate %116 1 BuiltIn PointSize\n"
444 "OpMemberDecorate %116 2 BuiltIn ClipDistance\n"
445 "OpMemberDecorate %116 3 BuiltIn CullDistance\n"
446 "OpDecorate %116 Block\n"
447 "OpDecorate %128 BuiltIn TessCoord\n"
448 "%2 = OpTypeVoid\n"
449 "%3 = OpTypeFunction %2\n"
450 "%6 = OpTypeInt 32 0\n"
451 "%7 = OpTypePointer Function %6\n"
452 "%9 = OpConstant %6 1\n"
453 "%12 = OpConstant %6 0\n"
454 "%13 = OpTypeVector %6 4\n"
455 "%14 = OpTypePointer Function %13\n"
456 "%16 = OpTypeBool\n"
457 "%17 = OpConstantTrue %16\n"
458 "%18 = OpConstant %6 3\n"
459 "%21 = OpTypePointer Input %13\n"
460 "%22 = OpVariable %21 Input\n"
461 "%31 = OpTypePointer Input %6\n"
462 "%32 = OpVariable %31 Input\n"
463 "%36 = OpVariable %31 Input\n"
464 "%46 = OpTypeInt 32 1\n"
465 "%47 = OpConstant %46 1\n"
466 "%56 = OpConstant %6 32\n"
467 "%76 = OpConstant %6 2\n"
468 "%105 = OpTypeFloat 32\n"
469 "%106 = OpTypePointer Output %105\n"
470 "%107 = OpVariable %106 Output\n"
471 "%110 = OpTypeVector %105 4\n"
472 "%111 = OpTypeArray %105 %9\n"
473 "%112 = OpTypeStruct %110 %105 %111 %111\n"
474 "%113 = OpTypePointer Output %112\n"
475 "%114 = OpVariable %113 Output\n"
476 "%115 = OpConstant %46 0\n"
477 "%116 = OpTypeStruct %110 %105 %111 %111\n"
478 "%117 = OpConstant %6 32\n"
479 "%118 = OpTypeArray %116 %117\n"
480 "%119 = OpTypePointer Input %118\n"
481 "%120 = OpVariable %119 Input\n"
482 "%121 = OpTypePointer Input %110\n"
483 "%126 = OpTypeVector %105 3\n"
484 "%127 = OpTypePointer Input %126\n"
485 "%128 = OpVariable %127 Input\n"
486 "%129 = OpTypePointer Input %105\n"
487 "%134 = OpTypePointer Output %110\n"
488 "%4 = OpFunction %2 None %3\n"
489 "%5 = OpLabel\n"
490 "%8 = OpVariable %7 Function\n"
491 "%10 = OpVariable %7 Function\n"
492 "%11 = OpVariable %7 Function\n"
493 "%15 = OpVariable %14 Function\n"
494 "%20 = OpVariable %14 Function\n"
495 "%24 = OpVariable %7 Function\n"
496 "%49 = OpVariable %7 Function\n"
497 "OpStore %8 %9\n"
498 "OpStore %10 %9\n"
499 "OpStore %11 %12\n"
500 "%19 = OpGroupNonUniformBallot %13 %18 %17\n"
501 "OpStore %15 %19\n"
502 "%23 = OpLoad %13 %22\n"
503 "OpStore %20 %23\n"
504 "OpStore %24 %12\n"
505 "OpBranch %25\n"
506 "%25 = OpLabel\n"
507 "OpLoopMerge %27 %28 None\n"
508 "OpBranch %29\n"
509 "%29 = OpLabel\n"
510 "%30 = OpLoad %6 %24\n"
511 "%33 = OpLoad %6 %32\n"
512 "%34 = OpULessThan %16 %30 %33\n"
513 "OpBranchConditional %34 %26 %27\n"
514 "%26 = OpLabel\n"
515 "%35 = OpLoad %6 %24\n"
516 "%37 = OpLoad %6 %36\n" +
517 comparison +
518 "%39 = OpLoad %13 %20\n"
519 "%40 = OpLoad %6 %24\n"
520 "%41 = OpGroupNonUniformBallotBitExtract %16 %18 %39 %40\n"
521 "%42 = OpLogicalNotEqual %16 %38 %41\n"
522 "OpSelectionMerge %44 None\n"
523 "OpBranchConditional %42 %43 %44\n"
524 "%43 = OpLabel\n"
525 "OpStore %8 %12\n"
526 "OpBranch %44\n"
527 "%44 = OpLabel\n"
528 "OpBranch %28\n"
529 "%28 = OpLabel\n"
530 "%45 = OpLoad %6 %24\n"
531 "%48 = OpIAdd %6 %45 %47\n"
532 "OpStore %24 %48\n"
533 "OpBranch %25\n"
534 "%27 = OpLabel\n"
535 "OpStore %49 %12\n"
536 "OpBranch %50\n"
537 "%50 = OpLabel\n"
538 "OpLoopMerge %52 %53 None\n"
539 "OpBranch %54\n"
540 "%54 = OpLabel\n"
541 "%55 = OpLoad %6 %49\n"
542 "%57 = OpULessThan %16 %55 %56\n"
543 "OpBranchConditional %57 %51 %52\n"
544 "%51 = OpLabel\n"
545 "%58 = OpAccessChain %7 %20 %12\n"
546 "%59 = OpLoad %6 %58\n"
547 "%60 = OpLoad %6 %10\n"
548 "%61 = OpBitwiseAnd %6 %59 %60\n"
549 "%62 = OpUGreaterThan %16 %61 %12\n"
550 "OpSelectionMerge %64 None\n"
551 "OpBranchConditional %62 %63 %64\n"
552 "%63 = OpLabel\n"
553 "%65 = OpLoad %6 %11\n"
554 "%66 = OpIAdd %6 %65 %47\n"
555 "OpStore %11 %66\n"
556 "OpBranch %64\n"
557 "%64 = OpLabel\n"
558 "%67 = OpAccessChain %7 %20 %9\n"
559 "%68 = OpLoad %6 %67\n"
560 "%69 = OpLoad %6 %10\n"
561 "%70 = OpBitwiseAnd %6 %68 %69\n"
562 "%71 = OpUGreaterThan %16 %70 %12\n"
563 "OpSelectionMerge %73 None\n"
564 "OpBranchConditional %71 %72 %73\n"
565 "%72 = OpLabel\n"
566 "%74 = OpLoad %6 %11\n"
567 "%75 = OpIAdd %6 %74 %47\n"
568 "OpStore %11 %75\n"
569 "OpBranch %73\n"
570 "%73 = OpLabel\n"
571 "%77 = OpAccessChain %7 %20 %76\n"
572 "%78 = OpLoad %6 %77\n"
573 "%79 = OpLoad %6 %10\n"
574 "%80 = OpBitwiseAnd %6 %78 %79\n"
575 "%81 = OpUGreaterThan %16 %80 %12\n"
576 "OpSelectionMerge %83 None\n"
577 "OpBranchConditional %81 %82 %83\n"
578 "%82 = OpLabel\n"
579 "%84 = OpLoad %6 %11\n"
580 "%85 = OpIAdd %6 %84 %47\n"
581 "OpStore %11 %85\n"
582 "OpBranch %83\n"
583 "%83 = OpLabel\n"
584 "%86 = OpAccessChain %7 %20 %18\n"
585 "%87 = OpLoad %6 %86\n"
586 "%88 = OpLoad %6 %10\n"
587 "%89 = OpBitwiseAnd %6 %87 %88\n"
588 "%90 = OpUGreaterThan %16 %89 %12\n"
589 "OpSelectionMerge %92 None\n"
590 "OpBranchConditional %90 %91 %92\n"
591 "%91 = OpLabel\n"
592 "%93 = OpLoad %6 %11\n"
593 "%94 = OpIAdd %6 %93 %47\n"
594 "OpStore %11 %94\n"
595 "OpBranch %92\n"
596 "%92 = OpLabel\n"
597 "%95 = OpLoad %6 %10\n"
598 "%96 = OpShiftLeftLogical %6 %95 %47\n"
599 "OpStore %10 %96\n"
600 "OpBranch %53\n"
601 "%53 = OpLabel\n"
602 "%97 = OpLoad %6 %49\n"
603 "%98 = OpIAdd %6 %97 %47\n"
604 "OpStore %49 %98\n"
605 "OpBranch %50\n"
606 "%52 = OpLabel\n"
607 "%99 = OpLoad %13 %20\n"
608 "%100 = OpGroupNonUniformBallotBitCount %6 %18 Reduce %99\n"
609 "%101 = OpLoad %6 %11\n"
610 "%102 = OpINotEqual %16 %100 %101\n"
611 "OpSelectionMerge %104 None\n"
612 "OpBranchConditional %102 %103 %104\n"
613 "%103 = OpLabel\n"
614 "OpStore %8 %12\n"
615 "OpBranch %104\n"
616 "%104 = OpLabel\n"
617 "%108 = OpLoad %6 %8\n"
618 "%109 = OpConvertUToF %105 %108\n"
619 "OpStore %107 %109\n"
620 "%122 = OpAccessChain %121 %120 %115 %115\n"
621 "%123 = OpLoad %110 %122\n"
622 "%124 = OpAccessChain %121 %120 %47 %115\n"
623 "%125 = OpLoad %110 %124\n"
624 "%130 = OpAccessChain %129 %128 %12\n"
625 "%131 = OpLoad %105 %130\n"
626 "%132 = OpCompositeConstruct %110 %131 %131 %131 %131\n"
627 "%133 = OpExtInst %110 %1 FMix %123 %125 %132\n"
628 "%135 = OpAccessChain %134 %114 %115\n"
629 "OpStore %135 %133\n"
630 "OpReturn\n"
631 "OpFunctionEnd\n";
632 programCollection.spirvAsmSources.add("tese") << evaluationSource << buildOptionsSpr;
633 subgroups::setTesCtrlShaderFrameBuffer(programCollection);
634 }
635 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
636 {
637 /*
638 const string bdy = subgroupMask(caseDef);
639 const string controlSource =
640 "#version 450\n"
641 "#extension GL_EXT_tessellation_shader : require\n"
642 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
643 "layout(vertices = 2) out;\n"
644 "layout(location = 0) out float out_color[];\n"
645 "void main (void)\n"
646 "{\n"
647 " if (gl_InvocationID == 0)\n"
648 " {\n"
649 " gl_TessLevelOuter[0] = 1.0f;\n"
650 " gl_TessLevelOuter[1] = 1.0f;\n"
651 " }\n"
652 + bdy +
653 " out_color[gl_InvocationID] = float(tempResult);\n"
654 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
655 "}\n";
656 programCollection.glslSources.add("tesc")
657 << glu::TessellationControlSource(controlSource) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
658 */
659 const string controlSource = "; SPIR-V\n"
660 "; Version: 1.3\n"
661 "; Generator: Khronos Glslang Reference Front End; 2\n"
662 "; Bound: 146\n"
663 "; Schema: 0\n"
664 "OpCapability Tessellation\n"
665 "OpCapability GroupNonUniform\n"
666 "OpCapability GroupNonUniformBallot\n"
667 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
668 "OpMemoryModel Logical GLSL450\n"
669 "OpEntryPoint TessellationControl %4 \"main\" %8 %20 %40 %50 %54 %123 %133 %139\n"
670 "OpExecutionMode %4 OutputVertices 2\n"
671 "OpDecorate %8 BuiltIn InvocationId\n"
672 "OpDecorate %20 Patch\n"
673 "OpDecorate %20 BuiltIn TessLevelOuter\n" +
674 mask +
675 "OpDecorate %50 RelaxedPrecision\n"
676 "OpDecorate %50 BuiltIn SubgroupSize\n"
677 "OpDecorate %51 RelaxedPrecision\n"
678 "OpDecorate %54 RelaxedPrecision\n"
679 "OpDecorate %54 BuiltIn SubgroupLocalInvocationId\n"
680 "OpDecorate %55 RelaxedPrecision\n"
681 "OpDecorate %123 Location 0\n"
682 "OpMemberDecorate %130 0 BuiltIn Position\n"
683 "OpMemberDecorate %130 1 BuiltIn PointSize\n"
684 "OpMemberDecorate %130 2 BuiltIn ClipDistance\n"
685 "OpMemberDecorate %130 3 BuiltIn CullDistance\n"
686 "OpDecorate %130 Block\n"
687 "OpMemberDecorate %135 0 BuiltIn Position\n"
688 "OpMemberDecorate %135 1 BuiltIn PointSize\n"
689 "OpMemberDecorate %135 2 BuiltIn ClipDistance\n"
690 "OpMemberDecorate %135 3 BuiltIn CullDistance\n"
691 "OpDecorate %135 Block\n"
692 "%2 = OpTypeVoid\n"
693 "%3 = OpTypeFunction %2\n"
694 "%6 = OpTypeInt 32 1\n"
695 "%7 = OpTypePointer Input %6\n"
696 "%8 = OpVariable %7 Input\n"
697 "%10 = OpConstant %6 0\n"
698 "%11 = OpTypeBool\n"
699 "%15 = OpTypeFloat 32\n"
700 "%16 = OpTypeInt 32 0\n"
701 "%17 = OpConstant %16 4\n"
702 "%18 = OpTypeArray %15 %17\n"
703 "%19 = OpTypePointer Output %18\n"
704 "%20 = OpVariable %19 Output\n"
705 "%21 = OpConstant %15 1\n"
706 "%22 = OpTypePointer Output %15\n"
707 "%24 = OpConstant %6 1\n"
708 "%26 = OpTypePointer Function %16\n"
709 "%28 = OpConstant %16 1\n"
710 "%31 = OpConstant %16 0\n"
711 "%32 = OpTypeVector %16 4\n"
712 "%33 = OpTypePointer Function %32\n"
713 "%35 = OpConstantTrue %11\n"
714 "%36 = OpConstant %16 3\n"
715 "%39 = OpTypePointer Input %32\n"
716 "%40 = OpVariable %39 Input\n"
717 "%49 = OpTypePointer Input %16\n"
718 "%50 = OpVariable %49 Input\n"
719 "%54 = OpVariable %49 Input\n"
720 "%72 = OpConstant %16 32\n"
721 "%92 = OpConstant %16 2\n"
722 "%121 = OpTypeArray %15 %92\n"
723 "%122 = OpTypePointer Output %121\n"
724 "%123 = OpVariable %122 Output\n"
725 "%128 = OpTypeVector %15 4\n"
726 "%129 = OpTypeArray %15 %28\n"
727 "%130 = OpTypeStruct %128 %15 %129 %129\n"
728 "%131 = OpTypeArray %130 %92\n"
729 "%132 = OpTypePointer Output %131\n"
730 "%133 = OpVariable %132 Output\n"
731 "%135 = OpTypeStruct %128 %15 %129 %129\n"
732 "%136 = OpConstant %16 32\n"
733 "%137 = OpTypeArray %135 %136\n"
734 "%138 = OpTypePointer Input %137\n"
735 "%139 = OpVariable %138 Input\n"
736 "%141 = OpTypePointer Input %128\n"
737 "%144 = OpTypePointer Output %128\n"
738 "%4 = OpFunction %2 None %3\n"
739 "%5 = OpLabel\n"
740 "%27 = OpVariable %26 Function\n"
741 "%29 = OpVariable %26 Function\n"
742 "%30 = OpVariable %26 Function\n"
743 "%34 = OpVariable %33 Function\n"
744 "%38 = OpVariable %33 Function\n"
745 "%42 = OpVariable %26 Function\n"
746 "%65 = OpVariable %26 Function\n"
747 "%9 = OpLoad %6 %8\n"
748 "%12 = OpIEqual %11 %9 %10\n"
749 "OpSelectionMerge %14 None\n"
750 "OpBranchConditional %12 %13 %14\n"
751 "%13 = OpLabel\n"
752 "%23 = OpAccessChain %22 %20 %10\n"
753 "OpStore %23 %21\n"
754 "%25 = OpAccessChain %22 %20 %24\n"
755 "OpStore %25 %21\n"
756 "OpBranch %14\n"
757 "%14 = OpLabel\n"
758 "OpStore %27 %28\n"
759 "OpStore %29 %28\n"
760 "OpStore %30 %31\n"
761 "%37 = OpGroupNonUniformBallot %32 %36 %35\n"
762 "OpStore %34 %37\n"
763 "%41 = OpLoad %32 %40\n"
764 "OpStore %38 %41\n"
765 "OpStore %42 %31\n"
766 "OpBranch %43\n"
767 "%43 = OpLabel\n"
768 "OpLoopMerge %45 %46 None\n"
769 "OpBranch %47\n"
770 "%47 = OpLabel\n"
771 "%48 = OpLoad %16 %42\n"
772 "%51 = OpLoad %16 %50\n"
773 "%52 = OpULessThan %11 %48 %51\n"
774 "OpBranchConditional %52 %44 %45\n"
775 "%44 = OpLabel\n"
776 "%53 = OpLoad %16 %42\n"
777 "%55 = OpLoad %16 %54\n" +
778 comparison +
779 "%57 = OpLoad %32 %38\n"
780 "%58 = OpLoad %16 %42\n"
781 "%59 = OpGroupNonUniformBallotBitExtract %11 %36 %57 %58\n"
782 "%60 = OpLogicalNotEqual %11 %56 %59\n"
783 "OpSelectionMerge %62 None\n"
784 "OpBranchConditional %60 %61 %62\n"
785 "%61 = OpLabel\n"
786 "OpStore %27 %31\n"
787 "OpBranch %62\n"
788 "%62 = OpLabel\n"
789 "OpBranch %46\n"
790 "%46 = OpLabel\n"
791 "%63 = OpLoad %16 %42\n"
792 "%64 = OpIAdd %16 %63 %24\n"
793 "OpStore %42 %64\n"
794 "OpBranch %43\n"
795 "%45 = OpLabel\n"
796 "OpStore %65 %31\n"
797 "OpBranch %66\n"
798 "%66 = OpLabel\n"
799 "OpLoopMerge %68 %69 None\n"
800 "OpBranch %70\n"
801 "%70 = OpLabel\n"
802 "%71 = OpLoad %16 %65\n"
803 "%73 = OpULessThan %11 %71 %72\n"
804 "OpBranchConditional %73 %67 %68\n"
805 "%67 = OpLabel\n"
806 "%74 = OpAccessChain %26 %38 %31\n"
807 "%75 = OpLoad %16 %74\n"
808 "%76 = OpLoad %16 %29\n"
809 "%77 = OpBitwiseAnd %16 %75 %76\n"
810 "%78 = OpUGreaterThan %11 %77 %31\n"
811 "OpSelectionMerge %80 None\n"
812 "OpBranchConditional %78 %79 %80\n"
813 "%79 = OpLabel\n"
814 "%81 = OpLoad %16 %30\n"
815 "%82 = OpIAdd %16 %81 %24\n"
816 "OpStore %30 %82\n"
817 "OpBranch %80\n"
818 "%80 = OpLabel\n"
819 "%83 = OpAccessChain %26 %38 %28\n"
820 "%84 = OpLoad %16 %83\n"
821 "%85 = OpLoad %16 %29\n"
822 "%86 = OpBitwiseAnd %16 %84 %85\n"
823 "%87 = OpUGreaterThan %11 %86 %31\n"
824 "OpSelectionMerge %89 None\n"
825 "OpBranchConditional %87 %88 %89\n"
826 "%88 = OpLabel\n"
827 "%90 = OpLoad %16 %30\n"
828 "%91 = OpIAdd %16 %90 %24\n"
829 "OpStore %30 %91\n"
830 "OpBranch %89\n"
831 "%89 = OpLabel\n"
832 "%93 = OpAccessChain %26 %38 %92\n"
833 "%94 = OpLoad %16 %93\n"
834 "%95 = OpLoad %16 %29\n"
835 "%96 = OpBitwiseAnd %16 %94 %95\n"
836 "%97 = OpUGreaterThan %11 %96 %31\n"
837 "OpSelectionMerge %99 None\n"
838 "OpBranchConditional %97 %98 %99\n"
839 "%98 = OpLabel\n"
840 "%100 = OpLoad %16 %30\n"
841 "%101 = OpIAdd %16 %100 %24\n"
842 "OpStore %30 %101\n"
843 "OpBranch %99\n"
844 "%99 = OpLabel\n"
845 "%102 = OpAccessChain %26 %38 %36\n"
846 "%103 = OpLoad %16 %102\n"
847 "%104 = OpLoad %16 %29\n"
848 "%105 = OpBitwiseAnd %16 %103 %104\n"
849 "%106 = OpUGreaterThan %11 %105 %31\n"
850 "OpSelectionMerge %108 None\n"
851 "OpBranchConditional %106 %107 %108\n"
852 "%107 = OpLabel\n"
853 "%109 = OpLoad %16 %30\n"
854 "%110 = OpIAdd %16 %109 %24\n"
855 "OpStore %30 %110\n"
856 "OpBranch %108\n"
857 "%108 = OpLabel\n"
858 "%111 = OpLoad %16 %29\n"
859 "%112 = OpShiftLeftLogical %16 %111 %24\n"
860 "OpStore %29 %112\n"
861 "OpBranch %69\n"
862 "%69 = OpLabel\n"
863 "%113 = OpLoad %16 %65\n"
864 "%114 = OpIAdd %16 %113 %24\n"
865 "OpStore %65 %114\n"
866 "OpBranch %66\n"
867 "%68 = OpLabel\n"
868 "%115 = OpLoad %32 %38\n"
869 "%116 = OpGroupNonUniformBallotBitCount %16 %36 Reduce %115\n"
870 "%117 = OpLoad %16 %30\n"
871 "%118 = OpINotEqual %11 %116 %117\n"
872 "OpSelectionMerge %120 None\n"
873 "OpBranchConditional %118 %119 %120\n"
874 "%119 = OpLabel\n"
875 "OpStore %27 %31\n"
876 "OpBranch %120\n"
877 "%120 = OpLabel\n"
878 "%124 = OpLoad %6 %8\n"
879 "%125 = OpLoad %16 %27\n"
880 "%126 = OpConvertUToF %15 %125\n"
881 "%127 = OpAccessChain %22 %123 %124\n"
882 "OpStore %127 %126\n"
883 "%134 = OpLoad %6 %8\n"
884 "%140 = OpLoad %6 %8\n"
885 "%142 = OpAccessChain %141 %139 %140 %10\n"
886 "%143 = OpLoad %128 %142\n"
887 "%145 = OpAccessChain %144 %133 %134 %10\n"
888 "OpStore %145 %143\n"
889 "OpReturn\n"
890 "OpFunctionEnd\n";
891 programCollection.spirvAsmSources.add("tesc") << controlSource << buildOptionsSpr;
892 subgroups::setTesEvalShaderFrameBuffer(programCollection);
893 }
894 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
895 {
896 /*
897 const string bdy = subgroupMask(caseDef);
898 const string geometry =
899 "#version 450\n"
900 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
901 "layout(points) in;\n"
902 "layout(points, max_vertices = 1) out;\n"
903 "layout(location = 0) out float out_color;\n"
904 "\n"
905 "void main (void)\n"
906 "{\n"
907 + bdy +
908 " out_color = float(tempResult);\n"
909 " gl_Position = gl_in[0].gl_Position;\n"
910 " gl_PointSize = gl_in[0].gl_PointSize;\n"
911 " EmitVertex();\n"
912 " EndPrimitive();\n"
913 "}\n";
914 programCollection.glslSources.add("geometry")
915 << glu::GeometrySource(geometry) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
916 */
917
918 ostringstream geometry;
919 geometry << "; SPIR-V\n"
920 << "; Version: 1.3\n"
921 << "; Generator: Khronos Glslang Reference Front End; 2\n"
922 << "; Bound: 125\n"
923 << "; Schema: 0\n"
924 << "OpCapability Geometry\n"
925 << (*caseDef.geometryPointSizeSupported ? "OpCapability GeometryPointSize\n" : "")
926 << "OpCapability GroupNonUniform\n"
927 << "OpCapability GroupNonUniformBallot\n"
928 << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
929 << "OpMemoryModel Logical GLSL450\n"
930 << "OpEntryPoint Geometry %4 \"main\" %22 %32 %36 %107 %114 %119\n"
931 << "OpExecutionMode %4 InputPoints\n"
932 << "OpExecutionMode %4 Invocations 1\n"
933 << "OpExecutionMode %4 OutputPoints\n"
934 << "OpExecutionMode %4 OutputVertices 1\n"
935 << mask << "OpDecorate %32 RelaxedPrecision\n"
936 << "OpDecorate %32 BuiltIn SubgroupSize\n"
937 << "OpDecorate %33 RelaxedPrecision\n"
938 << "OpDecorate %36 RelaxedPrecision\n"
939 << "OpDecorate %36 BuiltIn SubgroupLocalInvocationId\n"
940 << "OpDecorate %37 RelaxedPrecision\n"
941 << "OpDecorate %107 Location 0\n"
942 << "OpMemberDecorate %112 0 BuiltIn Position\n"
943 << "OpMemberDecorate %112 1 BuiltIn PointSize\n"
944 << "OpMemberDecorate %112 2 BuiltIn ClipDistance\n"
945 << "OpMemberDecorate %112 3 BuiltIn CullDistance\n"
946 << "OpDecorate %112 Block\n"
947 << "OpMemberDecorate %116 0 BuiltIn Position\n"
948 << "OpMemberDecorate %116 1 BuiltIn PointSize\n"
949 << "OpMemberDecorate %116 2 BuiltIn ClipDistance\n"
950 << "OpMemberDecorate %116 3 BuiltIn CullDistance\n"
951 << "OpDecorate %116 Block\n"
952 << "%2 = OpTypeVoid\n"
953 << "%3 = OpTypeFunction %2\n"
954 << "%6 = OpTypeInt 32 0\n"
955 << "%7 = OpTypePointer Function %6\n"
956 << "%9 = OpConstant %6 1\n"
957 << "%12 = OpConstant %6 0\n"
958 << "%13 = OpTypeVector %6 4\n"
959 << "%14 = OpTypePointer Function %13\n"
960 << "%16 = OpTypeBool\n"
961 << "%17 = OpConstantTrue %16\n"
962 << "%18 = OpConstant %6 3\n"
963 << "%21 = OpTypePointer Input %13\n"
964 << "%22 = OpVariable %21 Input\n"
965 << "%31 = OpTypePointer Input %6\n"
966 << "%32 = OpVariable %31 Input\n"
967 << "%36 = OpVariable %31 Input\n"
968 << "%46 = OpTypeInt 32 1\n"
969 << "%47 = OpConstant %46 1\n"
970 << "%56 = OpConstant %6 32\n"
971 << "%76 = OpConstant %6 2\n"
972 << "%105 = OpTypeFloat 32\n"
973 << "%106 = OpTypePointer Output %105\n"
974 << "%107 = OpVariable %106 Output\n"
975 << "%110 = OpTypeVector %105 4\n"
976 << "%111 = OpTypeArray %105 %9\n"
977 << "%112 = OpTypeStruct %110 %105 %111 %111\n"
978 << "%113 = OpTypePointer Output %112\n"
979 << "%114 = OpVariable %113 Output\n"
980 << "%115 = OpConstant %46 0\n"
981 << "%116 = OpTypeStruct %110 %105 %111 %111\n"
982 << "%117 = OpTypeArray %116 %9\n"
983 << "%118 = OpTypePointer Input %117\n"
984 << "%119 = OpVariable %118 Input\n"
985 << "%120 = OpTypePointer Input %110\n"
986 << "%123 = OpTypePointer Output %110\n"
987 << (*caseDef.geometryPointSizeSupported ? "%125 = OpTypePointer Input %105\n"
988 "%126 = OpTypePointer Output %105\n" :
989 "")
990 << "%4 = OpFunction %2 None %3\n"
991 << "%5 = OpLabel\n"
992 << "%8 = OpVariable %7 Function\n"
993 << "%10 = OpVariable %7 Function\n"
994 << "%11 = OpVariable %7 Function\n"
995 << "%15 = OpVariable %14 Function\n"
996 << "%20 = OpVariable %14 Function\n"
997 << "%24 = OpVariable %7 Function\n"
998 << "%49 = OpVariable %7 Function\n"
999 << "OpStore %8 %9\n"
1000 << "OpStore %10 %9\n"
1001 << "OpStore %11 %12\n"
1002 << "%19 = OpGroupNonUniformBallot %13 %18 %17\n"
1003 << "OpStore %15 %19\n"
1004 << "%23 = OpLoad %13 %22\n"
1005 << "OpStore %20 %23\n"
1006 << "OpStore %24 %12\n"
1007 << "OpBranch %25\n"
1008 << "%25 = OpLabel\n"
1009 << "OpLoopMerge %27 %28 None\n"
1010 << "OpBranch %29\n"
1011 << "%29 = OpLabel\n"
1012 << "%30 = OpLoad %6 %24\n"
1013 << "%33 = OpLoad %6 %32\n"
1014 << "%34 = OpULessThan %16 %30 %33\n"
1015 << "OpBranchConditional %34 %26 %27\n"
1016 << "%26 = OpLabel\n"
1017 << "%35 = OpLoad %6 %24\n"
1018 << "%37 = OpLoad %6 %36\n"
1019 << comparison << "%39 = OpLoad %13 %20\n"
1020 << "%40 = OpLoad %6 %24\n"
1021 << "%41 = OpGroupNonUniformBallotBitExtract %16 %18 %39 %40\n"
1022 << "%42 = OpLogicalNotEqual %16 %38 %41\n"
1023 << "OpSelectionMerge %44 None\n"
1024 << "OpBranchConditional %42 %43 %44\n"
1025 << "%43 = OpLabel\n"
1026 << "OpStore %8 %12\n"
1027 << "OpBranch %44\n"
1028 << "%44 = OpLabel\n"
1029 << "OpBranch %28\n"
1030 << "%28 = OpLabel\n"
1031 << "%45 = OpLoad %6 %24\n"
1032 << "%48 = OpIAdd %6 %45 %47\n"
1033 << "OpStore %24 %48\n"
1034 << "OpBranch %25\n"
1035 << "%27 = OpLabel\n"
1036 << "OpStore %49 %12\n"
1037 << "OpBranch %50\n"
1038 << "%50 = OpLabel\n"
1039 << "OpLoopMerge %52 %53 None\n"
1040 << "OpBranch %54\n"
1041 << "%54 = OpLabel\n"
1042 << "%55 = OpLoad %6 %49\n"
1043 << "%57 = OpULessThan %16 %55 %56\n"
1044 << "OpBranchConditional %57 %51 %52\n"
1045 << "%51 = OpLabel\n"
1046 << "%58 = OpAccessChain %7 %20 %12\n"
1047 << "%59 = OpLoad %6 %58\n"
1048 << "%60 = OpLoad %6 %10\n"
1049 << "%61 = OpBitwiseAnd %6 %59 %60\n"
1050 << "%62 = OpUGreaterThan %16 %61 %12\n"
1051 << "OpSelectionMerge %64 None\n"
1052 << "OpBranchConditional %62 %63 %64\n"
1053 << "%63 = OpLabel\n"
1054 << "%65 = OpLoad %6 %11\n"
1055 << "%66 = OpIAdd %6 %65 %47\n"
1056 << "OpStore %11 %66\n"
1057 << "OpBranch %64\n"
1058 << "%64 = OpLabel\n"
1059 << "%67 = OpAccessChain %7 %20 %9\n"
1060 << "%68 = OpLoad %6 %67\n"
1061 << "%69 = OpLoad %6 %10\n"
1062 << "%70 = OpBitwiseAnd %6 %68 %69\n"
1063 << "%71 = OpUGreaterThan %16 %70 %12\n"
1064 << "OpSelectionMerge %73 None\n"
1065 << "OpBranchConditional %71 %72 %73\n"
1066 << "%72 = OpLabel\n"
1067 << "%74 = OpLoad %6 %11\n"
1068 << "%75 = OpIAdd %6 %74 %47\n"
1069 << "OpStore %11 %75\n"
1070 << "OpBranch %73\n"
1071 << "%73 = OpLabel\n"
1072 << "%77 = OpAccessChain %7 %20 %76\n"
1073 << "%78 = OpLoad %6 %77\n"
1074 << "%79 = OpLoad %6 %10\n"
1075 << "%80 = OpBitwiseAnd %6 %78 %79\n"
1076 << "%81 = OpUGreaterThan %16 %80 %12\n"
1077 << "OpSelectionMerge %83 None\n"
1078 << "OpBranchConditional %81 %82 %83\n"
1079 << "%82 = OpLabel\n"
1080 << "%84 = OpLoad %6 %11\n"
1081 << "%85 = OpIAdd %6 %84 %47\n"
1082 << "OpStore %11 %85\n"
1083 << "OpBranch %83\n"
1084 << "%83 = OpLabel\n"
1085 << "%86 = OpAccessChain %7 %20 %18\n"
1086 << "%87 = OpLoad %6 %86\n"
1087 << "%88 = OpLoad %6 %10\n"
1088 << "%89 = OpBitwiseAnd %6 %87 %88\n"
1089 << "%90 = OpUGreaterThan %16 %89 %12\n"
1090 << "OpSelectionMerge %92 None\n"
1091 << "OpBranchConditional %90 %91 %92\n"
1092 << "%91 = OpLabel\n"
1093 << "%93 = OpLoad %6 %11\n"
1094 << "%94 = OpIAdd %6 %93 %47\n"
1095 << "OpStore %11 %94\n"
1096 << "OpBranch %92\n"
1097 << "%92 = OpLabel\n"
1098 << "%95 = OpLoad %6 %10\n"
1099 << "%96 = OpShiftLeftLogical %6 %95 %47\n"
1100 << "OpStore %10 %96\n"
1101 << "OpBranch %53\n"
1102 << "%53 = OpLabel\n"
1103 << "%97 = OpLoad %6 %49\n"
1104 << "%98 = OpIAdd %6 %97 %47\n"
1105 << "OpStore %49 %98\n"
1106 << "OpBranch %50\n"
1107 << "%52 = OpLabel\n"
1108 << "%99 = OpLoad %13 %20\n"
1109 << "%100 = OpGroupNonUniformBallotBitCount %6 %18 Reduce %99\n"
1110 << "%101 = OpLoad %6 %11\n"
1111 << "%102 = OpINotEqual %16 %100 %101\n"
1112 << "OpSelectionMerge %104 None\n"
1113 << "OpBranchConditional %102 %103 %104\n"
1114 << "%103 = OpLabel\n"
1115 << "OpStore %8 %12\n"
1116 << "OpBranch %104\n"
1117 << "%104 = OpLabel\n"
1118 << "%108 = OpLoad %6 %8\n"
1119 << "%109 = OpConvertUToF %105 %108\n"
1120 << "OpStore %107 %109\n"
1121 << "%121 = OpAccessChain %120 %119 %115 %115\n"
1122 << "%122 = OpLoad %110 %121\n"
1123 << "%124 = OpAccessChain %123 %114 %115\n"
1124 << "OpStore %124 %122\n"
1125 << (*caseDef.geometryPointSizeSupported ? "%127 = OpAccessChain %125 %119 %115 %47\n"
1126 "%128 = OpLoad %105 %127\n"
1127 "%129 = OpAccessChain %126 %114 %47\n"
1128 "OpStore %129 %128\n" :
1129 "")
1130 << "OpEmitVertex\n"
1131 << "OpEndPrimitive\n"
1132 << "OpReturn\n"
1133 << "OpFunctionEnd\n";
1134
1135 programCollection.spirvAsmSources.add("geometry") << geometry.str() << buildOptionsSpr;
1136 }
1137 else
1138 {
1139 DE_FATAL("Unsupported shader stage");
1140 }
1141 }
1142
getExtHeader(const CaseDefinition &)1143 string getExtHeader(const CaseDefinition &)
1144 {
1145 return "#extension GL_KHR_shader_subgroup_ballot: enable\n";
1146 }
1147
getPerStageHeadDeclarations(const CaseDefinition & caseDef)1148 vector<string> getPerStageHeadDeclarations(const CaseDefinition &caseDef)
1149 {
1150 const uint32_t stageCount = subgroups::getStagesCount(caseDef.shaderStage);
1151 const bool fragment = (caseDef.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT) != 0;
1152 vector<string> result(stageCount, string());
1153
1154 if (fragment)
1155 result.reserve(result.size() + 1);
1156
1157 for (size_t i = 0; i < result.size(); ++i)
1158 {
1159 result[i] = "layout(set = 0, binding = " + de::toString(i) +
1160 ", std430) buffer Output\n"
1161 "{\n"
1162 " uint result[];\n"
1163 "};\n";
1164 }
1165
1166 if (fragment)
1167 {
1168 const string fragPart = "layout(location = 0) out uint result;\n";
1169
1170 result.push_back(fragPart);
1171 }
1172
1173 return result;
1174 }
1175
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)1176 void initPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
1177 {
1178 #ifndef CTS_USES_VULKANSC
1179 const bool spirv14required =
1180 (isAllRayTracingStages(caseDef.shaderStage) || isAllMeshShadingStages(caseDef.shaderStage));
1181 #else
1182 const bool spirv14required = false;
1183 #endif // CTS_USES_VULKANSC
1184 const SpirvVersion spirvVersion = (spirv14required ? SPIRV_VERSION_1_4 : SPIRV_VERSION_1_3);
1185 const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, spirvVersion, 0u, spirv14required);
1186 const string extHeader = getExtHeader(caseDef);
1187 const string testSrc = subgroupMask(caseDef);
1188 const vector<string> headDeclarations = getPerStageHeadDeclarations(caseDef);
1189
1190 subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32_UINT, true,
1191 extHeader, testSrc, "", headDeclarations);
1192 }
1193
supportedCheck(Context & context,CaseDefinition caseDef)1194 void supportedCheck(Context &context, CaseDefinition caseDef)
1195 {
1196 if (!subgroups::isSubgroupSupported(context))
1197 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
1198
1199 if (caseDef.requiredSubgroupSize)
1200 {
1201 context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
1202
1203 #ifndef CTS_USES_VULKANSC
1204 const VkPhysicalDeviceSubgroupSizeControlFeatures &subgroupSizeControlFeatures =
1205 context.getSubgroupSizeControlFeatures();
1206 const VkPhysicalDeviceSubgroupSizeControlProperties &subgroupSizeControlProperties =
1207 context.getSubgroupSizeControlProperties();
1208 #else
1209 const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT &subgroupSizeControlFeatures =
1210 context.getSubgroupSizeControlFeaturesEXT();
1211 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT &subgroupSizeControlProperties =
1212 context.getSubgroupSizeControlPropertiesEXT();
1213 #endif // CTS_USES_VULKANSC
1214
1215 if (subgroupSizeControlFeatures.subgroupSizeControl == false)
1216 TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
1217
1218 if (subgroupSizeControlFeatures.computeFullSubgroups == false)
1219 TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
1220
1221 if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
1222 TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
1223 }
1224
1225 *caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
1226
1227 vkt::subgroups::supportedCheckShader(context, caseDef.shaderStage);
1228
1229 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
1230 {
1231 TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
1232 }
1233
1234 #ifndef CTS_USES_VULKANSC
1235 if (isAllRayTracingStages(caseDef.shaderStage))
1236 {
1237 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1238 }
1239 else if (isAllMeshShadingStages(caseDef.shaderStage))
1240 {
1241 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
1242 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1243
1244 if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
1245 {
1246 const auto &features = context.getMeshShaderFeaturesEXT();
1247 if (!features.taskShader)
1248 TCU_THROW(NotSupportedError, "Task shaders not supported");
1249 }
1250 }
1251 #endif // CTS_USES_VULKANSC
1252 }
1253
noSSBOtest(Context & context,const CaseDefinition caseDef)1254 TestStatus noSSBOtest(Context &context, const CaseDefinition caseDef)
1255 {
1256 switch (caseDef.shaderStage)
1257 {
1258 case VK_SHADER_STAGE_VERTEX_BIT:
1259 return makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages);
1260 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
1261 return makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL,
1262 checkVertexPipelineStages);
1263 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
1264 return makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL,
1265 checkVertexPipelineStages);
1266 case VK_SHADER_STAGE_GEOMETRY_BIT:
1267 return makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages);
1268 default:
1269 TCU_THROW(InternalError, "Unhandled shader stage");
1270 }
1271 }
1272
test(Context & context,const CaseDefinition caseDef)1273 TestStatus test(Context &context, const CaseDefinition caseDef)
1274 {
1275 const bool isCompute = isAllComputeStages(caseDef.shaderStage);
1276 #ifndef CTS_USES_VULKANSC
1277 const bool isMesh = isAllMeshShadingStages(caseDef.shaderStage);
1278 #else
1279 const bool isMesh = false;
1280 #endif // CTS_USES_VULKANSC
1281 DE_ASSERT(!(isCompute && isMesh));
1282
1283 if (isCompute || isMesh)
1284 {
1285 #ifndef CTS_USES_VULKANSC
1286 const VkPhysicalDeviceSubgroupSizeControlProperties &subgroupSizeControlProperties =
1287 context.getSubgroupSizeControlProperties();
1288 #else
1289 const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT &subgroupSizeControlProperties =
1290 context.getSubgroupSizeControlPropertiesEXT();
1291 #endif // CTS_USES_VULKANSC
1292 TestLog &log = context.getTestContext().getLog();
1293
1294 if (caseDef.requiredSubgroupSize == false)
1295 {
1296 if (isCompute)
1297 return makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeOrMeshStage);
1298 else
1299 return makeMeshTest(context, VK_FORMAT_R32_UINT, nullptr, 0, nullptr, checkComputeOrMeshStage);
1300 }
1301
1302 log << TestLog::Message << "Testing required subgroup size range ["
1303 << subgroupSizeControlProperties.minSubgroupSize << ", " << subgroupSizeControlProperties.maxSubgroupSize
1304 << "]" << TestLog::EndMessage;
1305
1306 // According to the spec, requiredSubgroupSize must be a power-of-two integer.
1307 for (uint32_t size = subgroupSizeControlProperties.minSubgroupSize;
1308 size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
1309 {
1310 TestStatus result(QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
1311
1312 if (isCompute)
1313 result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL,
1314 checkComputeOrMeshStage, size);
1315 else
1316 result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, nullptr, 0, nullptr,
1317 checkComputeOrMeshStage, size);
1318
1319 if (result.getCode() != QP_TEST_RESULT_PASS)
1320 {
1321 log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
1322 return result;
1323 }
1324 }
1325
1326 return TestStatus::pass("OK");
1327 }
1328 else if (isAllGraphicsStages(caseDef.shaderStage))
1329 {
1330 const VkShaderStageFlags stages = subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
1331
1332 return subgroups::allStages(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStages,
1333 stages);
1334 }
1335 #ifndef CTS_USES_VULKANSC
1336 else if (isAllRayTracingStages(caseDef.shaderStage))
1337 {
1338 const VkShaderStageFlags stages = subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
1339
1340 return subgroups::allRayTracingStages(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL,
1341 checkVertexPipelineStages, stages);
1342 }
1343 #endif // CTS_USES_VULKANSC
1344 else
1345 TCU_THROW(InternalError, "Unknown stage or invalid stage set");
1346 }
1347
createSubgroupsBuiltinMaskVarTests(TestContext & testCtx)1348 TestCaseGroup *createSubgroupsBuiltinMaskVarTests(TestContext &testCtx)
1349 {
1350 de::MovePtr<TestCaseGroup> group(new TestCaseGroup(testCtx, "builtin_mask_var"));
1351 de::MovePtr<TestCaseGroup> graphicGroup(new TestCaseGroup(testCtx, "graphics"));
1352 de::MovePtr<TestCaseGroup> computeGroup(new TestCaseGroup(testCtx, "compute"));
1353 de::MovePtr<TestCaseGroup> framebufferGroup(new TestCaseGroup(testCtx, "framebuffer"));
1354 #ifndef CTS_USES_VULKANSC
1355 de::MovePtr<TestCaseGroup> raytracingGroup(new TestCaseGroup(testCtx, "ray_tracing"));
1356 de::MovePtr<TestCaseGroup> meshGroup(new TestCaseGroup(testCtx, "mesh"));
1357 #endif // CTS_USES_VULKANSC
1358 const TestType allStagesBuiltinVars[] = {
1359 TEST_TYPE_SUBGROUP_EQ_MASK, TEST_TYPE_SUBGROUP_GE_MASK, TEST_TYPE_SUBGROUP_GT_MASK,
1360 TEST_TYPE_SUBGROUP_LE_MASK, TEST_TYPE_SUBGROUP_LT_MASK,
1361 };
1362 const VkShaderStageFlags fbStages[] = {
1363 VK_SHADER_STAGE_VERTEX_BIT,
1364 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1365 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1366 VK_SHADER_STAGE_GEOMETRY_BIT,
1367 };
1368 #ifndef CTS_USES_VULKANSC
1369 const VkShaderStageFlags meshStages[] = {
1370 VK_SHADER_STAGE_MESH_BIT_EXT,
1371 VK_SHADER_STAGE_TASK_BIT_EXT,
1372 };
1373 #endif // CTS_USES_VULKANSC
1374 const bool boolValues[] = {false, true};
1375
1376 for (int a = 0; a < DE_LENGTH_OF_ARRAY(allStagesBuiltinVars); ++a)
1377 {
1378 const TestType testType = allStagesBuiltinVars[a];
1379 const string name = getTestName(testType);
1380
1381 {
1382 const CaseDefinition caseDef = {
1383 testType, // TestType testType;
1384 VK_SHADER_STAGE_ALL_GRAPHICS, // VkShaderStageFlags shaderStage;
1385 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
1386 false // bool requiredSubgroupSize;
1387 };
1388
1389 addFunctionCaseWithPrograms(graphicGroup.get(), name, supportedCheck, initPrograms, test, caseDef);
1390 }
1391
1392 #ifndef CTS_USES_VULKANSC
1393 {
1394 const CaseDefinition caseDef = {
1395 testType, // TestType testType;
1396 SHADER_STAGE_ALL_RAY_TRACING, // VkShaderStageFlags shaderStage;
1397 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
1398 false // bool requiredSubgroupSize;
1399 };
1400
1401 addFunctionCaseWithPrograms(raytracingGroup.get(), name, supportedCheck, initPrograms, test, caseDef);
1402 }
1403 #endif // CTS_USES_VULKANSC
1404
1405 for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
1406 {
1407 const bool requiredSubgroupSize = boolValues[groupSizeNdx];
1408 const string testName = name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "");
1409 const CaseDefinition caseDef = {
1410 testType, // TestType testType;
1411 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags shaderStage;
1412 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
1413 requiredSubgroupSize // bool requiredSubgroupSize;
1414 };
1415
1416 addFunctionCaseWithPrograms(computeGroup.get(), testName, supportedCheck, initPrograms, test, caseDef);
1417 }
1418
1419 #ifndef CTS_USES_VULKANSC
1420 for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
1421 {
1422 for (const auto &stage : meshStages)
1423 {
1424 const bool requiredSubgroupSize = boolValues[groupSizeNdx];
1425 const string testName =
1426 name + (requiredSubgroupSize ? "_requiredsubgroupsize" : "") + "_" + getShaderStageName(stage);
1427 const CaseDefinition caseDef = {
1428 testType, // TestType testType;
1429 stage, // VkShaderStageFlags shaderStage;
1430 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
1431 requiredSubgroupSize // bool requiredSubgroupSize;
1432 };
1433
1434 addFunctionCaseWithPrograms(meshGroup.get(), testName, supportedCheck, initPrograms, test, caseDef);
1435 }
1436 }
1437 #endif // CTS_USES_VULKANSC
1438
1439 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
1440 {
1441 const CaseDefinition caseDef = {
1442 testType, // TestType testType;
1443 fbStages[stageIndex], // VkShaderStageFlags shaderStage;
1444 de::SharedPtr<bool>(new bool), // de::SharedPtr<bool> geometryPointSizeSupported;
1445 false // bool requiredSubgroupSize;
1446 };
1447 const string testName = name + +"_" + getShaderStageName(caseDef.shaderStage);
1448
1449 addFunctionCaseWithPrograms(framebufferGroup.get(), testName, supportedCheck, initFrameBufferPrograms,
1450 noSSBOtest, caseDef);
1451 }
1452 }
1453
1454 group->addChild(graphicGroup.release());
1455 group->addChild(computeGroup.release());
1456 group->addChild(framebufferGroup.release());
1457 #ifndef CTS_USES_VULKANSC
1458 group->addChild(raytracingGroup.release());
1459 group->addChild(meshGroup.release());
1460 #endif // CTS_USES_VULKANSC
1461
1462 return group.release();
1463 }
1464 } // namespace subgroups
1465 } // namespace vkt
1466