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