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