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