• 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 
1021 #ifndef CTS_USES_VULKANSC
getPerStageHeadDeclarations(const CaseDefinition & caseDef)1022 vector<string> getPerStageHeadDeclarations (const CaseDefinition& caseDef)
1023 {
1024 	const deUint32	stageCount	= subgroups::getStagesCount(caseDef.shaderStage);
1025 	vector<string>	result		(stageCount, string());
1026 
1027 	for (size_t i = 0; i < result.size(); ++i)
1028 	{
1029 		result[i] =
1030 			"layout(set = 0, binding = " + de::toString(i) + ", std430) buffer Buffer1\n"
1031 			"{\n"
1032 			"  uvec4 result[];\n"
1033 			"};\n";
1034 	}
1035 
1036 	return result;
1037 }
1038 #endif // CTS_USES_VULKANSC
1039 
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)1040 void initPrograms (SourceCollections& programCollection, CaseDefinition caseDef)
1041 {
1042 	if (isAllComputeStages(caseDef.shaderStage))
1043 	{
1044 		const ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
1045 
1046 		ostringstream src;
1047 
1048 		src << "#version 450\n"
1049 			<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1050 			<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
1051 			"local_size_z_id = 2) in;\n"
1052 			<< "layout(set = 0, binding = 0, std430) buffer Output\n"
1053 			<< "{\n"
1054 			<< "  uvec4 result[];\n"
1055 			<< "};\n"
1056 			<< "\n"
1057 			<< "void main (void)\n"
1058 			<< "{\n"
1059 			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
1060 			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
1061 			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
1062 			"gl_GlobalInvocationID.x;\n"
1063 			<< "  result[offset] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, gl_NumSubgroups, gl_SubgroupID);\n"
1064 			<< "}\n";
1065 
1066 		programCollection.glslSources.add("comp") << glu::ComputeSource(src.str()) << buildOptions;
1067 	}
1068 #ifndef CTS_USES_VULKANSC
1069 	else if (isAllMeshShadingStages(caseDef.shaderStage))
1070 	{
1071 		const ShaderBuildOptions	buildOptions		(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, 0u, true);
1072 		const string				extHeader			= "#extension GL_KHR_shader_subgroup_basic : require\n";
1073 		const string				tempRes				= "  uvec4 tempRes;\n";
1074 		const string				testSrc				= "  tempRes = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID, gl_NumSubgroups, gl_SubgroupID);\n";
1075 		const vector<string>		headDeclarations	= getPerStageHeadDeclarations(caseDef);
1076 
1077 		subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32G32B32A32_UINT, false, extHeader, testSrc, "", headDeclarations, false, tempRes);
1078 	}
1079 #endif // CTS_USES_VULKANSC
1080 	else if (isAllGraphicsStages(caseDef.shaderStage))
1081 	{
1082 		const ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
1083 		const SpirVAsmBuildOptions	buildOptionsSpr	(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
1084 
1085 		{
1086 			/*
1087 				"#version 450\n"
1088 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
1089 				"layout(set = 0, binding = 0, std430) buffer Output\n"
1090 				"{\n"
1091 				"  uvec4 result[];\n"
1092 				"};\n"
1093 				"\n"
1094 				"void main (void)\n"
1095 				"{\n"
1096 				"  result[gl_VertexIndex] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID + 1024, 0, 0);\n"
1097 				"  float pixelSize = 2.0f/1024.0f;\n"
1098 				"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
1099 				"  gl_Position = vec4(float(gl_VertexIndex) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
1100 				"  gl_PointSize = 1.0f;\n"
1101 				"}\n";
1102 			*/
1103 			const string vertex =
1104 				"; SPIR-V\n"
1105 				"; Version: 1.3\n"
1106 				"; Generator: Khronos Glslang Reference Front End; 1\n"
1107 				"; Bound: 52\n"
1108 				"; Schema: 0\n"
1109 				"OpCapability Shader\n"
1110 				"OpCapability GroupNonUniform\n"
1111 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1112 				"OpMemoryModel Logical GLSL450\n"
1113 				"OpEntryPoint Vertex %4 \"main\" %15 %18 %20 %41\n"
1114 				"OpDecorate %8 ArrayStride 16\n"
1115 				"OpMemberDecorate %9 0 Offset 0\n"
1116 				"OpDecorate %9 BufferBlock\n"
1117 				"OpDecorate %11 DescriptorSet 0\n"
1118 				"OpDecorate %11 Binding 0\n"
1119 				"OpDecorate %15 BuiltIn VertexIndex\n"
1120 				"OpDecorate %18 RelaxedPrecision\n"
1121 				"OpDecorate %18 BuiltIn SubgroupSize\n"
1122 				"OpDecorate %19 RelaxedPrecision\n"
1123 				"OpDecorate %20 RelaxedPrecision\n"
1124 				"OpDecorate %20 BuiltIn SubgroupLocalInvocationId\n"
1125 				"OpDecorate %21 RelaxedPrecision\n"
1126 				"OpMemberDecorate %39 0 BuiltIn Position\n"
1127 				"OpMemberDecorate %39 1 BuiltIn PointSize\n"
1128 				"OpMemberDecorate %39 2 BuiltIn ClipDistance\n"
1129 				"OpMemberDecorate %39 3 BuiltIn CullDistance\n"
1130 				"OpDecorate %39 Block\n"
1131 				"%2 = OpTypeVoid\n"
1132 				"%3 = OpTypeFunction %2\n"
1133 				"%6 = OpTypeInt 32 0\n"
1134 				"%7 = OpTypeVector %6 4\n"
1135 				"%8 = OpTypeRuntimeArray %7\n"
1136 				"%9 = OpTypeStruct %8\n"
1137 				"%10 = OpTypePointer Uniform %9\n"
1138 				"%11 = OpVariable %10 Uniform\n"
1139 				"%12 = OpTypeInt 32 1\n"
1140 				"%13 = OpConstant %12 0\n"
1141 				"%14 = OpTypePointer Input %12\n"
1142 				"%15 = OpVariable %14 Input\n"
1143 				"%17 = OpTypePointer Input %6\n"
1144 				"%18 = OpVariable %17 Input\n"
1145 				"%20 = OpVariable %17 Input\n"
1146 				"%22 = OpConstant %6 0\n"
1147 				"%24 = OpTypePointer Uniform %7\n"
1148 				"%26 = OpTypeFloat 32\n"
1149 				"%27 = OpTypePointer Function %26\n"
1150 				"%29 = OpConstant %26 0.00195313\n"
1151 				"%32 = OpConstant %26 2\n"
1152 				"%34 = OpConstant %26 1\n"
1153 				"%36 = OpTypeVector %26 4\n"
1154 				"%37 = OpConstant %6 1\n"
1155 				"%38 = OpTypeArray %26 %37\n"
1156 				"%39 = OpTypeStruct %36 %26 %38 %38\n"
1157 				"%40 = OpTypePointer Output %39\n"
1158 				"%41 = OpVariable %40 Output\n"
1159 				"%48 = OpConstant %26 0\n"
1160 				"%50 = OpTypePointer Output %36\n"
1161 				"%52 = OpConstant %12 1\n"
1162 				"%99 = OpConstant %6 1024\n"
1163 				"%53 = OpTypePointer Output %26\n"
1164 				"%4 = OpFunction %2 None %3\n"
1165 				"%5 = OpLabel\n"
1166 				"%28 = OpVariable %27 Function\n"
1167 				"%30 = OpVariable %27 Function\n"
1168 				"%16 = OpLoad %12 %15\n"
1169 				"%19 = OpLoad %6 %18\n"
1170 				"%98 = OpLoad %6 %20\n"
1171 				"%21 = OpIAdd %6 %98 %99\n"
1172 				"%23 = OpCompositeConstruct %7 %19 %21 %22 %22\n"
1173 				"%25 = OpAccessChain %24 %11 %13 %16\n"
1174 				"OpStore %25 %23\n"
1175 				"OpStore %28 %29\n"
1176 				"%31 = OpLoad %26 %28\n"
1177 				"%33 = OpFDiv %26 %31 %32\n"
1178 				"%35 = OpFSub %26 %33 %34\n"
1179 				"OpStore %30 %35\n"
1180 				"%42 = OpLoad %12 %15\n"
1181 				"%43 = OpConvertSToF %26 %42\n"
1182 				"%44 = OpLoad %26 %28\n"
1183 				"%45 = OpFMul %26 %43 %44\n"
1184 				"%46 = OpLoad %26 %30\n"
1185 				"%47 = OpFAdd %26 %45 %46\n"
1186 				"%49 = OpCompositeConstruct %36 %47 %48 %48 %34\n"
1187 				"%51 = OpAccessChain %50 %41 %13\n"
1188 				"OpStore %51 %49\n"
1189 				"%54 = OpAccessChain %53 %41 %52\n"
1190 				"OpStore %54 %34\n"
1191 				"OpReturn\n"
1192 				"OpFunctionEnd\n";
1193 				programCollection.spirvAsmSources.add("vert") << vertex << buildOptionsSpr;
1194 		}
1195 
1196 		{
1197 			/*
1198 				"#version 450\n"
1199 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
1200 				"layout(vertices=1) out;\n"
1201 				"layout(set = 0, binding = 1, std430) buffer Output\n"
1202 				"{\n"
1203 				"  uvec4 result[];\n"
1204 				"};\n"
1205 				"\n"
1206 				"void main (void)\n"
1207 				"{\n"
1208 				"  result[gl_PrimitiveID] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID + 1024, 0, 0);\n"
1209 				"  if (gl_InvocationID == 0)\n"
1210 				"  {\n"
1211 				"    gl_TessLevelOuter[0] = 1.0f;\n"
1212 				"    gl_TessLevelOuter[1] = 1.0f;\n"
1213 				"  }\n"
1214 				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1215 				#if GEOMETRY_POINT_SIZE_SUPPORTED
1216 				"  gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n"
1217 				#endif
1218 				"}\n";
1219 			*/
1220 
1221 			const string pointSizeCapability = (*caseDef.geometryPointSizeSupported ? "OpCapability TessellationPointSize\n" : "");
1222 
1223 			const string tesc =
1224 				"; SPIR-V\n"
1225 				"; Version: 1.3\n"
1226 				"; Generator: Khronos Glslang Reference Front End; 1\n"
1227 				"; Bound: 61\n"
1228 				"; Schema: 0\n"
1229 				"OpCapability Tessellation\n"
1230 				"OpCapability GroupNonUniform\n"
1231 				+ pointSizeCapability +
1232 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1233 				"OpMemoryModel Logical GLSL450\n"
1234 				"OpEntryPoint TessellationControl %4 \"main\" %15 %18 %20 %26 %36 %48 %54\n"
1235 				"OpExecutionMode %4 OutputVertices 1\n"
1236 				"OpDecorate %8 ArrayStride 16\n"
1237 				"OpMemberDecorate %9 0 Offset 0\n"
1238 				"OpDecorate %9 BufferBlock\n"
1239 				"OpDecorate %11 DescriptorSet 0\n"
1240 				"OpDecorate %11 Binding 1\n"
1241 				"OpDecorate %15 BuiltIn PrimitiveId\n"
1242 				"OpDecorate %18 RelaxedPrecision\n"
1243 				"OpDecorate %18 BuiltIn SubgroupSize\n"
1244 				"OpDecorate %19 RelaxedPrecision\n"
1245 				"OpDecorate %20 RelaxedPrecision\n"
1246 				"OpDecorate %20 BuiltIn SubgroupLocalInvocationId\n"
1247 				"OpDecorate %21 RelaxedPrecision\n"
1248 				"OpDecorate %26 BuiltIn InvocationId\n"
1249 				"OpDecorate %36 Patch\n"
1250 				"OpDecorate %36 BuiltIn TessLevelOuter\n"
1251 				"OpMemberDecorate %45 0 BuiltIn Position\n"
1252 				"OpMemberDecorate %45 1 BuiltIn PointSize\n"
1253 				"OpMemberDecorate %45 2 BuiltIn ClipDistance\n"
1254 				"OpMemberDecorate %45 3 BuiltIn CullDistance\n"
1255 				"OpDecorate %45 Block\n"
1256 				"OpMemberDecorate %50 0 BuiltIn Position\n"
1257 				"OpMemberDecorate %50 1 BuiltIn PointSize\n"
1258 				"OpMemberDecorate %50 2 BuiltIn ClipDistance\n"
1259 				"OpMemberDecorate %50 3 BuiltIn CullDistance\n"
1260 				"OpDecorate %50 Block\n"
1261 				"%2 = OpTypeVoid\n"
1262 				"%3 = OpTypeFunction %2\n"
1263 				"%6 = OpTypeInt 32 0\n"
1264 				"%7 = OpTypeVector %6 4\n"
1265 				"%8 = OpTypeRuntimeArray %7\n"
1266 				"%9 = OpTypeStruct %8\n"
1267 				"%10 = OpTypePointer Uniform %9\n"
1268 				"%11 = OpVariable %10 Uniform\n"
1269 				"%12 = OpTypeInt 32 1\n"
1270 				"%13 = OpConstant %12 0\n"
1271 				"%14 = OpTypePointer Input %12\n"
1272 				"%15 = OpVariable %14 Input\n"
1273 				"%17 = OpTypePointer Input %6\n"
1274 				"%18 = OpVariable %17 Input\n"
1275 				"%20 = OpVariable %17 Input\n"
1276 				"%22 = OpConstant %6 0\n"
1277 				"%24 = OpTypePointer Uniform %7\n"
1278 				"%26 = OpVariable %14 Input\n"
1279 				"%28 = OpTypeBool\n"
1280 				"%32 = OpTypeFloat 32\n"
1281 				"%33 = OpConstant %6 4\n"
1282 				"%34 = OpTypeArray %32 %33\n"
1283 				"%35 = OpTypePointer Output %34\n"
1284 				"%36 = OpVariable %35 Output\n"
1285 				"%37 = OpConstant %32 1\n"
1286 				"%38 = OpTypePointer Output %32\n"
1287 				"%40 = OpConstant %12 1\n"
1288 				"%42 = OpTypeVector %32 4\n"
1289 				"%43 = OpConstant %6 1\n"
1290 				"%44 = OpTypeArray %32 %43\n"
1291 				"%45 = OpTypeStruct %42 %32 %44 %44\n"
1292 				"%46 = OpTypeArray %45 %43\n"
1293 				"%47 = OpTypePointer Output %46\n"
1294 				"%48 = OpVariable %47 Output\n"
1295 				"%50 = OpTypeStruct %42 %32 %44 %44\n"
1296 				"%51 = OpConstant %6 32\n"
1297 				"%52 = OpTypeArray %50 %51\n"
1298 				"%53 = OpTypePointer Input %52\n"
1299 				"%54 = OpVariable %53 Input\n"
1300 				"%56 = OpTypePointer Input %42\n"
1301 				"%59 = OpTypePointer Output %42\n"
1302 				+ (*caseDef.geometryPointSizeSupported ?
1303 					"%61 = OpTypePointer Input %32\n"
1304 					"%62 = OpTypePointer Output %32\n"
1305 					"%63 = OpConstant %12 1\n" : "") +
1306 				"%99 = OpConstant %6 1024\n"
1307 				"%4 = OpFunction %2 None %3\n"
1308 				"%5 = OpLabel\n"
1309 				"%16 = OpLoad %12 %15\n"
1310 				"%19 = OpLoad %6 %18\n"
1311 				"%98 = OpLoad %6 %20\n"
1312 				"%21 = OpIAdd %6 %98 %99\n"
1313 				"%23 = OpCompositeConstruct %7 %19 %21 %22 %22\n"
1314 				"%25 = OpAccessChain %24 %11 %13 %16\n"
1315 				"OpStore %25 %23\n"
1316 				"%27 = OpLoad %12 %26\n"
1317 				"%29 = OpIEqual %28 %27 %13\n"
1318 				"OpSelectionMerge %31 None\n"
1319 				"OpBranchConditional %29 %30 %31\n"
1320 				"%30 = OpLabel\n"
1321 				"%39 = OpAccessChain %38 %36 %13\n"
1322 				"OpStore %39 %37\n"
1323 				"%41 = OpAccessChain %38 %36 %40\n"
1324 				"OpStore %41 %37\n"
1325 				"OpBranch %31\n"
1326 				"%31 = OpLabel\n"
1327 				"%49 = OpLoad %12 %26\n"
1328 				"%55 = OpLoad %12 %26\n"
1329 				"%57 = OpAccessChain %56 %54 %55 %13\n"
1330 				"%58 = OpLoad %42 %57\n"
1331 				"%60 = OpAccessChain %59 %48 %49 %13\n"
1332 				"OpStore %60 %58\n"
1333 				+ (*caseDef.geometryPointSizeSupported ?
1334 					"%64 = OpAccessChain %61 %54 %49 %63\n"
1335 					"%65 = OpLoad %32 %64\n"
1336 					"%66 = OpAccessChain %62 %48 %49 %63\n"
1337 					"OpStore %66 %65\n" : "") +
1338 				"OpReturn\n"
1339 				"OpFunctionEnd\n";
1340 				programCollection.spirvAsmSources.add("tesc") << tesc << buildOptionsSpr;
1341 		}
1342 
1343 		{
1344 			/*
1345 				"#version 450\n"
1346 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
1347 				"layout(isolines) in;\n"
1348 				"layout(set = 0, binding = 2, std430) buffer Output\n"
1349 				"{\n"
1350 				"  uvec4 result[];\n"
1351 				"};\n"
1352 				"\n"
1353 				"void main (void)\n"
1354 				"{\n"
1355 				"  result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID + 1024, 0, 0);\n"
1356 				"  float pixelSize = 2.0f/1024.0f;\n"
1357 				"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
1358 				#if GEOMETRY_POINT_SIZE_SUPPORTED
1359 				"  gl_PointSize = gl_in[0].gl_PointSize;\n"
1360 				#endif
1361 				"}\n";
1362 			*/
1363 
1364 			const string pointSizeCapability = (*caseDef.geometryPointSizeSupported ? "OpCapability TessellationPointSize\n" : "");
1365 
1366 			const string tese =
1367 				"; SPIR - V\n"
1368 				"; Version: 1.3\n"
1369 				"; Generator: Khronos Glslang Reference Front End; 2\n"
1370 				"; Bound: 67\n"
1371 				"; Schema: 0\n"
1372 				"OpCapability Tessellation\n"
1373 				"OpCapability GroupNonUniform\n"
1374 				+ pointSizeCapability +
1375 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1376 				"OpMemoryModel Logical GLSL450\n"
1377 				"OpEntryPoint TessellationEvaluation %4 \"main\" %15 %23 %33 %35 %48 %53\n"
1378 				"OpExecutionMode %4 Isolines\n"
1379 				"OpExecutionMode %4 SpacingEqual\n"
1380 				"OpExecutionMode %4 VertexOrderCcw\n"
1381 				"OpDecorate %8 ArrayStride 16\n"
1382 				"OpMemberDecorate %9 0 Offset 0\n"
1383 				"OpDecorate %9 BufferBlock\n"
1384 				"OpDecorate %11 DescriptorSet 0\n"
1385 				"OpDecorate %11 Binding 2\n"
1386 				"OpDecorate %15 BuiltIn PrimitiveId\n"
1387 				"OpDecorate %23 BuiltIn TessCoord\n"
1388 				"OpDecorate %33 RelaxedPrecision\n"
1389 				"OpDecorate %33 BuiltIn SubgroupSize\n"
1390 				"OpDecorate %34 RelaxedPrecision\n"
1391 				"OpDecorate %35 RelaxedPrecision\n"
1392 				"OpDecorate %35 BuiltIn SubgroupLocalInvocationId\n"
1393 				"OpDecorate %36 RelaxedPrecision\n"
1394 				"OpMemberDecorate %46 0 BuiltIn Position\n"
1395 				"OpMemberDecorate %46 1 BuiltIn PointSize\n"
1396 				"OpMemberDecorate %46 2 BuiltIn ClipDistance\n"
1397 				"OpMemberDecorate %46 3 BuiltIn CullDistance\n"
1398 				"OpDecorate %46 Block\n"
1399 				"OpMemberDecorate %49 0 BuiltIn Position\n"
1400 				"OpMemberDecorate %49 1 BuiltIn PointSize\n"
1401 				"OpMemberDecorate %49 2 BuiltIn ClipDistance\n"
1402 				"OpMemberDecorate %49 3 BuiltIn CullDistance\n"
1403 				"OpDecorate %49 Block\n"
1404 				"%2 = OpTypeVoid\n"
1405 				"%3 = OpTypeFunction %2\n"
1406 				"%6 = OpTypeInt 32 0\n"
1407 				"%7 = OpTypeVector %6 4\n"
1408 				"%8 = OpTypeRuntimeArray %7\n"
1409 				"%9 = OpTypeStruct %8\n"
1410 				"%10 = OpTypePointer Uniform %9\n"
1411 				"%11 = OpVariable %10 Uniform\n"
1412 				"%12 = OpTypeInt 32 1\n"
1413 				"%13 = OpConstant %12 0\n"
1414 				"%14 = OpTypePointer Input %12\n"
1415 				"%15 = OpVariable %14 Input\n"
1416 				"%17 = OpConstant %12 2\n"
1417 				"%20 = OpTypeFloat 32\n"
1418 				"%21 = OpTypeVector %20 3\n"
1419 				"%22 = OpTypePointer Input %21\n"
1420 				"%23 = OpVariable %22 Input\n"
1421 				"%24 = OpConstant %6 0\n"
1422 				"%25 = OpTypePointer Input %20\n"
1423 				"%28 = OpConstant %20 0.5\n"
1424 				"%32 = OpTypePointer Input %6\n"
1425 				"%33 = OpVariable %32 Input\n"
1426 				"%35 = OpVariable %32 Input\n"
1427 				"%38 = OpTypePointer Uniform %7\n"
1428 				"%40 = OpTypePointer Function %20\n"
1429 				"%42 = OpConstant %20 0.00195313\n"
1430 				"%43 = OpTypeVector %20 4\n"
1431 				"%44 = OpConstant %6 1\n"
1432 				"%45 = OpTypeArray %20 %44\n"
1433 				"%46 = OpTypeStruct %43 %20 %45 %45\n"
1434 				"%47 = OpTypePointer Output %46\n"
1435 				"%48 = OpVariable %47 Output\n"
1436 				"%49 = OpTypeStruct %43 %20 %45 %45\n"
1437 				"%50 = OpConstant %6 32\n"
1438 				"%51 = OpTypeArray %49 %50\n"
1439 				"%52 = OpTypePointer Input %51\n"
1440 				"%53 = OpVariable %52 Input\n"
1441 				"%54 = OpTypePointer Input %43\n"
1442 				"%61 = OpConstant %20 2\n"
1443 				"%65 = OpTypePointer Output %43\n"
1444 				+ (*caseDef.geometryPointSizeSupported ?
1445 					"%67 = OpTypePointer Input %20\n"
1446 					"%68 = OpTypePointer Output %20\n"
1447 					"%69 = OpConstant %12 1\n" : "") +
1448 				"%99 = OpConstant %6 1024\n"
1449 				"%4 = OpFunction %2 None %3\n"
1450 				"%5 = OpLabel\n"
1451 				"%41 = OpVariable %40 Function\n"
1452 				"%16 = OpLoad %12 %15\n"
1453 				"%18 = OpIMul %12 %16 %17\n"
1454 				"%19 = OpBitcast %6 %18\n"
1455 				"%26 = OpAccessChain %25 %23 %24\n"
1456 				"%27 = OpLoad %20 %26\n"
1457 				"%29 = OpFAdd %20 %27 %28\n"
1458 				"%30 = OpConvertFToU %6 %29\n"
1459 				"%31 = OpIAdd %6 %19 %30\n"
1460 				"%34 = OpLoad %6 %33\n"
1461 				"%98 = OpLoad %6 %35\n"
1462 				"%36 = OpIAdd %6 %98 %99\n"
1463 				"%37 = OpCompositeConstruct %7 %34 %36 %24 %24\n"
1464 				"%39 = OpAccessChain %38 %11 %13 %31\n"
1465 				"OpStore %39 %37\n"
1466 				"OpStore %41 %42\n"
1467 				"%55 = OpAccessChain %54 %53 %13 %13\n"
1468 				"%56 = OpLoad %43 %55\n"
1469 				"%57 = OpAccessChain %25 %23 %24\n"
1470 				"%58 = OpLoad %20 %57\n"
1471 				"%59 = OpLoad %20 %41\n"
1472 				"%60 = OpFMul %20 %58 %59\n"
1473 				"%62 = OpFDiv %20 %60 %61\n"
1474 				"%63 = OpCompositeConstruct %43 %62 %62 %62 %62\n"
1475 				"%64 = OpFAdd %43 %56 %63\n"
1476 				"%66 = OpAccessChain %65 %48 %13\n"
1477 				"OpStore %66 %64\n"
1478 				+ (*caseDef.geometryPointSizeSupported ?
1479 					"%70 = OpAccessChain %67 %53 %13 %69\n"
1480 					"%71 = OpLoad %20 %70\n"
1481 					"%72 = OpAccessChain %68 %48 %69\n"
1482 					"OpStore %72 %71\n" : "") +
1483 				"OpReturn\n"
1484 				"OpFunctionEnd\n";
1485 				programCollection.spirvAsmSources.add("tese") << tese << buildOptionsSpr;
1486 		}
1487 
1488 		{
1489 			/*
1490 				"#version 450\n"
1491 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
1492 				"// Note: ${TOPOLOGY} variable is substituted manually at SPIR-V ASM level"
1493 				"layout(${TOPOLOGY}) in;\n"
1494 				"layout(points, max_vertices = 1) out;\n"
1495 				"layout(set = 0, binding = 3, std430) buffer Output\n"
1496 				"{\n"
1497 				"  uvec4 result[];\n"
1498 				"};\n"
1499 				"\n"
1500 				"void main (void)\n"
1501 				"{\n"
1502 				"  result[gl_PrimitiveIDIn] = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID + 1024, 0, 0);\n"
1503 				"  gl_Position = gl_in[0].gl_Position;\n"
1504 				#if GEOMETRY_POINT_SIZE_SUPPORTED
1505 				"  gl_PointSize = gl_in[0].gl_PointSize;\n"
1506 				#endif
1507 				"  EmitVertex();\n"
1508 				"  EndPrimitive();\n"
1509 				"}\n";
1510 			*/
1511 
1512 			const string pointSizeCapability = (*caseDef.geometryPointSizeSupported ? "OpCapability GeometryPointSize\n" : "");
1513 
1514 			const string geometry =
1515 			"; SPIR-V\n"
1516 			"; Version: 1.3\n"
1517 			"; Generator: Khronos Glslang Reference Front End; 1\n"
1518 			"; Bound: 42\n"
1519 			"; Schema: 0\n"
1520 			"OpCapability Geometry\n"
1521 			"OpCapability GroupNonUniform\n"
1522 			+ pointSizeCapability +
1523 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1524 			"OpMemoryModel Logical GLSL450\n"
1525 			"OpEntryPoint Geometry %4 \"main\" %15 %18 %20 %32 %36\n"
1526 			"OpExecutionMode %4 ${TOPOLOGY}\n"
1527 			"OpExecutionMode %4 Invocations 1\n"
1528 			"OpExecutionMode %4 OutputPoints\n"
1529 			"OpExecutionMode %4 OutputVertices 1\n"
1530 			"OpDecorate %8 ArrayStride 16\n"
1531 			"OpMemberDecorate %9 0 Offset 0\n"
1532 			"OpDecorate %9 BufferBlock\n"
1533 			"OpDecorate %11 DescriptorSet 0\n"
1534 			"OpDecorate %11 Binding 3\n"
1535 			"OpDecorate %15 BuiltIn PrimitiveId\n"
1536 			"OpDecorate %18 RelaxedPrecision\n"
1537 			"OpDecorate %18 BuiltIn SubgroupSize\n"
1538 			"OpDecorate %19 RelaxedPrecision\n"
1539 			"OpDecorate %20 RelaxedPrecision\n"
1540 			"OpDecorate %20 BuiltIn SubgroupLocalInvocationId\n"
1541 			"OpDecorate %21 RelaxedPrecision\n"
1542 			"OpMemberDecorate %30 0 BuiltIn Position\n"
1543 			"OpMemberDecorate %30 1 BuiltIn PointSize\n"
1544 			"OpMemberDecorate %30 2 BuiltIn ClipDistance\n"
1545 			"OpMemberDecorate %30 3 BuiltIn CullDistance\n"
1546 			"OpDecorate %30 Block\n"
1547 			"OpMemberDecorate %33 0 BuiltIn Position\n"
1548 			"OpMemberDecorate %33 1 BuiltIn PointSize\n"
1549 			"OpMemberDecorate %33 2 BuiltIn ClipDistance\n"
1550 			"OpMemberDecorate %33 3 BuiltIn CullDistance\n"
1551 			"OpDecorate %33 Block\n"
1552 			"%2 = OpTypeVoid\n"
1553 			"%3 = OpTypeFunction %2\n"
1554 			"%6 = OpTypeInt 32 0\n"
1555 			"%7 = OpTypeVector %6 4\n"
1556 			"%8 = OpTypeRuntimeArray %7\n"
1557 			"%9 = OpTypeStruct %8\n"
1558 			"%10 = OpTypePointer Uniform %9\n"
1559 			"%11 = OpVariable %10 Uniform\n"
1560 			"%12 = OpTypeInt 32 1\n"
1561 			"%13 = OpConstant %12 0\n"
1562 			"%14 = OpTypePointer Input %12\n"
1563 			"%15 = OpVariable %14 Input\n"
1564 			"%17 = OpTypePointer Input %6\n"
1565 			"%18 = OpVariable %17 Input\n"
1566 			"%20 = OpVariable %17 Input\n"
1567 			"%22 = OpConstant %6 0\n"
1568 			"%24 = OpTypePointer Uniform %7\n"
1569 			"%26 = OpTypeFloat 32\n"
1570 			"%27 = OpTypeVector %26 4\n"
1571 			"%28 = OpConstant %6 1\n"
1572 			"%29 = OpTypeArray %26 %28\n"
1573 			"%30 = OpTypeStruct %27 %26 %29 %29\n"
1574 			"%31 = OpTypePointer Output %30\n"
1575 			"%32 = OpVariable %31 Output\n"
1576 			"%33 = OpTypeStruct %27 %26 %29 %29\n"
1577 			"%34 = OpTypeArray %33 %28\n"
1578 			"%35 = OpTypePointer Input %34\n"
1579 			"%36 = OpVariable %35 Input\n"
1580 			"%37 = OpTypePointer Input %27\n"
1581 			"%40 = OpTypePointer Output %27\n"
1582 			+ (*caseDef.geometryPointSizeSupported ?
1583 				"%42 = OpTypePointer Input %26\n"
1584 				"%43 = OpTypePointer Output %26\n"
1585 				"%44 = OpConstant %12 1\n" : "") +
1586 			"%99 = OpConstant %6 1024\n"
1587 			"%4 = OpFunction %2 None %3\n"
1588 			"%5 = OpLabel\n"
1589 			"%16 = OpLoad %12 %15\n"
1590 			"%19 = OpLoad %6 %18\n"
1591 			"%98 = OpLoad %6 %20\n"
1592 			"%21 = OpIAdd %6 %98 %99\n"
1593 			"%23 = OpCompositeConstruct %7 %19 %21 %22 %22\n"
1594 			"%25 = OpAccessChain %24 %11 %13 %16\n"
1595 			"OpStore %25 %23\n"
1596 			"%38 = OpAccessChain %37 %36 %13 %13\n"
1597 			"%39 = OpLoad %27 %38\n"
1598 			"%41 = OpAccessChain %40 %32 %13\n"
1599 			"OpStore %41 %39\n"
1600 			+ (*caseDef.geometryPointSizeSupported ?
1601 				"%45 = OpAccessChain %42 %36 %13 %44\n"
1602 				"%46 = OpLoad %26 %45\n"
1603 				"%47 = OpAccessChain %43 %32 %44\n"
1604 				"OpStore %47 %46\n" : "") +
1605 			"OpEmitVertex\n"
1606 			"OpEndPrimitive\n"
1607 			"OpReturn\n"
1608 			"OpFunctionEnd\n";
1609 
1610 			addGeometryShadersFromTemplate(geometry, buildOptionsSpr, programCollection.spirvAsmSources);
1611 		}
1612 
1613 		{
1614 			/*
1615 				"#version 450\n"
1616 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
1617 				"layout(location = 0) out uvec4 data;\n"
1618 				"void main (void)\n"
1619 				"{\n"
1620 				"  data = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID + 1024, 0, 0);\n"
1621 				"}\n";
1622 			*/
1623 			const string fragment =
1624 			"; SPIR-V\n"
1625 			"; Version: 1.3\n"
1626 			"; Generator: Khronos Glslang Reference Front End; 1\n"
1627 			"; Bound: 17\n"
1628 			"; Schema: 0\n"
1629 			"OpCapability Shader\n"
1630 			"OpCapability GroupNonUniform\n"
1631 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1632 			"OpMemoryModel Logical GLSL450\n"
1633 			"OpEntryPoint Fragment %4 \"main\" %9 %11 %13\n"
1634 			"OpExecutionMode %4 OriginUpperLeft\n"
1635 			"OpDecorate %9 Location 0\n"
1636 			"OpDecorate %11 RelaxedPrecision\n"
1637 			"OpDecorate %11 Flat\n"
1638 			"OpDecorate %11 BuiltIn SubgroupSize\n"
1639 			"OpDecorate %12 RelaxedPrecision\n"
1640 			"OpDecorate %13 RelaxedPrecision\n"
1641 			"OpDecorate %13 Flat\n"
1642 			"OpDecorate %13 BuiltIn SubgroupLocalInvocationId\n"
1643 			"OpDecorate %14 RelaxedPrecision\n"
1644 			"%2 = OpTypeVoid\n"
1645 			"%3 = OpTypeFunction %2\n"
1646 			"%6 = OpTypeInt 32 0\n"
1647 			"%7 = OpTypeVector %6 4\n"
1648 			"%8 = OpTypePointer Output %7\n"
1649 			"%9 = OpVariable %8 Output\n"
1650 			"%10 = OpTypePointer Input %6\n"
1651 			"%11 = OpVariable %10 Input\n"
1652 			"%13 = OpVariable %10 Input\n"
1653 			"%15 = OpConstant %6 0\n"
1654 			"%99 = OpConstant %6 1024\n"
1655 			"%4 = OpFunction %2 None %3\n"
1656 			"%5 = OpLabel\n"
1657 			"%12 = OpLoad %6 %11\n"
1658 			"%98 = OpLoad %6 %13\n"
1659 			"%14 = OpIAdd %6 %98 %99\n"
1660 			"%16 = OpCompositeConstruct %7 %12 %14 %15 %15\n"
1661 			"OpStore %9 %16\n"
1662 			"OpReturn\n"
1663 			"OpFunctionEnd\n";
1664 
1665 			programCollection.spirvAsmSources.add("fragment") << fragment << buildOptionsSpr;
1666 		}
1667 
1668 		subgroups::addNoSubgroupShader(programCollection);
1669 	}
1670 #ifndef CTS_USES_VULKANSC
1671 	else if (isAllRayTracingStages(caseDef.shaderStage))
1672 	{
1673 		const ShaderBuildOptions	buildOptions		(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, 0u, true);
1674 		const string				extHeader			= "#extension GL_KHR_shader_subgroup_basic : require\n";
1675 		const string				tempRes				= "  uvec4 tempRes;\n";
1676 		const string				testSrc				= "  tempRes = uvec4(gl_SubgroupSize, gl_SubgroupInvocationID + 1024, 0, 0);\n";
1677 		const vector<string>		headDeclarations	= getPerStageHeadDeclarations(caseDef);
1678 
1679 		subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, VK_FORMAT_R32G32B32A32_UINT, false, extHeader, testSrc, "", headDeclarations, false, tempRes);
1680 	}
1681 #endif // CTS_USES_VULKANSC
1682 	else
1683 		TCU_THROW(InternalError, "Unknown stage");
1684 }
1685 
supportedCheck(Context & context,CaseDefinition caseDef)1686 void supportedCheck (Context& context, CaseDefinition caseDef)
1687 {
1688 	if (!subgroups::isSubgroupSupported(context))
1689 		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
1690 
1691 	if (caseDef.requiredSubgroupSize)
1692 	{
1693 		context.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
1694 
1695 #ifndef CTS_USES_VULKANSC
1696 		const VkPhysicalDeviceSubgroupSizeControlFeatures&		subgroupSizeControlFeatures		= context.getSubgroupSizeControlFeatures();
1697 		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties	= context.getSubgroupSizeControlProperties();
1698 #else
1699 		const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT&	subgroupSizeControlFeatures		= context.getSubgroupSizeControlFeaturesEXT();
1700 		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties	= context.getSubgroupSizeControlPropertiesEXT();
1701 #endif // CTS_USES_VULKANSC
1702 
1703 		if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
1704 			TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes nor required subgroup size");
1705 
1706 		if (subgroupSizeControlFeatures.computeFullSubgroups == DE_FALSE)
1707 			TCU_THROW(NotSupportedError, "Device does not support full subgroups in compute shaders");
1708 
1709 		if ((subgroupSizeControlProperties.requiredSubgroupSizeStages & caseDef.shaderStage) != caseDef.shaderStage)
1710 			TCU_THROW(NotSupportedError, "Required subgroup size is not supported for shader stage");
1711 	}
1712 
1713 	*caseDef.geometryPointSizeSupported = subgroups::isTessellationAndGeometryPointSizeSupported(context);
1714 
1715 #ifndef CTS_USES_VULKANSC
1716 	if (isAllRayTracingStages(caseDef.shaderStage))
1717 	{
1718 		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
1719 	}
1720 	else if (isAllMeshShadingStages(caseDef.shaderStage))
1721 	{
1722 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
1723 		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1724 
1725 		if ((caseDef.shaderStage & VK_SHADER_STAGE_TASK_BIT_EXT) != 0u)
1726 		{
1727 			const auto& features = context.getMeshShaderFeaturesEXT();
1728 			if (!features.taskShader)
1729 				TCU_THROW(NotSupportedError, "Task shaders not supported");
1730 		}
1731 	}
1732 #endif // CTS_USES_VULKANSC
1733 
1734 	vkt::subgroups::supportedCheckShader(context, caseDef.shaderStage);
1735 }
1736 
noSSBOtest(Context & context,const CaseDefinition caseDef)1737 TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
1738 {
1739 	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
1740 	{
1741 		switch (caseDef.testType)
1742 		{
1743 			case TEST_TYPE_SUBGROUP_SIZE:			return makeVertexFrameBufferTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupSize);
1744 			case TEST_TYPE_SUBGROUP_INVOCATION_ID:	return makeVertexFrameBufferTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupInvocationID);
1745 			default:								TCU_THROW(InternalError, "Unknown builtin");
1746 		}
1747 	}
1748 	else if ((VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) & caseDef.shaderStage)
1749 	{
1750 		switch (caseDef.testType)
1751 		{
1752 			case TEST_TYPE_SUBGROUP_SIZE:			return makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupSize);
1753 			case TEST_TYPE_SUBGROUP_INVOCATION_ID:	return makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupInvocationID);
1754 			default:								TCU_THROW(InternalError, "Unknown builtin");
1755 		}
1756 	}
1757 	else if (VK_SHADER_STAGE_GEOMETRY_BIT & caseDef.shaderStage)
1758 	{
1759 		switch (caseDef.testType)
1760 		{
1761 			case TEST_TYPE_SUBGROUP_SIZE:			return makeGeometryFrameBufferTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupSize);
1762 			case TEST_TYPE_SUBGROUP_INVOCATION_ID:	return makeGeometryFrameBufferTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupInvocationID);
1763 			default:								TCU_THROW(InternalError, "Unknown builtin");
1764 		}
1765 	}
1766 	else
1767 	{
1768 		TCU_THROW(InternalError, "Unhandled shader stage");
1769 	}
1770 }
1771 
test(Context & context,const CaseDefinition caseDef)1772 TestStatus test (Context& context, const CaseDefinition caseDef)
1773 {
1774 	const bool isCompute	= isAllComputeStages(caseDef.shaderStage);
1775 #ifndef CTS_USES_VULKANSC
1776 	const bool isMesh		= isAllMeshShadingStages(caseDef.shaderStage);
1777 #else
1778 	const bool isMesh		= false;
1779 #endif // CTS_USES_VULKANSC
1780 	DE_ASSERT(!(isCompute && isMesh));
1781 
1782 	if (isCompute || isMesh)
1783 	{
1784 #ifndef CTS_USES_VULKANSC
1785 		const VkPhysicalDeviceSubgroupSizeControlProperties&	subgroupSizeControlProperties = context.getSubgroupSizeControlProperties();
1786 #else
1787 		const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT&	subgroupSizeControlProperties = context.getSubgroupSizeControlPropertiesEXT();
1788 #endif // CTS_USES_VULKANSC
1789 		TestLog&												log								= context.getTestContext().getLog();
1790 
1791 		switch (caseDef.testType)
1792 		{
1793 			case TEST_TYPE_SUBGROUP_SIZE:
1794 			{
1795 				if (caseDef.requiredSubgroupSize == DE_FALSE)
1796 				{
1797 					if (isCompute)
1798 						return makeComputeTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupSize);
1799 					else
1800 						return makeMeshTest(context, VK_FORMAT_R32G32B32A32_UINT, nullptr, 0, nullptr, checkComputeSubgroupSize);
1801 				}
1802 
1803 				log << TestLog::Message << "Testing required subgroup size range [" <<  subgroupSizeControlProperties.minSubgroupSize << ", "
1804 					<< subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
1805 
1806 				// According to the spec, requiredSubgroupSize must be a power-of-two integer.
1807 				for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
1808 				{
1809 					TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
1810 
1811 					if (isCompute)
1812 						result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupSize, size);
1813 					else
1814 						result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, nullptr, 0, nullptr, checkComputeSubgroupSize, size);
1815 
1816 					if (result.getCode() != QP_TEST_RESULT_PASS)
1817 					{
1818 						log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
1819 
1820 						return result;
1821 					}
1822 				}
1823 
1824 				return TestStatus::pass("OK");
1825 			}
1826 
1827 			case TEST_TYPE_SUBGROUP_INVOCATION_ID:
1828 			{
1829 				if (caseDef.requiredSubgroupSize == DE_FALSE)
1830 				{
1831 					if (isCompute)
1832 						return makeComputeTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupInvocationID);
1833 					else
1834 						return makeMeshTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupInvocationID);
1835 				}
1836 
1837 				log << TestLog::Message << "Testing required subgroup size range [" <<  subgroupSizeControlProperties.minSubgroupSize << ", "
1838 					<< subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
1839 
1840 				// According to the spec, requiredSubgroupSize must be a power-of-two integer.
1841 				for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
1842 				{
1843 					TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
1844 
1845 					if (isCompute)
1846 						result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupInvocationID, size);
1847 					else
1848 						result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupInvocationID, size);
1849 
1850 					if (result.getCode() != QP_TEST_RESULT_PASS)
1851 					{
1852 						log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
1853 
1854 						return result;
1855 					}
1856 				}
1857 
1858 				return TestStatus::pass("OK");
1859 			}
1860 
1861 			case TEST_TYPE_SUBGROUP_NUM_SUBGROUPS:
1862 			{
1863 				if (caseDef.requiredSubgroupSize == DE_FALSE)
1864 				{
1865 					if (isCompute)
1866 						return makeComputeTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkComputeNumSubgroups);
1867 					else
1868 						return  makeMeshTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkComputeNumSubgroups);
1869 				}
1870 
1871 				log << TestLog::Message << "Testing required subgroup size range [" <<  subgroupSizeControlProperties.minSubgroupSize << ", "
1872 					<< subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
1873 
1874 				// According to the spec, requiredSubgroupSize must be a power-of-two integer.
1875 				for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
1876 				{
1877 					TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
1878 
1879 					if (isCompute)
1880 						result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeNumSubgroups, size);
1881 					else
1882 						result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeNumSubgroups, size);
1883 
1884 					if (result.getCode() != QP_TEST_RESULT_PASS)
1885 					{
1886 						log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
1887 
1888 						return result;
1889 					}
1890 				}
1891 
1892 				return TestStatus::pass("OK");
1893 			}
1894 
1895 			case TEST_TYPE_SUBGROUP_NUM_SUBGROUP_ID:
1896 			{
1897 				if (caseDef.requiredSubgroupSize == DE_FALSE)
1898 				{
1899 					if (isCompute)
1900 						return makeComputeTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupID);
1901 					else
1902 						return makeMeshTest(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupID);
1903 				}
1904 
1905 				log << TestLog::Message << "Testing required subgroup size range [" <<  subgroupSizeControlProperties.minSubgroupSize << ", "
1906 					<< subgroupSizeControlProperties.maxSubgroupSize << "]" << TestLog::EndMessage;
1907 
1908 				// According to the spec, requiredSubgroupSize must be a power-of-two integer.
1909 				for (deUint32 size = subgroupSizeControlProperties.minSubgroupSize; size <= subgroupSizeControlProperties.maxSubgroupSize; size *= 2)
1910 				{
1911 					TestStatus result (QP_TEST_RESULT_INTERNAL_ERROR, "Internal Error");
1912 
1913 					if (isCompute)
1914 						result = subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupID, size);
1915 					else
1916 						result = subgroups::makeMeshTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, DE_NULL, checkComputeSubgroupID, size);
1917 
1918 					if (result.getCode() != QP_TEST_RESULT_PASS)
1919 					{
1920 						log << TestLog::Message << "subgroupSize " << size << " failed" << TestLog::EndMessage;
1921 
1922 						return result;
1923 					}
1924 				}
1925 
1926 				return TestStatus::pass("OK");
1927 			}
1928 
1929 			default:
1930 				TCU_THROW(InternalError, "Unknown builtin");
1931 		}
1932 	}
1933 	else if (isAllGraphicsStages(caseDef.shaderStage))
1934 	{
1935 		const VkShaderStageFlags	stages	= subgroups::getPossibleGraphicsSubgroupStages(context, caseDef.shaderStage);
1936 
1937 		switch (caseDef.testType)
1938 		{
1939 			case TEST_TYPE_SUBGROUP_SIZE:			return subgroups::allStages(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupSize, stages);
1940 			case TEST_TYPE_SUBGROUP_INVOCATION_ID:	return subgroups::allStages(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupInvocationID, stages);
1941 			default:								TCU_THROW(InternalError, "Unknown builtin");
1942 		}
1943 	}
1944 #ifndef CTS_USES_VULKANSC
1945 	else if (isAllRayTracingStages(caseDef.shaderStage))
1946 	{
1947 		const VkShaderStageFlags	stages	= subgroups::getPossibleRayTracingSubgroupStages(context, caseDef.shaderStage);
1948 
1949 		switch (caseDef.testType)
1950 		{
1951 			case TEST_TYPE_SUBGROUP_SIZE:			return subgroups::allRayTracingStages(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupSize, stages);
1952 			case TEST_TYPE_SUBGROUP_INVOCATION_ID:	return subgroups::allRayTracingStages(context, VK_FORMAT_R32G32B32A32_UINT, DE_NULL, 0, DE_NULL, checkVertexPipelineStagesSubgroupInvocationID, stages);
1953 			default:								TCU_THROW(InternalError, "Unknown builtin");
1954 		}
1955 	}
1956 #endif // CTS_USES_VULKANSC
1957 	else
1958 		TCU_THROW(InternalError, "Unknown stage or invalid stage set");
1959 }
1960 
createSubgroupsBuiltinVarTests(TestContext & testCtx)1961 TestCaseGroup* createSubgroupsBuiltinVarTests (TestContext& testCtx)
1962 {
1963 	de::MovePtr<TestCaseGroup>	group						(new TestCaseGroup(testCtx, "builtin_var",	"Subgroup builtin variable tests"));
1964 	de::MovePtr<TestCaseGroup>	graphicGroup				(new TestCaseGroup(testCtx, "graphics",		"Subgroup builtin variable tests: graphics"));
1965 	de::MovePtr<TestCaseGroup>	computeGroup				(new TestCaseGroup(testCtx, "compute",		"Subgroup builtin variable tests: compute"));
1966 	de::MovePtr<TestCaseGroup>	framebufferGroup			(new TestCaseGroup(testCtx, "framebuffer",	"Subgroup builtin variable tests: framebuffer"));
1967 #ifndef CTS_USES_VULKANSC
1968 	de::MovePtr<TestCaseGroup>	raytracingGroup				(new TestCaseGroup(testCtx, "ray_tracing",	"Subgroup builtin variable tests: ray tracing"));
1969 	de::MovePtr<TestCaseGroup>	meshGroup					(new TestCaseGroup(testCtx, "mesh",			"Subgroup builtin variable tests: mesh shading"));
1970 #endif // CTS_USES_VULKANSC
1971 	const TestType				allStagesBuiltinVars[]		=
1972 	{
1973 		TEST_TYPE_SUBGROUP_SIZE,
1974 		TEST_TYPE_SUBGROUP_INVOCATION_ID,
1975 	};
1976 	const TestType				computeOnlyBuiltinVars[]	=
1977 	{
1978 		TEST_TYPE_SUBGROUP_NUM_SUBGROUPS,
1979 		TEST_TYPE_SUBGROUP_NUM_SUBGROUP_ID,
1980 	};
1981 	const VkShaderStageFlags	fbStages[]					=
1982 	{
1983 		VK_SHADER_STAGE_VERTEX_BIT,
1984 		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1985 		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1986 		VK_SHADER_STAGE_GEOMETRY_BIT,
1987 	};
1988 #ifndef CTS_USES_VULKANSC
1989 	const VkShaderStageFlags	meshStages[]				=
1990 	{
1991 		VK_SHADER_STAGE_MESH_BIT_EXT,
1992 		VK_SHADER_STAGE_TASK_BIT_EXT,
1993 	};
1994 #endif // CTS_USES_VULKANSC
1995 	const deBool				boolValues[]				=
1996 	{
1997 		DE_FALSE,
1998 		DE_TRUE
1999 	};
2000 
2001 	for (int a = 0; a < DE_LENGTH_OF_ARRAY(allStagesBuiltinVars); ++a)
2002 	{
2003 		const TestType	testType	= allStagesBuiltinVars[a];
2004 		const string	varLower	= de::toLower(getTestName(testType));
2005 
2006 		{
2007 			const CaseDefinition	caseDef	=
2008 			{
2009 				testType,							//  TestType			testType;
2010 				VK_SHADER_STAGE_ALL_GRAPHICS,		//  VkShaderStageFlags	shaderStage;
2011 				de::SharedPtr<bool>(new bool),		//  de::SharedPtr<bool>	geometryPointSizeSupported;
2012 				DE_FALSE							//  deBool				requiredSubgroupSize;
2013 			};
2014 
2015 			addFunctionCaseWithPrograms(graphicGroup.get(), varLower, "", supportedCheck, initPrograms, test, caseDef);
2016 		}
2017 
2018 #ifndef CTS_USES_VULKANSC
2019 		{
2020 			const CaseDefinition	caseDef	=
2021 			{
2022 				testType,							//  TestType			testType;
2023 				SHADER_STAGE_ALL_RAY_TRACING,		//  VkShaderStageFlags	shaderStage;
2024 				de::SharedPtr<bool>(new bool),		//  de::SharedPtr<bool>	geometryPointSizeSupported;
2025 				DE_FALSE							//  deBool				requiredSubgroupSize;
2026 			};
2027 
2028 			addFunctionCaseWithPrograms(raytracingGroup.get(), varLower, "", supportedCheck, initPrograms, test, caseDef);
2029 		}
2030 #endif // CTS_USES_VULKANSC
2031 
2032 		for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
2033 		{
2034 			const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
2035 			const string			testNameSuffix			= requiredSubgroupSize ? "_requiredsubgroupsize" : "";
2036 			const CaseDefinition	caseDef					=
2037 			{
2038 				testType,							//  TestType			testType;
2039 				VK_SHADER_STAGE_COMPUTE_BIT,		//  VkShaderStageFlags	shaderStage;
2040 				de::SharedPtr<bool>(new bool),		//  de::SharedPtr<bool>	geometryPointSizeSupported;
2041 				requiredSubgroupSize				//  deBool				requiredSubgroupSize;
2042 			};
2043 			const string			testName				= varLower + "_" + getShaderStageName(caseDef.shaderStage) + testNameSuffix;
2044 
2045 			addFunctionCaseWithPrograms(computeGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
2046 		}
2047 
2048 #ifndef CTS_USES_VULKANSC
2049 		for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
2050 		{
2051 			for (const auto& stage : meshStages)
2052 			{
2053 				const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
2054 				const string			testNameSuffix			= requiredSubgroupSize ? "_requiredsubgroupsize" : "";
2055 				const CaseDefinition	caseDef					=
2056 				{
2057 					testType,							//  TestType			testType;
2058 					stage,								//  VkShaderStageFlags	shaderStage;
2059 					de::SharedPtr<bool>(new bool),		//  de::SharedPtr<bool>	geometryPointSizeSupported;
2060 					requiredSubgroupSize				//  deBool				requiredSubgroupSize;
2061 				};
2062 				const string			testName				= varLower + "_" + getShaderStageName(caseDef.shaderStage) + testNameSuffix;
2063 
2064 				addFunctionCaseWithPrograms(meshGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
2065 			}
2066 		}
2067 #endif // CTS_USES_VULKANSC
2068 
2069 		for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(fbStages); ++stageIndex)
2070 		{
2071 			const CaseDefinition	caseDef		=
2072 			{
2073 				testType,							//  TestType			testType;
2074 				fbStages[stageIndex],				//  VkShaderStageFlags	shaderStage;
2075 				de::SharedPtr<bool>(new bool),		//  de::SharedPtr<bool>	geometryPointSizeSupported;
2076 				DE_FALSE							//  deBool				requiredSubgroupSize;
2077 			};
2078 			const string			testName	= varLower + "_" + getShaderStageName(caseDef.shaderStage);
2079 
2080 			addFunctionCaseWithPrograms(framebufferGroup.get(), testName, "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
2081 		}
2082 	}
2083 
2084 	for (int a = 0; a < DE_LENGTH_OF_ARRAY(computeOnlyBuiltinVars); ++a)
2085 	{
2086 		const TestType		testType	= computeOnlyBuiltinVars[a];
2087 		const string		varLower	= de::toLower(getTestName(testType));
2088 
2089 		for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
2090 		{
2091 			const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
2092 			const string			testNameSuffix			= requiredSubgroupSize ? "_requiredsubgroupsize" : "";
2093 			const CaseDefinition	caseDef					=
2094 			{
2095 				testType,							//  TestType			testType;
2096 				VK_SHADER_STAGE_COMPUTE_BIT,		//  VkShaderStageFlags	shaderStage;
2097 				de::SharedPtr<bool>(new bool),		//  de::SharedPtr<bool>	geometryPointSizeSupported;
2098 				requiredSubgroupSize				//  deBool				requiredSubgroupSize;
2099 			};
2100 			const string			testName				= varLower + testNameSuffix;
2101 
2102 			addFunctionCaseWithPrograms(computeGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
2103 		}
2104 
2105 #ifndef CTS_USES_VULKANSC
2106 		for (size_t groupSizeNdx = 0; groupSizeNdx < DE_LENGTH_OF_ARRAY(boolValues); ++groupSizeNdx)
2107 		{
2108 			for (const auto& stage : meshStages)
2109 			{
2110 				const deBool			requiredSubgroupSize	= boolValues[groupSizeNdx];
2111 				const string			testNameSuffix			= requiredSubgroupSize ? "_requiredsubgroupsize" : "";
2112 				const CaseDefinition	caseDef					=
2113 				{
2114 					testType,							//  TestType			testType;
2115 					stage,								//  VkShaderStageFlags	shaderStage;
2116 					de::SharedPtr<bool>(new bool),		//  de::SharedPtr<bool>	geometryPointSizeSupported;
2117 					requiredSubgroupSize				//  deBool				requiredSubgroupSize;
2118 				};
2119 				const string			testName				= varLower + testNameSuffix + "_" + getShaderStageName(stage);
2120 
2121 				addFunctionCaseWithPrograms(meshGroup.get(), testName, "", supportedCheck, initPrograms, test, caseDef);
2122 			}
2123 		}
2124 #endif // CTS_USES_VULKANSC
2125 	}
2126 
2127 	group->addChild(graphicGroup.release());
2128 	group->addChild(computeGroup.release());
2129 #ifndef CTS_USES_VULKANSC
2130 	group->addChild(raytracingGroup.release());
2131 	group->addChild(meshGroup.release());
2132 #endif // CTS_USES_VULKANSC
2133 	group->addChild(framebufferGroup.release());
2134 
2135 	return group.release();
2136 }
2137 
2138 } // subgroups
2139 } // vkt
2140