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 "vktSubgroupsBasicTests.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 using namespace vkt;
35 
36 namespace
37 {
38 static const deUint32			ELECTED_VALUE		= 42u;
39 static const deUint32			UNELECTED_VALUE		= 13u;
40 static const vk::VkDeviceSize	SHADER_BUFFER_SIZE	= 4096ull; // min(maxUniformBufferRange, maxImageDimension1D)
41 
_checkFragmentSubgroupBarriersNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32 height,bool withImage)42 static bool _checkFragmentSubgroupBarriersNoSSBO(std::vector<const void*> datas,
43 		deUint32 width, deUint32 height, bool withImage)
44 {
45 	const float* const	resultData	= reinterpret_cast<const float*>(datas[0]);
46 
47 	for (deUint32 x = 0u; x < width; ++x)
48 	{
49 		for (deUint32 y = 0u; y < height; ++y)
50 		{
51 			const deUint32 ndx = (x * height + y) * 4u;
52 			if (!withImage && 0.0f == resultData[ndx])
53 			{
54 				return false;
55 			}
56 			else if (1.0f == resultData[ndx +2])
57 			{
58 				if(resultData[ndx] != resultData[ndx +1])
59 				{
60 					return false;
61 				}
62 			}
63 			else if (resultData[ndx] != resultData[ndx +3])
64 			{
65 				return false;
66 			}
67 		}
68 	}
69 
70 	return true;
71 }
72 
checkFragmentSubgroupBarriersNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32 height,deUint32)73 static bool checkFragmentSubgroupBarriersNoSSBO(std::vector<const void*> datas,
74 		deUint32 width, deUint32 height, deUint32)
75 {
76 	return _checkFragmentSubgroupBarriersNoSSBO(datas, width, height, false);
77 }
78 
checkFragmentSubgroupBarriersWithImageNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32 height,deUint32)79 static bool checkFragmentSubgroupBarriersWithImageNoSSBO(std::vector<const void*> datas,
80 		deUint32 width, deUint32 height, deUint32)
81 {
82 	return _checkFragmentSubgroupBarriersNoSSBO(datas, width, height, true);
83 }
84 
checkVertexPipelineStagesSubgroupElectNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32)85 static bool checkVertexPipelineStagesSubgroupElectNoSSBO(std::vector<const void*> datas,
86 		deUint32 width, deUint32)
87 {
88 	const float* const	resultData			= reinterpret_cast<const float*>(datas[0]);
89 	float				poisonValuesFound	= 0.0f;
90 	float				numSubgroupsUsed	= 0.0f;
91 
92 	for (deUint32 x = 0; x < width; ++x)
93 	{
94 		deUint32 val = static_cast<deUint32>(resultData[x * 2]);
95 		numSubgroupsUsed += resultData[x * 2 + 1];
96 
97 		switch (val)
98 		{
99 			default:
100 				// some garbage value was found!
101 				return false;
102 			case UNELECTED_VALUE:
103 				break;
104 			case ELECTED_VALUE:
105 				poisonValuesFound += 1.0f;
106 				break;
107 		}
108 	}
109 	return numSubgroupsUsed == poisonValuesFound;
110 }
111 
checkVertexPipelineStagesSubgroupElect(std::vector<const void * > datas,deUint32 width,deUint32)112 static bool checkVertexPipelineStagesSubgroupElect(std::vector<const void*> datas,
113 		deUint32 width, deUint32)
114 {
115 	const deUint32* const resultData =
116 		reinterpret_cast<const deUint32*>(datas[0]);
117 	deUint32 poisonValuesFound = 0;
118 
119 	for (deUint32 x = 0; x < width; ++x)
120 	{
121 		deUint32 val = resultData[x];
122 
123 		switch (val)
124 		{
125 			default:
126 				// some garbage value was found!
127 				return false;
128 			case UNELECTED_VALUE:
129 				break;
130 			case ELECTED_VALUE:
131 				poisonValuesFound++;
132 				break;
133 		}
134 	}
135 
136 	// we used an atomicly incremented counter to note how many subgroups we used for the vertex shader
137 	const deUint32 numSubgroupsUsed =
138 		*reinterpret_cast<const deUint32*>(datas[1]);
139 
140 	return numSubgroupsUsed == poisonValuesFound;
141 }
142 
checkVertexPipelineStagesSubgroupBarriers(std::vector<const void * > datas,deUint32 width,deUint32)143 static bool checkVertexPipelineStagesSubgroupBarriers(std::vector<const void*> datas,
144 		deUint32 width, deUint32)
145 {
146 	const deUint32* const resultData = reinterpret_cast<const deUint32*>(datas[0]);
147 
148 	// We used this SSBO to generate our unique value!
149 	const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[3]);
150 
151 	for (deUint32 x = 0; x < width; ++x)
152 	{
153 		deUint32 val = resultData[x];
154 
155 		if (val != ref)
156 			return false;
157 	}
158 
159 	return true;
160 }
161 
_checkVertexPipelineStagesSubgroupBarriersNoSSBO(std::vector<const void * > datas,deUint32 width,bool withImage)162 static bool _checkVertexPipelineStagesSubgroupBarriersNoSSBO(std::vector<const void*> datas,
163 		deUint32 width, bool withImage)
164 {
165 	const float* const	resultData	= reinterpret_cast<const float*>(datas[0]);
166 
167 	for (deUint32 x = 0u; x < width; ++x)
168 	{
169 		const deUint32 ndx = x*4u;
170 		if (!withImage && 0.0f == resultData[ndx])
171 		{
172 			return false;
173 		}
174 		else if (1.0f == resultData[ndx +2])
175 		{
176 			if(resultData[ndx] != resultData[ndx +1])
177 				return false;
178 		}
179 		else if (resultData[ndx] != resultData[ndx +3])
180 		{
181 			return false;
182 		}
183 	}
184 	return true;
185 }
186 
checkVertexPipelineStagesSubgroupBarriersNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32)187 static bool checkVertexPipelineStagesSubgroupBarriersNoSSBO(std::vector<const void*> datas,
188 		deUint32 width, deUint32)
189 {
190 	return _checkVertexPipelineStagesSubgroupBarriersNoSSBO(datas, width, false);
191 }
192 
checkVertexPipelineStagesSubgroupBarriersWithImageNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32)193 static bool checkVertexPipelineStagesSubgroupBarriersWithImageNoSSBO(std::vector<const void*> datas,
194 		deUint32 width, deUint32)
195 {
196 	return _checkVertexPipelineStagesSubgroupBarriersNoSSBO(datas, width, true);
197 }
198 
_checkTessellationEvaluationSubgroupBarriersNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32,bool withImage)199 static bool _checkTessellationEvaluationSubgroupBarriersNoSSBO(std::vector<const void*> datas,
200 		deUint32 width, deUint32, bool withImage)
201 {
202 	const float* const	resultData	= reinterpret_cast<const float*>(datas[0]);
203 
204 	for (deUint32 x = 0u; x < width; ++x)
205 	{
206 		const deUint32 ndx = x*4u;
207 		if (!withImage && 0.0f == resultData[ndx])
208 		{
209 			return false;
210 		}
211 		else if (0.0f == resultData[ndx +2] && resultData[ndx] != resultData[ndx +3])
212 		{
213 			return false;
214 		}
215 	}
216 	return true;
217 }
218 
checkTessellationEvaluationSubgroupBarriersWithImageNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32 height)219 static bool checkTessellationEvaluationSubgroupBarriersWithImageNoSSBO(std::vector<const void*> datas,
220 	deUint32 width, deUint32 height)
221 {
222 	return _checkTessellationEvaluationSubgroupBarriersNoSSBO(datas, width, height, true);
223 }
224 
checkTessellationEvaluationSubgroupBarriersNoSSBO(std::vector<const void * > datas,deUint32 width,deUint32 height)225 static bool checkTessellationEvaluationSubgroupBarriersNoSSBO(std::vector<const void*> datas,
226 		deUint32 width, deUint32 height)
227 {
228 	return _checkTessellationEvaluationSubgroupBarriersNoSSBO(datas, width, height, false);
229 }
230 
checkComputeSubgroupElect(std::vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32)231 static bool checkComputeSubgroupElect(std::vector<const void*> datas,
232 									  const deUint32 numWorkgroups[3], const deUint32 localSize[3],
233 									  deUint32)
234 {
235 	return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
236 }
237 
checkComputeSubgroupBarriers(std::vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32)238 static bool checkComputeSubgroupBarriers(std::vector<const void*> datas,
239 		const deUint32 numWorkgroups[3], const deUint32 localSize[3],
240 		deUint32)
241 {
242 	// We used this SSBO to generate our unique value!
243 	const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[2]);
244 	return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, ref);
245 }
246 
247 enum OpType
248 {
249 	OPTYPE_ELECT = 0,
250 	OPTYPE_SUBGROUP_BARRIER,
251 	OPTYPE_SUBGROUP_MEMORY_BARRIER,
252 	OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER,
253 	OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED,
254 	OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE,
255 	OPTYPE_LAST
256 };
257 
getOpTypeName(int opType)258 std::string getOpTypeName(int opType)
259 {
260 	switch (opType)
261 	{
262 		default:
263 			DE_FATAL("Unsupported op type");
264 			return "";
265 		case OPTYPE_ELECT:
266 			return "subgroupElect";
267 		case OPTYPE_SUBGROUP_BARRIER:
268 			return "subgroupBarrier";
269 		case OPTYPE_SUBGROUP_MEMORY_BARRIER:
270 			return "subgroupMemoryBarrier";
271 		case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
272 			return "subgroupMemoryBarrierBuffer";
273 		case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
274 			return "subgroupMemoryBarrierShared";
275 		case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
276 			return "subgroupMemoryBarrierImage";
277 	}
278 }
279 
280 struct CaseDefinition
281 {
282 	int					opType;
283 	VkShaderStageFlags	shaderStage;
284 };
285 
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)286 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
287 {
288 	const vk::ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
289 	const vk::SpirVAsmBuildOptions	buildOptionsSpr	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3);
290 
291 	if(VK_SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage)
292 	{
293 		/*
294 			"layout(location = 0) in vec4 in_color;\n"
295 			"layout(location = 0) out vec4 out_color;\n"
296 			"void main()\n"
297 			{\n"
298 			"	out_color = in_color;\n"
299 			"}\n";
300 		*/
301 		const string fragment =
302 			"; SPIR-V\n"
303 			"; Version: 1.3\n"
304 			"; Generator: Khronos Glslang Reference Front End; 2\n"
305 			"; Bound: 13\n"
306 			"; Schema: 0\n"
307 			"OpCapability Shader\n"
308 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
309 			"OpMemoryModel Logical GLSL450\n"
310 			"OpEntryPoint Fragment %4 \"main\" %9 %11\n"
311 			"OpExecutionMode %4 OriginUpperLeft\n"
312 			"OpDecorate %9 Location 0\n"
313 			"OpDecorate %11 Location 0\n"
314 			"%2 = OpTypeVoid\n"
315 			"%3 = OpTypeFunction %2\n"
316 			"%6 = OpTypeFloat 32\n"
317 			"%7 = OpTypeVector %6 4\n"
318 			"%8 = OpTypePointer Output %7\n"
319 			"%9 = OpVariable %8 Output\n"
320 			"%10 = OpTypePointer Input %7\n"
321 			"%11 = OpVariable %10 Input\n"
322 			"%4 = OpFunction %2 None %3\n"
323 			"%5 = OpLabel\n"
324 			"%12 = OpLoad %7 %11\n"
325 			"OpStore %9 %12\n"
326 			"OpReturn\n"
327 			"OpFunctionEnd\n";
328 		programCollection.spirvAsmSources.add("fragment") << fragment;
329 	}
330 	if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
331 	{
332 		/*
333 			"#version 450\n"
334 			"void main (void)\n"
335 			"{\n"
336 			"  vec2 uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);\n"
337 			"  gl_Position = vec4(uv * 2.0f + -1.0f, 0.0f, 1.0f);\n"
338 			"  gl_PointSize = 1.0f;\n"
339 			"}\n";
340 		*/
341 		const string vertex =
342 			"; SPIR-V\n"
343 			"; Version: 1.3\n"
344 			"; Generator: Khronos Glslang Reference Front End; 2\n"
345 			"; Bound: 44\n"
346 			"; Schema: 0\n"
347 			"OpCapability Shader\n"
348 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
349 			"OpMemoryModel Logical GLSL450\n"
350 			"OpEntryPoint Vertex %4 \"main\" %12 %29\n"
351 			"OpDecorate %12 BuiltIn VertexIndex\n"
352 			"OpMemberDecorate %27 0 BuiltIn Position\n"
353 			"OpMemberDecorate %27 1 BuiltIn PointSize\n"
354 			"OpMemberDecorate %27 2 BuiltIn ClipDistance\n"
355 			"OpMemberDecorate %27 3 BuiltIn CullDistance\n"
356 			"OpDecorate %27 Block\n"
357 			"%2 = OpTypeVoid\n"
358 			"%3 = OpTypeFunction %2\n"
359 			"%6 = OpTypeFloat 32\n"
360 			"%7 = OpTypeVector %6 2\n"
361 			"%8 = OpTypePointer Function %7\n"
362 			"%10 = OpTypeInt 32 1\n"
363 			"%11 = OpTypePointer Input %10\n"
364 			"%12 = OpVariable %11 Input\n"
365 			"%14 = OpConstant %10 1\n"
366 			"%16 = OpConstant %10 2\n"
367 			"%23 = OpTypeVector %6 4\n"
368 			"%24 = OpTypeInt 32 0\n"
369 			"%25 = OpConstant %24 1\n"
370 			"%26 = OpTypeArray %6 %25\n"
371 			"%27 = OpTypeStruct %23 %6 %26 %26\n"
372 			"%28 = OpTypePointer Output %27\n"
373 			"%29 = OpVariable %28 Output\n"
374 			"%30 = OpConstant %10 0\n"
375 			"%32 = OpConstant %6 2\n"
376 			"%34 = OpConstant %6 -1\n"
377 			"%37 = OpConstant %6 0\n"
378 			"%38 = OpConstant %6 1\n"
379 			"%42 = OpTypePointer Output %23\n"
380 			"%44 = OpTypePointer Output %6\n"
381 			"%4 = OpFunction %2 None %3\n"
382 			"%5 = OpLabel\n"
383 			"%9 = OpVariable %8 Function\n"
384 			"%13 = OpLoad %10 %12\n"
385 			"%15 = OpShiftLeftLogical %10 %13 %14\n"
386 			"%17 = OpBitwiseAnd %10 %15 %16\n"
387 			"%18 = OpConvertSToF %6 %17\n"
388 			"%19 = OpLoad %10 %12\n"
389 			"%20 = OpBitwiseAnd %10 %19 %16\n"
390 			"%21 = OpConvertSToF %6 %20\n"
391 			"%22 = OpCompositeConstruct %7 %18 %21\n"
392 			"OpStore %9 %22\n"
393 			"%31 = OpLoad %7 %9\n"
394 			"%33 = OpVectorTimesScalar %7 %31 %32\n"
395 			"%35 = OpCompositeConstruct %7 %34 %34\n"
396 			"%36 = OpFAdd %7 %33 %35\n"
397 			"%39 = OpCompositeExtract %6 %36 0\n"
398 			"%40 = OpCompositeExtract %6 %36 1\n"
399 			"%41 = OpCompositeConstruct %23 %39 %40 %37 %38\n"
400 			"%43 = OpAccessChain %42 %29 %30\n"
401 			"OpStore %43 %41\n"
402 			"%45 = OpAccessChain %44 %29 %14\n"
403 			"OpStore %45 %38\n"
404 			"OpReturn\n"
405 			"OpFunctionEnd\n";
406 		programCollection.spirvAsmSources.add("vert") << vertex;
407 	}
408 	else if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
409 		subgroups::setVertexShaderFrameBuffer(programCollection);
410 
411 	if (OPTYPE_ELECT == caseDef.opType)
412 	{
413 		std::ostringstream electedValue ;
414 		std::ostringstream unelectedValue;
415 		electedValue << ELECTED_VALUE;
416 		unelectedValue << UNELECTED_VALUE;
417 
418 		if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
419 		{
420 			/*
421 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
422 				"layout(location = 0) out vec4 out_color;\n"
423 				"layout(location = 0) in highp vec4 in_position;\n"
424 				"\n"
425 				"void main (void)\n"
426 				"{\n"
427 				"  if (subgroupElect())\n"
428 				"  {\n"
429 				"    out_color.r = " << ELECTED_VALUE << ";\n"
430 				"    out_color.g = 1.0f;\n"
431 				"  }\n"
432 				"  else\n"
433 				"  {\n"
434 				"    out_color.r = " << UNELECTED_VALUE << ";\n"
435 				"    out_color.g = 0.0f;\n"
436 				"  }\n"
437 				"  gl_Position = in_position;\n"
438 				"  gl_PointSize = 1.0f;\n"
439 				"}\n";
440 			*/
441 			const string vertex =
442 				"; SPIR-V\n"
443 				"; Version: 1.3\n"
444 				"; Generator: Khronos Glslang Reference Front End; 2\n"
445 				"; Bound: 38\n"
446 				"; Schema: 0\n"
447 				"OpCapability Shader\n"
448 				"OpCapability GroupNonUniform\n"
449 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
450 				"OpMemoryModel Logical GLSL450\n"
451 				"OpEntryPoint Vertex %4 \"main\" %15 %31 %35\n"
452 				"OpDecorate %15 Location 0\n"
453 				"OpMemberDecorate %29 0 BuiltIn Position\n"
454 				"OpMemberDecorate %29 1 BuiltIn PointSize\n"
455 				"OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
456 				"OpMemberDecorate %29 3 BuiltIn CullDistance\n"
457 				"OpDecorate %29 Block\n"
458 				"OpDecorate %35 Location 0\n"
459 				"%2 = OpTypeVoid\n"
460 				"%3 = OpTypeFunction %2\n"
461 				"%6 = OpTypeBool\n"
462 				"%7 = OpTypeInt 32 0\n"
463 				"%8 = OpConstant %7 3\n"
464 				"%12 = OpTypeFloat 32\n"
465 				"%13 = OpTypeVector %12 4\n"
466 				"%14 = OpTypePointer Output %13\n"
467 				"%15 = OpVariable %14 Output\n"
468 				"%16 = OpConstant %12 " + electedValue.str() + "\n"
469 				"%17 = OpConstant %7 0\n"
470 				"%18 = OpTypePointer Output %12\n"
471 				"%20 = OpConstant %12 1\n"
472 				"%21 = OpConstant %7 1\n"
473 				"%24 = OpConstant %12 " + unelectedValue.str() + "\n"
474 				"%26 = OpConstant %12 0\n"
475 				"%28 = OpTypeArray %12 %21\n"
476 				"%29 = OpTypeStruct %13 %12 %28 %28\n"
477 				"%30 = OpTypePointer Output %29\n"
478 				"%31 = OpVariable %30 Output\n"
479 				"%32 = OpTypeInt 32 1\n"
480 				"%33 = OpConstant %32 0\n"
481 				"%34 = OpTypePointer Input %13\n"
482 				"%35 = OpVariable %34 Input\n"
483 				"%38 = OpConstant %32 1\n"
484 				"%4 = OpFunction %2 None %3\n"
485 				"%5 = OpLabel\n"
486 				"%9 = OpGroupNonUniformElect %6 %8\n"
487 				"OpSelectionMerge %11 None\n"
488 				"OpBranchConditional %9 %10 %23\n"
489 				"%10 = OpLabel\n"
490 				"%19 = OpAccessChain %18 %15 %17\n"
491 				"OpStore %19 %16\n"
492 				"%22 = OpAccessChain %18 %15 %21\n"
493 				"OpStore %22 %20\n"
494 				"OpBranch %11\n"
495 				"%23 = OpLabel\n"
496 				"%25 = OpAccessChain %18 %15 %17\n"
497 				"OpStore %25 %24\n"
498 				"%27 = OpAccessChain %18 %15 %21\n"
499 				"OpStore %27 %26\n"
500 				"OpBranch %11\n"
501 				"%11 = OpLabel\n"
502 				"%36 = OpLoad %13 %35\n"
503 				"%37 = OpAccessChain %14 %31 %33\n"
504 				"OpStore %37 %36\n"
505 				"%39 = OpAccessChain %18 %31 %38\n"
506 				"OpStore %39 %20\n"
507 				"OpReturn\n"
508 				"OpFunctionEnd\n";
509 			programCollection.spirvAsmSources.add("vert") << vertex << buildOptionsSpr;
510 		}
511 		else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
512 		{
513 			/*
514 				"#version 450\n"
515 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
516 				"layout(points) in;\n"
517 				"layout(points, max_vertices = 1) out;\n"
518 				"layout(location = 0) out vec4 out_color;\n"
519 				"void main (void)\n"
520 				"{\n"
521 				"  if (subgroupElect())\n"
522 				"  {\n"
523 				"    out_color.r = " << ELECTED_VALUE << ";\n"
524 				"    out_color.g = 1.0f;\n"
525 				"  }\n"
526 				"  else\n"
527 				"  {\n"
528 				"    out_color.r = " << UNELECTED_VALUE << ";\n"
529 				"    out_color.g = 0.0f;\n"
530 				"  }\n"
531 				"  gl_Position = gl_in[0].gl_Position;\n"
532 				"  EmitVertex();\n"
533 				"  EndPrimitive();\n"
534 				"}\n";
535 			*/
536 			const string geometry =
537 				"; SPIR-V\n"
538 				"; Version: 1.3\n"
539 				"; Generator: Khronos Glslang Reference Front End; 2\n"
540 				"; Bound: 42\n"
541 				"; Schema: 0\n"
542 				"OpCapability Geometry\n"
543 				"OpCapability GroupNonUniform\n"
544 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
545 				"OpMemoryModel Logical GLSL450\n"
546 				"OpEntryPoint Geometry %4 \"main\" %15 %31 %37\n"
547 				"OpExecutionMode %4 InputPoints\n"
548 				"OpExecutionMode %4 Invocations 1\n"
549 				"OpExecutionMode %4 OutputPoints\n"
550 				"OpExecutionMode %4 OutputVertices 1\n"
551 				"OpDecorate %15 Location 0\n"
552 				"OpMemberDecorate %29 0 BuiltIn Position\n"
553 				"OpMemberDecorate %29 1 BuiltIn PointSize\n"
554 				"OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
555 				"OpMemberDecorate %29 3 BuiltIn CullDistance\n"
556 				"OpDecorate %29 Block\n"
557 				"OpMemberDecorate %34 0 BuiltIn Position\n"
558 				"OpMemberDecorate %34 1 BuiltIn PointSize\n"
559 				"OpMemberDecorate %34 2 BuiltIn ClipDistance\n"
560 				"OpMemberDecorate %34 3 BuiltIn CullDistance\n"
561 				"OpDecorate %34 Block\n"
562 				"%2 = OpTypeVoid\n"
563 				"%3 = OpTypeFunction %2\n"
564 				"%6 = OpTypeBool\n"
565 				"%7 = OpTypeInt 32 0\n"
566 				"%8 = OpConstant %7 3\n"
567 				"%12 = OpTypeFloat 32\n"
568 				"%13 = OpTypeVector %12 4\n"
569 				"%14 = OpTypePointer Output %13\n"
570 				"%15 = OpVariable %14 Output\n"
571 				"%16 = OpConstant %12 " + electedValue.str() + "\n"
572 				"%17 = OpConstant %7 0\n"
573 				"%18 = OpTypePointer Output %12\n"
574 				"%20 = OpConstant %12 1\n"
575 				"%21 = OpConstant %7 1\n"
576 				"%24 = OpConstant %12 " + unelectedValue.str() + "\n"
577 				"%26 = OpConstant %12 0\n"
578 				"%28 = OpTypeArray %12 %21\n"
579 				"%29 = OpTypeStruct %13 %12 %28 %28\n"
580 				"%30 = OpTypePointer Output %29\n"
581 				"%31 = OpVariable %30 Output\n"
582 				"%32 = OpTypeInt 32 1\n"
583 				"%33 = OpConstant %32 0\n"
584 				"%34 = OpTypeStruct %13 %12 %28 %28\n"
585 				"%35 = OpTypeArray %34 %21\n"
586 				"%36 = OpTypePointer Input %35\n"
587 				"%37 = OpVariable %36 Input\n"
588 				"%38 = OpTypePointer Input %13\n"
589 				"%4 = OpFunction %2 None %3\n"
590 				"%5 = OpLabel\n"
591 				"%9 = OpGroupNonUniformElect %6 %8\n"
592 				"OpSelectionMerge %11 None\n"
593 				"OpBranchConditional %9 %10 %23\n"
594 				"%10 = OpLabel\n"
595 				"%19 = OpAccessChain %18 %15 %17\n"
596 				"OpStore %19 %16\n"
597 				"%22 = OpAccessChain %18 %15 %21\n"
598 				"OpStore %22 %20\n"
599 				"OpBranch %11\n"
600 				"%23 = OpLabel\n"
601 				"%25 = OpAccessChain %18 %15 %17\n"
602 				"OpStore %25 %24\n"
603 				"%27 = OpAccessChain %18 %15 %21\n"
604 				"OpStore %27 %26\n"
605 				"OpBranch %11\n"
606 				"%11 = OpLabel\n"
607 				"%39 = OpAccessChain %38 %37 %33 %33\n"
608 				"%40 = OpLoad %13 %39\n"
609 				"%41 = OpAccessChain %14 %31 %33\n"
610 				"OpStore %41 %40\n"
611 				"OpEmitVertex\n"
612 				"OpEndPrimitive\n"
613 				"OpReturn\n"
614 				"OpFunctionEnd\n";
615 			programCollection.spirvAsmSources.add("geometry") << geometry << buildOptionsSpr;
616 		}
617 		else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
618 		{
619 			/*
620 				<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
621 				<< "#extension GL_EXT_tessellation_shader : require\n"
622 				<< "layout(vertices = 2) out;\n"
623 				<< "void main (void)\n"
624 				<< "{\n"
625 				<< "  if (gl_InvocationID == 0)\n"
626 				<<"  {\n"
627 				<< "    gl_TessLevelOuter[0] = 1.0f;\n"
628 				<< "    gl_TessLevelOuter[1] = 1.0f;\n"
629 				<< "  }\n"
630 				<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
631 				<< "}\n";
632 			*/
633 			const string controlSource =
634 				"; SPIR-V\n"
635 				"; Version: 1.3\n"
636 				"; Generator: Khronos Glslang Reference Front End; 2\n"
637 				"; Bound: 46\n"
638 				"; Schema: 0\n"
639 				"OpCapability Tessellation\n"
640 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
641 				"OpMemoryModel Logical GLSL450\n"
642 				"OpEntryPoint TessellationControl %4 \"main\" %8 %20 %33 %39\n"
643 				"OpExecutionMode %4 OutputVertices 2\n"
644 				"OpDecorate %8 BuiltIn InvocationId\n"
645 				"OpDecorate %20 Patch\n"
646 				"OpDecorate %20 BuiltIn TessLevelOuter\n"
647 				"OpMemberDecorate %29 0 BuiltIn Position\n"
648 				"OpMemberDecorate %29 1 BuiltIn PointSize\n"
649 				"OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
650 				"OpMemberDecorate %29 3 BuiltIn CullDistance\n"
651 				"OpDecorate %29 Block\n"
652 				"OpMemberDecorate %35 0 BuiltIn Position\n"
653 				"OpMemberDecorate %35 1 BuiltIn PointSize\n"
654 				"OpMemberDecorate %35 2 BuiltIn ClipDistance\n"
655 				"OpMemberDecorate %35 3 BuiltIn CullDistance\n"
656 				"OpDecorate %35 Block\n"
657 				"%2 = OpTypeVoid\n"
658 				"%3 = OpTypeFunction %2\n"
659 				"%6 = OpTypeInt 32 1\n"
660 				"%7 = OpTypePointer Input %6\n"
661 				"%8 = OpVariable %7 Input\n"
662 				"%10 = OpConstant %6 0\n"
663 				"%11 = OpTypeBool\n"
664 				"%15 = OpTypeFloat 32\n"
665 				"%16 = OpTypeInt 32 0\n"
666 				"%17 = OpConstant %16 4\n"
667 				"%18 = OpTypeArray %15 %17\n"
668 				"%19 = OpTypePointer Output %18\n"
669 				"%20 = OpVariable %19 Output\n"
670 				"%21 = OpConstant %15 1\n"
671 				"%22 = OpTypePointer Output %15\n"
672 				"%24 = OpConstant %6 1\n"
673 				"%26 = OpTypeVector %15 4\n"
674 				"%27 = OpConstant %16 1\n"
675 				"%28 = OpTypeArray %15 %27\n"
676 				"%29 = OpTypeStruct %26 %15 %28 %28\n"
677 				"%30 = OpConstant %16 2\n"
678 				"%31 = OpTypeArray %29 %30\n"
679 				"%32 = OpTypePointer Output %31\n"
680 				"%33 = OpVariable %32 Output\n"
681 				"%35 = OpTypeStruct %26 %15 %28 %28\n"
682 				"%36 = OpConstant %16 32\n"
683 				"%37 = OpTypeArray %35 %36\n"
684 				"%38 = OpTypePointer Input %37\n"
685 				"%39 = OpVariable %38 Input\n"
686 				"%41 = OpTypePointer Input %26\n"
687 				"%44 = OpTypePointer Output %26\n"
688 				"%4 = OpFunction %2 None %3\n"
689 				"%5 = OpLabel\n"
690 				"%9 = OpLoad %6 %8\n"
691 				"%12 = OpIEqual %11 %9 %10\n"
692 				"OpSelectionMerge %14 None\n"
693 				"OpBranchConditional %12 %13 %14\n"
694 				"%13 = OpLabel\n"
695 				"%23 = OpAccessChain %22 %20 %10\n"
696 				"OpStore %23 %21\n"
697 				"%25 = OpAccessChain %22 %20 %24\n"
698 				"OpStore %25 %21\n"
699 				"OpBranch %14\n"
700 				"%14 = OpLabel\n"
701 				"%34 = OpLoad %6 %8\n"
702 				"%40 = OpLoad %6 %8\n"
703 				"%42 = OpAccessChain %41 %39 %40 %10\n"
704 				"%43 = OpLoad %26 %42\n"
705 				"%45 = OpAccessChain %44 %33 %34 %10\n"
706 				"OpStore %45 %43\n"
707 				"OpReturn\n"
708 				"OpFunctionEnd\n";
709 			programCollection.spirvAsmSources.add("tesc") << controlSource << buildOptionsSpr;
710 
711 			/*
712 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
713 				"#extension GL_EXT_tessellation_shader : require\n"
714 				"layout(isolines, equal_spacing, ccw ) in;\n"
715 				"layout(location = 0) out vec4 out_color;\n"
716 				"\n"
717 				"void main (void)\n"
718 				"{\n"
719 				"  if (subgroupElect())\n"
720 				"  {\n"
721 				"    out_color.r = " << 2 * ELECTED_VALUE - UNELECTED_VALUE << ";\n"
722 				"    out_color.g = 2.0f;\n"
723 				"  }\n"
724 				"  else\n"
725 				"  {\n"
726 				"    out_color.r = " << UNELECTED_VALUE << ";\n"
727 				"    out_color.g = 0.0f;\n"
728 				"  }\n"
729 				"  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
730 				"}\n";
731 			*/
732 
733 			const string evaluationSource =
734 				"; SPIR-V\n"
735 				"; Version: 1.3\n"
736 				"; Generator: Khronos Glslang Reference Front End; 2\n"
737 				"; Bound: 54\n"
738 				"; Schema: 0\n"
739 				"OpCapability Tessellation\n"
740 				"OpCapability GroupNonUniform\n"
741 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
742 				"OpMemoryModel Logical GLSL450\n"
743 				"OpEntryPoint TessellationEvaluation %4 \"main\" %15 %31 %38 %47\n"
744 				"OpExecutionMode %4 Isolines\n"
745 				"OpExecutionMode %4 SpacingEqual\n"
746 				"OpExecutionMode %4 VertexOrderCcw\n"
747 				"OpDecorate %15 Location 0\n"
748 				"OpMemberDecorate %29 0 BuiltIn Position\n"
749 				"OpMemberDecorate %29 1 BuiltIn PointSize\n"
750 				"OpMemberDecorate %29 2 BuiltIn ClipDistance\n"
751 				"OpMemberDecorate %29 3 BuiltIn CullDistance\n"
752 				"OpDecorate %29 Block\n"
753 				"OpMemberDecorate %34 0 BuiltIn Position\n"
754 				"OpMemberDecorate %34 1 BuiltIn PointSize\n"
755 				"OpMemberDecorate %34 2 BuiltIn ClipDistance\n"
756 				"OpMemberDecorate %34 3 BuiltIn CullDistance\n"
757 				"OpDecorate %34 Block\n"
758 				"OpDecorate %47 BuiltIn TessCoord\n"
759 				"%2 = OpTypeVoid\n"
760 				"%3 = OpTypeFunction %2\n"
761 				"%6 = OpTypeBool\n"
762 				"%7 = OpTypeInt 32 0\n"
763 				"%8 = OpConstant %7 3\n"
764 				"%12 = OpTypeFloat 32\n"
765 				"%13 = OpTypeVector %12 4\n"
766 				"%14 = OpTypePointer Output %13\n"
767 				"%15 = OpVariable %14 Output\n"
768 				"%16 = OpConstant %12 71\n"//electedValue
769 				"%17 = OpConstant %7 0\n"
770 				"%18 = OpTypePointer Output %12\n"
771 				"%20 = OpConstant %12 2\n"
772 				"%21 = OpConstant %7 1\n"
773 				"%24 = OpConstant %12 " + unelectedValue.str() + "\n"
774 				"%26 = OpConstant %12 0\n"
775 				"%28 = OpTypeArray %12 %21\n"
776 				"%29 = OpTypeStruct %13 %12 %28 %28\n"
777 				"%30 = OpTypePointer Output %29\n"
778 				"%31 = OpVariable %30 Output\n"
779 				"%32 = OpTypeInt 32 1\n"
780 				"%33 = OpConstant %32 0\n"
781 				"%34 = OpTypeStruct %13 %12 %28 %28\n"
782 				"%35 = OpConstant %7 32\n"
783 				"%36 = OpTypeArray %34 %35\n"
784 				"%37 = OpTypePointer Input %36\n"
785 				"%38 = OpVariable %37 Input\n"
786 				"%39 = OpTypePointer Input %13\n"
787 				"%42 = OpConstant %32 1\n"
788 				"%45 = OpTypeVector %12 3\n"
789 				"%46 = OpTypePointer Input %45\n"
790 				"%47 = OpVariable %46 Input\n"
791 				"%48 = OpTypePointer Input %12\n"
792 				"%4 = OpFunction %2 None %3\n"
793 				"%5 = OpLabel\n"
794 				"%9 = OpGroupNonUniformElect %6 %8\n"
795 				"OpSelectionMerge %11 None\n"
796 				"OpBranchConditional %9 %10 %23\n"
797 				"%10 = OpLabel\n"
798 				"%19 = OpAccessChain %18 %15 %17\n"
799 				"OpStore %19 %16\n"
800 				"%22 = OpAccessChain %18 %15 %21\n"
801 				"OpStore %22 %20\n"
802 				"OpBranch %11\n"
803 				"%23 = OpLabel\n"
804 				"%25 = OpAccessChain %18 %15 %17\n"
805 				"OpStore %25 %24\n"
806 				"%27 = OpAccessChain %18 %15 %21\n"
807 				"OpStore %27 %26\n"
808 				"OpBranch %11\n"
809 				"%11 = OpLabel\n"
810 				"%40 = OpAccessChain %39 %38 %33 %33\n"
811 				"%41 = OpLoad %13 %40\n"
812 				"%43 = OpAccessChain %39 %38 %42 %33\n"
813 				"%44 = OpLoad %13 %43\n"
814 				"%49 = OpAccessChain %48 %47 %17\n"
815 				"%50 = OpLoad %12 %49\n"
816 				"%51 = OpCompositeConstruct %13 %50 %50 %50 %50\n"
817 				"%52 = OpExtInst %13 %1 FMix %41 %44 %51\n"
818 				"%53 = OpAccessChain %14 %31 %33\n"
819 				"OpStore %53 %52\n"
820 				"OpReturn\n"
821 				"OpFunctionEnd\n";
822 
823 			programCollection.spirvAsmSources.add("tese") << evaluationSource << buildOptionsSpr;
824 		}
825 		else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
826 		{
827 			/*
828 				"#extension GL_KHR_shader_subgroup_basic: enable\n"
829 				"#extension GL_EXT_tessellation_shader : require\n"
830 				"layout(vertices = 2) out;\n"
831 				"layout(location = 0) out vec4 out_color[];\n"
832 				"void main (void)\n"
833 				"{\n"
834 				"  if (gl_InvocationID == 0)\n"
835 				  {\n"
836 				"    gl_TessLevelOuter[0] = 1.0f;\n"
837 				"    gl_TessLevelOuter[1] = 1.0f;\n"
838 				"  }\n"
839 				"  if (subgroupElect())\n"
840 				"  {\n"
841 				"    out_color[gl_InvocationID].r = " << ELECTED_VALUE << ";\n"
842 				"    out_color[gl_InvocationID].g = 1.0f;\n"
843 				"  }\n"
844 				"  else\n"
845 				"  {\n"
846 				"    out_color[gl_InvocationID].r = " << UNELECTED_VALUE << ";\n"
847 				"    out_color[gl_InvocationID].g = 0.0f;\n"
848 				"  }\n"
849 				"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
850 				"}\n";
851 			*/
852 			const string  controlSource =
853 				"; SPIR-V\n"
854 				"; Version: 1.3\n"
855 				"; Generator: Khronos Glslang Reference Front End; 2\n"
856 				"; Bound: 66\n"
857 				"; Schema: 0\n"
858 				"OpCapability Tessellation\n"
859 				"OpCapability GroupNonUniform\n"
860 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
861 				"OpMemoryModel Logical GLSL450\n"
862 				"OpEntryPoint TessellationControl %4 \"main\" %8 %20 %34 %53 %59\n"
863 				"OpExecutionMode %4 OutputVertices 2\n"
864 				"OpDecorate %8 BuiltIn InvocationId\n"
865 				"OpDecorate %20 Patch\n"
866 				"OpDecorate %20 BuiltIn TessLevelOuter\n"
867 				"OpDecorate %34 Location 0\n"
868 				"OpMemberDecorate %50 0 BuiltIn Position\n"
869 				"OpMemberDecorate %50 1 BuiltIn PointSize\n"
870 				"OpMemberDecorate %50 2 BuiltIn ClipDistance\n"
871 				"OpMemberDecorate %50 3 BuiltIn CullDistance\n"
872 				"OpDecorate %50 Block\n"
873 				"OpMemberDecorate %55 0 BuiltIn Position\n"
874 				"OpMemberDecorate %55 1 BuiltIn PointSize\n"
875 				"OpMemberDecorate %55 2 BuiltIn ClipDistance\n"
876 				"OpMemberDecorate %55 3 BuiltIn CullDistance\n"
877 				"OpDecorate %55 Block\n"
878 				"%2 = OpTypeVoid\n"
879 				"%3 = OpTypeFunction %2\n"
880 				"%6 = OpTypeInt 32 1\n"
881 				"%7 = OpTypePointer Input %6\n"
882 				"%8 = OpVariable %7 Input\n"
883 				"%10 = OpConstant %6 0\n"
884 				"%11 = OpTypeBool\n"
885 				"%15 = OpTypeFloat 32\n"
886 				"%16 = OpTypeInt 32 0\n"
887 				"%17 = OpConstant %16 4\n"
888 				"%18 = OpTypeArray %15 %17\n"
889 				"%19 = OpTypePointer Output %18\n"
890 				"%20 = OpVariable %19 Output\n"
891 				"%21 = OpConstant %15 1\n"
892 				"%22 = OpTypePointer Output %15\n"
893 				"%24 = OpConstant %6 1\n"
894 				"%26 = OpConstant %16 3\n"
895 				"%30 = OpTypeVector %15 4\n"
896 				"%31 = OpConstant %16 2\n"
897 				"%32 = OpTypeArray %30 %31\n"
898 				"%33 = OpTypePointer Output %32\n"
899 				"%34 = OpVariable %33 Output\n"
900 				"%36 = OpConstant %15 " + electedValue.str() + "\n"
901 				"%37 = OpConstant %16 0\n"
902 				"%40 = OpConstant %16 1\n"
903 				"%44 = OpConstant %15 " + unelectedValue.str() + "\n"
904 				"%47 = OpConstant %15 0\n"
905 				"%49 = OpTypeArray %15 %40\n"
906 				"%50 = OpTypeStruct %30 %15 %49 %49\n"
907 				"%51 = OpTypeArray %50 %31\n"
908 				"%52 = OpTypePointer Output %51\n"
909 				"%53 = OpVariable %52 Output\n"
910 				"%55 = OpTypeStruct %30 %15 %49 %49\n"
911 				"%56 = OpConstant %16 32\n"
912 				"%57 = OpTypeArray %55 %56\n"
913 				"%58 = OpTypePointer Input %57\n"
914 				"%59 = OpVariable %58 Input\n"
915 				"%61 = OpTypePointer Input %30\n"
916 				"%64 = OpTypePointer Output %30\n"
917 				"%4 = OpFunction %2 None %3\n"
918 				"%5 = OpLabel\n"
919 				"%9 = OpLoad %6 %8\n"
920 				"%12 = OpIEqual %11 %9 %10\n"
921 				"OpSelectionMerge %14 None\n"
922 				"OpBranchConditional %12 %13 %14\n"
923 				"%13 = OpLabel\n"
924 				"%23 = OpAccessChain %22 %20 %10\n"
925 				"OpStore %23 %21\n"
926 				"%25 = OpAccessChain %22 %20 %24\n"
927 				"OpStore %25 %21\n"
928 				"OpBranch %14\n"
929 				"%14 = OpLabel\n"
930 				"%27 = OpGroupNonUniformElect %11 %26\n"
931 				"OpSelectionMerge %29 None\n"
932 				"OpBranchConditional %27 %28 %42\n"
933 				"%28 = OpLabel\n"
934 				"%35 = OpLoad %6 %8\n"
935 				"%38 = OpAccessChain %22 %34 %35 %37\n"
936 				"OpStore %38 %36\n"
937 				"%39 = OpLoad %6 %8\n"
938 				"%41 = OpAccessChain %22 %34 %39 %40\n"
939 				"OpStore %41 %21\n"
940 				"OpBranch %29\n"
941 				"%42 = OpLabel\n"
942 				"%43 = OpLoad %6 %8\n"
943 				"%45 = OpAccessChain %22 %34 %43 %37\n"
944 				"OpStore %45 %44\n"
945 				"%46 = OpLoad %6 %8\n"
946 				"%48 = OpAccessChain %22 %34 %46 %40\n"
947 				"OpStore %48 %47\n"
948 				"OpBranch %29\n"
949 				"%29 = OpLabel\n"
950 				"%54 = OpLoad %6 %8\n"
951 				"%60 = OpLoad %6 %8\n"
952 				"%62 = OpAccessChain %61 %59 %60 %10\n"
953 				"%63 = OpLoad %30 %62\n"
954 				"%65 = OpAccessChain %64 %53 %54 %10\n"
955 				"OpStore %65 %63\n"
956 				"OpReturn\n"
957 				"OpFunctionEnd\n";
958 			programCollection.spirvAsmSources.add("tesc") << controlSource << buildOptionsSpr;
959 
960 			/*
961 				"#extension GL_KHR_shader_subgroup_ballot: enable\n"
962 				"#extension GL_EXT_tessellation_shader : require\n"
963 				"layout(isolines, equal_spacing, ccw ) in;\n"
964 				"layout(location = 0) in vec4 in_color[];\n"
965 				"layout(location = 0) out vec4 out_color;\n"
966 				"\n"
967 				"void main (void)\n"
968 				"{\n"
969 				"  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
970 				"  out_color = in_color[0];\n"
971 				"}\n";
972 			*/
973 
974 			const string evaluationSource =
975 				"; SPIR-V\n"
976 				"; Version: 1.3\n"
977 				"; Generator: Khronos Glslang Reference Front End; 2\n"
978 				"; Bound: 44\n"
979 				"; Schema: 0\n"
980 				"OpCapability Tessellation\n"
981 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
982 				"OpMemoryModel Logical GLSL450\n"
983 				"OpEntryPoint TessellationEvaluation %4 \"main\" %13 %20 %29 %38 %41\n"
984 				"OpExecutionMode %4 Isolines\n"
985 				"OpExecutionMode %4 SpacingEqual\n"
986 				"OpExecutionMode %4 VertexOrderCcw\n"
987 				"OpMemberDecorate %11 0 BuiltIn Position\n"
988 				"OpMemberDecorate %11 1 BuiltIn PointSize\n"
989 				"OpMemberDecorate %11 2 BuiltIn ClipDistance\n"
990 				"OpMemberDecorate %11 3 BuiltIn CullDistance\n"
991 				"OpDecorate %11 Block\n"
992 				"OpMemberDecorate %16 0 BuiltIn Position\n"
993 				"OpMemberDecorate %16 1 BuiltIn PointSize\n"
994 				"OpMemberDecorate %16 2 BuiltIn ClipDistance\n"
995 				"OpMemberDecorate %16 3 BuiltIn CullDistance\n"
996 				"OpDecorate %16 Block\n"
997 				"OpDecorate %29 BuiltIn TessCoord\n"
998 				"OpDecorate %38 Location 0\n"
999 				"OpDecorate %41 Location 0\n"
1000 				"%2 = OpTypeVoid\n"
1001 				"%3 = OpTypeFunction %2\n"
1002 				"%6 = OpTypeFloat 32\n"
1003 				"%7 = OpTypeVector %6 4\n"
1004 				"%8 = OpTypeInt 32 0\n"
1005 				"%9 = OpConstant %8 1\n"
1006 				"%10 = OpTypeArray %6 %9\n"
1007 				"%11 = OpTypeStruct %7 %6 %10 %10\n"
1008 				"%12 = OpTypePointer Output %11\n"
1009 				"%13 = OpVariable %12 Output\n"
1010 				"%14 = OpTypeInt 32 1\n"
1011 				"%15 = OpConstant %14 0\n"
1012 				"%16 = OpTypeStruct %7 %6 %10 %10\n"
1013 				"%17 = OpConstant %8 32\n"
1014 				"%18 = OpTypeArray %16 %17\n"
1015 				"%19 = OpTypePointer Input %18\n"
1016 				"%20 = OpVariable %19 Input\n"
1017 				"%21 = OpTypePointer Input %7\n"
1018 				"%24 = OpConstant %14 1\n"
1019 				"%27 = OpTypeVector %6 3\n"
1020 				"%28 = OpTypePointer Input %27\n"
1021 				"%29 = OpVariable %28 Input\n"
1022 				"%30 = OpConstant %8 0\n"
1023 				"%31 = OpTypePointer Input %6\n"
1024 				"%36 = OpTypePointer Output %7\n"
1025 				"%38 = OpVariable %36 Output\n"
1026 				"%39 = OpTypeArray %7 %17\n"
1027 				"%40 = OpTypePointer Input %39\n"
1028 				"%41 = OpVariable %40 Input\n"
1029 				"%4 = OpFunction %2 None %3\n"
1030 				"%5 = OpLabel\n"
1031 				"%22 = OpAccessChain %21 %20 %15 %15\n"
1032 				"%23 = OpLoad %7 %22\n"
1033 				"%25 = OpAccessChain %21 %20 %24 %15\n"
1034 				"%26 = OpLoad %7 %25\n"
1035 				"%32 = OpAccessChain %31 %29 %30\n"
1036 				"%33 = OpLoad %6 %32\n"
1037 				"%34 = OpCompositeConstruct %7 %33 %33 %33 %33\n"
1038 				"%35 = OpExtInst %7 %1 FMix %23 %26 %34\n"
1039 				"%37 = OpAccessChain %36 %13 %15\n"
1040 				"OpStore %37 %35\n"
1041 				"%42 = OpAccessChain %21 %41 %15\n"
1042 				"%43 = OpLoad %7 %42\n"
1043 				"OpStore %38 %43\n"
1044 				"OpReturn\n"
1045 				"OpFunctionEnd\n";
1046 			programCollection.spirvAsmSources.add("tese") << evaluationSource << buildOptionsSpr;
1047 		}
1048 		else
1049 		{
1050 			DE_FATAL("Unsupported shader stage");
1051 		}
1052 	}
1053 	else
1054 	{
1055 		std::ostringstream bdy;
1056 		string color = (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) ? "out_color[gl_InvocationID].b = 1.0f;\n" : "out_color.b = 1.0f;\n";
1057 		switch (caseDef.opType)
1058 		{
1059 			default:
1060 				DE_FATAL("Unhandled op type!");
1061 				break;
1062 			case OPTYPE_SUBGROUP_BARRIER:
1063 			case OPTYPE_SUBGROUP_MEMORY_BARRIER:
1064 			case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
1065 			{
1066 				bdy << " tempResult2 = tempBuffer[id];\n"
1067 					<< "  if (subgroupElect())\n"
1068 					<< "  {\n"
1069 					<< "    tempResult = value;\n"
1070 					<< "    " << color
1071 					<< "  }\n"
1072 					 << "  else\n"
1073 					<< "  {\n"
1074 					<< "    tempResult = tempBuffer[id];\n"
1075 					<< "  }\n"
1076 					<< "  " << getOpTypeName(caseDef.opType) << "();\n";
1077 				break;
1078 			}
1079 			case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
1080 				bdy <<"tempResult2 = imageLoad(tempImage, ivec2(id, 0)).x;\n"
1081 					<< "  if (subgroupElect())\n"
1082 					<< "  {\n"
1083 					<< "    tempResult = value;\n"
1084 					<< "     " << color
1085 					<< "  }\n"
1086 					<< "  else\n"
1087 					<< "  {\n"
1088 					<< "    tempResult = imageLoad(tempImage, ivec2(id, 0)).x;\n"
1089 					<< "  }\n"
1090 					<< "  subgroupMemoryBarrierImage();\n";
1091 
1092 				break;
1093 		}
1094 
1095 		if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
1096 		{
1097 			std::ostringstream	fragment;
1098 			fragment	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1099 				<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1100 				<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1101 				<< "layout(location = 0) out vec4 out_color;\n"
1102 				<< "\n"
1103 				<< "layout(set = 0, binding = 0) uniform Buffer1\n"
1104 				<< "{\n"
1105 				<< "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1106 				<< "};\n"
1107 				<< "\n"
1108 				<< "layout(set = 0, binding = 1) uniform Buffer2\n"
1109 				<< "{\n"
1110 				<< "  uint value;\n"
1111 				<< "};\n"
1112 				<< (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1113 				<< "void main (void)\n"
1114 				<< "{\n"
1115 				<< "  if (gl_HelperInvocation) return;\n"
1116 				<< "  uint id = 0;\n"
1117 				<< "  if (subgroupElect())\n"
1118 				<< "  {\n"
1119 				<< "    id = uint(gl_FragCoord.x);\n"
1120 				<< "  }\n"
1121 				<< "  id = subgroupBroadcastFirst(id);\n"
1122 				<< "  uint localId = id;\n"
1123 				<< "  uint tempResult = 0u;\n"
1124 				<< "  uint tempResult2 = 0u;\n"
1125 				<< "  out_color.b = 0.0f;\n"
1126 				<< bdy.str()
1127 				<< "  out_color.r = float(tempResult);\n"
1128 				<< "  out_color.g = float(value);\n"
1129 				<< "  out_color.a = float(tempResult2);\n"
1130 				<< "}\n";
1131 			programCollection.glslSources.add("fragment")
1132 				<< glu::FragmentSource(fragment.str()) << buildOptions;
1133 		}
1134 		else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
1135 		{
1136 			std::ostringstream	vertex;
1137 			vertex	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1138 				<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1139 				<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1140 				<<"\n"
1141 				<< "layout(location = 0) out vec4 out_color;\n"
1142 				<< "layout(location = 0) in highp vec4 in_position;\n"
1143 				<< "\n"
1144 				<< "layout(set = 0, binding = 0) uniform Buffer1\n"
1145 				<< "{\n"
1146 				<< "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1147 				<< "};\n"
1148 				<< "\n"
1149 				<< "layout(set = 0, binding = 1) uniform Buffer2\n"
1150 				<< "{\n"
1151 				<< "  uint value;\n"
1152 				<< "};\n"
1153 				<< (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1154 				<< "void main (void)\n"
1155 				<< "{\n"
1156 				<< "  uint id = 0;\n"
1157 				<< "  if (subgroupElect())\n"
1158 				<< "  {\n"
1159 				<< "    id = gl_VertexIndex;\n"
1160 				<< "  }\n"
1161 				<< "  id = subgroupBroadcastFirst(id);\n"
1162 				<< "  uint tempResult = 0u;\n"
1163 				<< "  uint tempResult2 = 0u;\n"
1164 				<< "  out_color.b = 0.0f;\n"
1165 				<< bdy.str()
1166 				<< "  out_color.r = float(tempResult);\n"
1167 				<< "  out_color.g = float(value);\n"
1168 				<< "  out_color.a = float(tempResult2);\n"
1169 				<< "  gl_Position = in_position;\n"
1170 				<< "  gl_PointSize = 1.0f;\n"
1171 				<< "}\n";
1172 			programCollection.glslSources.add("vert")
1173 				<< glu::VertexSource(vertex.str()) << buildOptions;
1174 		}
1175 	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
1176 		{
1177 			std::ostringstream geometry;
1178 
1179 			geometry << "#version 450\n"
1180 					<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1181 					<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1182 					<< "layout(points) in;\n"
1183 					<< "layout(points, max_vertices = 1) out;\n"
1184 					<< "layout(location = 0) out vec4 out_color;\n"
1185 					<< "layout(set = 0, binding = 0) uniform Buffer1\n"
1186 					<< "{\n"
1187 					<< "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1188 					<< "};\n"
1189 					<< "\n"
1190 					<< "layout(set = 0, binding = 1) uniform Buffer2\n"
1191 					<< "{\n"
1192 					<< "  uint value;\n"
1193 					<< "};\n"
1194 					<< (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1195 					<< "void main (void)\n"
1196 					<< "{\n"
1197 					<< "  uint id = 0;\n"
1198 					<< "  if (subgroupElect())\n"
1199 					<< "  {\n"
1200 					<< "    id = gl_InvocationID;\n"
1201 					<< "  }\n"
1202 					<< "  id = subgroupBroadcastFirst(id);\n"
1203 					<< "  uint tempResult = 0u;\n"
1204 					<< "  uint tempResult2 = 0u;\n"
1205 					<< "  out_color.b = 0.0f;\n"
1206 					<< bdy.str()
1207 					<< "  out_color.r = float(tempResult);\n"
1208 					<< "  out_color.g = float(value);\n"
1209 					<< "  out_color.a = float(tempResult2);\n"
1210 					<< "  gl_Position = gl_in[0].gl_Position;\n"
1211 					<< "  EmitVertex();\n"
1212 					<< "  EndPrimitive();\n"
1213 					<< "}\n";
1214 
1215 			programCollection.glslSources.add("geometry")
1216 				<< glu::GeometrySource(geometry.str()) << buildOptions;
1217 		}
1218 		else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
1219 		{
1220 			std::ostringstream controlSource;
1221 			std::ostringstream evaluationSource;
1222 
1223 			controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1224 				<< "#extension GL_EXT_tessellation_shader : require\n"
1225 				<< "layout(vertices = 2) out;\n"
1226 				<< "void main (void)\n"
1227 				<< "{\n"
1228 				<< "  if (gl_InvocationID == 0)\n"
1229 				<<"  {\n"
1230 				<< "    gl_TessLevelOuter[0] = 1.0f;\n"
1231 				<< "    gl_TessLevelOuter[1] = 1.0f;\n"
1232 				<< "  }\n"
1233 				<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1234 				<< "}\n";
1235 
1236 			evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1237 				<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1238 				<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1239 				<< "#extension GL_EXT_tessellation_shader : require\n"
1240 				<< "layout(isolines, equal_spacing, ccw ) in;\n"
1241 				<< "layout(location = 0) out vec4 out_color;\n"
1242 				<< "layout(set = 0, binding = 0) uniform Buffer1\n"
1243 				<< "{\n"
1244 				<< "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1245 				<< "};\n"
1246 				<< "\n"
1247 				<< "layout(set = 0, binding = 1) uniform Buffer2\n"
1248 				<< "{\n"
1249 				<< "  uint value;\n"
1250 				<< "};\n"
1251 				<< (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1252 				<< "void main (void)\n"
1253 				<< "{\n"
1254 				<< "  uint id = 0;\n"
1255 				<< "  if (subgroupElect())\n"
1256 				<< "  {\n"
1257 				<< "    id = gl_PrimitiveID;\n"
1258 				<< "  }\n"
1259 				<< "  id = subgroupBroadcastFirst(id);\n"
1260 				<< "  uint tempResult = 0u;\n"
1261 				<< "  uint tempResult2 = 0u;\n"
1262 				<< "  out_color.b = 0.0f;\n"
1263 				<< bdy.str()
1264 				<< "  out_color.r = float(tempResult);\n"
1265 				<< "  out_color.g = float(value);\n"
1266 				<< "  out_color.a = float(tempResult2);\n"
1267 				<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
1268 				<< "}\n";
1269 
1270 			programCollection.glslSources.add("tesc")
1271 				<< glu::TessellationControlSource(controlSource.str()) << buildOptions;
1272 			programCollection.glslSources.add("tese")
1273 				<< glu::TessellationEvaluationSource(evaluationSource.str()) << buildOptions;
1274 		}
1275 		else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
1276 		{
1277 			std::ostringstream controlSource;
1278 			std::ostringstream evaluationSource;
1279 
1280 			controlSource  << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1281 				<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1282 				<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1283 				<< "#extension GL_EXT_tessellation_shader : require\n"
1284 				<< "layout(vertices = 2) out;\n"
1285 				<< "layout(location = 0) out vec4 out_color[];\n"
1286 				<< "layout(set = 0, binding = 0) uniform Buffer1\n"
1287 				<< "{\n"
1288 				<< "  uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
1289 				<< "};\n"
1290 				<< "\n"
1291 				<< "layout(set = 0, binding = 1) uniform Buffer2\n"
1292 				<< "{\n"
1293 				<< "  uint value;\n"
1294 				<< "};\n"
1295 				<< (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(set = 0, binding = 2, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
1296 				<< "void main (void)\n"
1297 				<< "{\n"
1298 				<< "  uint id = 0;\n"
1299 				<< "  if (gl_InvocationID == 0)\n"
1300 				<<"  {\n"
1301 				<< "    gl_TessLevelOuter[0] = 1.0f;\n"
1302 				<< "    gl_TessLevelOuter[1] = 1.0f;\n"
1303 				<< "  }\n"
1304 				<< "  if (subgroupElect())\n"
1305 				<< "  {\n"
1306 				<< "    id = gl_InvocationID;\n"
1307 				<< "  }\n"
1308 				<< "  id = subgroupBroadcastFirst(id);\n"
1309 				<< "  uint tempResult = 0u;\n"
1310 				<< "  uint tempResult2 = 0u;\n"
1311 				<< "  out_color[gl_InvocationID].b = 0.0f;\n"
1312 				<< bdy.str()
1313 				<< "  out_color[gl_InvocationID].r = float(tempResult);\n"
1314 				<< "  out_color[gl_InvocationID].g = float(value);\n"
1315 				<< "  out_color[gl_InvocationID].a = float(tempResult2);\n"
1316 				<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1317 				<< "}\n";
1318 
1319 			evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
1320 				<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1321 				<< "#extension GL_EXT_tessellation_shader : require\n"
1322 				<< "layout(isolines, equal_spacing, ccw ) in;\n"
1323 				<< "layout(location = 0) in vec4 in_color[];\n"
1324 				<< "layout(location = 0) out vec4 out_color;\n"
1325 				<< "\n"
1326 				<< "void main (void)\n"
1327 				<< "{\n"
1328 				<< "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
1329 				<< "  out_color = in_color[0];\n"
1330 				<< "}\n";
1331 
1332 			programCollection.glslSources.add("tesc")
1333 				<< glu::TessellationControlSource(controlSource.str()) << buildOptions;
1334 			programCollection.glslSources.add("tese")
1335 				<< glu::TessellationEvaluationSource(evaluationSource.str()) << buildOptions;
1336 		}
1337 		else
1338 		{
1339 			DE_FATAL("Unsupported shader stage");
1340 		}
1341 	}
1342 }
1343 
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)1344 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
1345 {
1346 	if (OPTYPE_ELECT == caseDef.opType)
1347 	{
1348 		if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1349 		{
1350 			std::ostringstream src;
1351 
1352 			src << "#version 450\n"
1353 				<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1354 				<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
1355 				"local_size_z_id = 2) in;\n"
1356 				<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1357 				<< "{\n"
1358 				<< "  uint result[];\n"
1359 				<< "};\n"
1360 				<< "\n"
1361 				<< subgroups::getSharedMemoryBallotHelper()
1362 				<< "void main (void)\n"
1363 				<< "{\n"
1364 				<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
1365 				<< "  highp uint offset = globalSize.x * ((globalSize.y * "
1366 				"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
1367 				"gl_GlobalInvocationID.x;\n"
1368 				<< "  uint value = " << UNELECTED_VALUE << ";\n"
1369 				<< "  if (subgroupElect())\n"
1370 				<< "  {\n"
1371 				<< "    value = " << ELECTED_VALUE << ";\n"
1372 				<< "  }\n"
1373 				<< "  uvec4 bits = bitCount(sharedMemoryBallot(value == " << ELECTED_VALUE << "));\n"
1374 				<< "  result[offset] = bits.x + bits.y + bits.z + bits.w;\n"
1375 				<< "}\n";
1376 
1377 			programCollection.glslSources.add("comp")
1378 					<< glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1379 		}
1380 		else
1381 		{
1382 			{
1383 				std::ostringstream  vertex;
1384 				vertex	<< "#version 450\n"
1385 						<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1386 						<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1387 						<< "{\n"
1388 						<< "  uint result[];\n"
1389 						<< "};\n"
1390 						<< "layout(set = 0, binding = 4, std430) buffer Buffer2\n"
1391 						<< "{\n"
1392 						<< "  uint numSubgroupsExecuted;\n"
1393 						<< "};\n"
1394 						<< "\n"
1395 						<< "void main (void)\n"
1396 						<< "{\n"
1397 						<< "  if (subgroupElect())\n"
1398 						<< "  {\n"
1399 						<< "    result[gl_VertexIndex] = " << ELECTED_VALUE << ";\n"
1400 						<< "    atomicAdd(numSubgroupsExecuted, 1);\n"
1401 						<< "  }\n"
1402 						<< "  else\n"
1403 						<< "  {\n"
1404 						<< "    result[gl_VertexIndex] = " << UNELECTED_VALUE << ";\n"
1405 						<< "  }\n"
1406 						<< "  float pixelSize = 2.0f/1024.0f;\n"
1407 						<< "  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
1408 						<< "  gl_Position = vec4(float(gl_VertexIndex) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
1409 						<< "  gl_PointSize = 1.0f;\n"
1410 						<< "}\n";
1411 				programCollection.glslSources.add("vert")
1412 					<< glu::VertexSource(vertex.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1413 			}
1414 
1415 			{
1416 				std::ostringstream tesc;
1417 				tesc	<< "#version 450\n"
1418 						<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1419 						<< "layout(vertices=1) out;\n"
1420 						<< "layout(set = 0, binding = 1, std430) buffer Buffer1\n"
1421 						<< "{\n"
1422 						<< "  uint result[];\n"
1423 						<< "};\n"
1424 						<< "layout(set = 0, binding = 5, std430) buffer Buffer2\n"
1425 						<< "{\n"
1426 						<< "  uint numSubgroupsExecuted;\n"
1427 						<< "};\n"
1428 						<< "\n"
1429 						<< "void main (void)\n"
1430 						<< "{\n"
1431 						<< "  if (subgroupElect())\n"
1432 						<< "  {\n"
1433 						<< "    result[gl_PrimitiveID] = " << ELECTED_VALUE << ";\n"
1434 						<< "    atomicAdd(numSubgroupsExecuted, 1);\n"
1435 						<< "  }\n"
1436 						<< "  else\n"
1437 						<< "  {\n"
1438 						<< "    result[gl_PrimitiveID] = " << UNELECTED_VALUE << ";\n"
1439 						<< "  }\n"
1440 						<< "  if (gl_InvocationID == 0)\n"
1441 						<< "  {\n"
1442 						<< "    gl_TessLevelOuter[0] = 1.0f;\n"
1443 						<< "    gl_TessLevelOuter[1] = 1.0f;\n"
1444 						<< "  }\n"
1445 						<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1446 						<< "}\n";
1447 				programCollection.glslSources.add("tesc")
1448 					<< glu::TessellationControlSource(tesc.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1449 			}
1450 
1451 			{
1452 				std::ostringstream tese;
1453 				tese	<< "#version 450\n"
1454 						<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1455 						<< "layout(isolines) in;\n"
1456 						<< "layout(set = 0, binding = 2, std430) buffer Buffer1\n"
1457 						<< "{\n"
1458 						<< "  uint result[];\n"
1459 						<< "};\n"
1460 						<< "layout(set = 0, binding = 6, std430) buffer Buffer2\n"
1461 						<< "{\n"
1462 						<< "  uint numSubgroupsExecuted;\n"
1463 						<< "};\n"
1464 						<< "\n"
1465 						<< "void main (void)\n"
1466 						<< "{\n"
1467 						<< "  if (subgroupElect())\n"
1468 						<< "  {\n"
1469 						<< "    result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << ELECTED_VALUE << ";\n"
1470 						<< "    atomicAdd(numSubgroupsExecuted, 1);\n"
1471 						<< "  }\n"
1472 						<< "  else\n"
1473 						<< "  {\n"
1474 						<< "    result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << UNELECTED_VALUE << ";\n"
1475 						<< "  }\n"
1476 						<< "  float pixelSize = 2.0f/1024.0f;\n"
1477 						<< "  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
1478 						<< "}\n";
1479 				programCollection.glslSources.add("tese")
1480 					<< glu::TessellationEvaluationSource(tese.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1481 			}
1482 
1483 			{
1484 				std::ostringstream geometry;
1485 				geometry	<< "#version 450\n"
1486 							<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1487 							<< "layout(${TOPOLOGY}) in;\n"
1488 							<< "layout(points, max_vertices = 1) out;\n"
1489 							<< "layout(set = 0, binding = 3, std430) buffer Buffer1\n"
1490 							<< "{\n"
1491 							<< "  uint result[];\n"
1492 							<< "};\n"
1493 							<< "layout(set = 0, binding = 7, std430) buffer Buffer2\n"
1494 							<< "{\n"
1495 							<< "  uint numSubgroupsExecuted;\n"
1496 							<< "};\n"
1497 							<< "\n"
1498 							<< "void main (void)\n"
1499 							<< "{\n"
1500 							<< "  if (subgroupElect())\n"
1501 							<< "  {\n"
1502 							<< "    result[gl_PrimitiveIDIn] = " << ELECTED_VALUE << ";\n"
1503 							<< "    atomicAdd(numSubgroupsExecuted, 1);\n"
1504 							<< "  }\n"
1505 							<< "  else\n"
1506 							<< "  {\n"
1507 							<< "    result[gl_PrimitiveIDIn] = " << UNELECTED_VALUE << ";\n"
1508 							<< "  }\n"
1509 							<< "  gl_Position = gl_in[0].gl_Position;\n"
1510 							<< "  EmitVertex();\n"
1511 							<< "  EndPrimitive();\n"
1512 							<< "}\n";
1513 				subgroups::addGeometryShadersFromTemplate(geometry.str(), vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u),
1514 														  programCollection.glslSources);
1515 			}
1516 
1517 			{
1518 				std::ostringstream fragment;
1519 				fragment	<< "#version 450\n"
1520 							<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1521 							<< "layout(location = 0) out uint data;\n"
1522 							<< "layout(set = 0, binding = 8, std430) buffer Buffer\n"
1523 							<< "{\n"
1524 							<< "  uint numSubgroupsExecuted;\n"
1525 							<< "};\n"
1526 							<< "void main (void)\n"
1527 							<< "{\n"
1528 							<< "  if (gl_HelperInvocation) return;\n"
1529 							<< "  if (subgroupElect())\n"
1530 							<< "  {\n"
1531 							<< "    data = " << ELECTED_VALUE << ";\n"
1532 							<< "    atomicAdd(numSubgroupsExecuted, 1);\n"
1533 							<< "  }\n"
1534 							<< "  else\n"
1535 							<< "  {\n"
1536 							<< "    data = " << UNELECTED_VALUE << ";\n"
1537 							<< "  }\n"
1538 							<< "}\n";
1539 				programCollection.glslSources.add("fragment")
1540 					<< glu::FragmentSource(fragment.str())<< vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1541 			}
1542 			subgroups::addNoSubgroupShader(programCollection);
1543 		}
1544 	}
1545 	else
1546 	{
1547 		std::ostringstream bdy;
1548 
1549 		switch (caseDef.opType)
1550 		{
1551 			default:
1552 				DE_FATAL("Unhandled op type!");
1553 				break;
1554 			case OPTYPE_SUBGROUP_BARRIER:
1555 			case OPTYPE_SUBGROUP_MEMORY_BARRIER:
1556 			case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
1557 				bdy << "  if (subgroupElect())\n"
1558 					<< "  {\n"
1559 					<< "    tempBuffer[id] = value;\n"
1560 					<< "  }\n"
1561 					<< "  " << getOpTypeName(caseDef.opType) << "();\n"
1562 					<< "  tempResult = tempBuffer[id];\n";
1563 				break;
1564 			case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
1565 				bdy << "  if (subgroupElect())\n"
1566 					<< "  {\n"
1567 					<< "    tempShared[localId] = value;\n"
1568 					<< "  }\n"
1569 					<< "  subgroupMemoryBarrierShared();\n"
1570 					<< "  tempResult = tempShared[localId];\n";
1571 				break;
1572 			case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
1573 				bdy << "  if (subgroupElect())\n"
1574 					<< "  {\n"
1575 					<< "    imageStore(tempImage, ivec2(id, 0), ivec4(value));\n"
1576 					<< "  }\n"
1577 					<< "  subgroupMemoryBarrierImage();\n"
1578 					<< "  tempResult = imageLoad(tempImage, ivec2(id, 0)).x;\n";
1579 				break;
1580 		}
1581 
1582 		if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1583 		{
1584 			std::ostringstream src;
1585 
1586 			src << "#version 450\n"
1587 				<< "#extension GL_KHR_shader_subgroup_basic: enable\n"
1588 				<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
1589 				"local_size_z_id = 2) in;\n"
1590 				<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1591 				<< "{\n"
1592 				<< "  uint result[];\n"
1593 				<< "};\n"
1594 				<< "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
1595 				<< "{\n"
1596 				<< "  uint tempBuffer[];\n"
1597 				<< "};\n"
1598 				<< "layout(set = 0, binding = 2, std430) buffer Buffer3\n"
1599 				<< "{\n"
1600 				<< "  uint value;\n"
1601 				<< "};\n"
1602 				<< "layout(set = 0, binding = 3, r32ui) uniform uimage2D tempImage;\n"
1603 				<< "shared uint tempShared[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
1604 				<< "\n"
1605 				<< "void main (void)\n"
1606 				<< "{\n"
1607 				<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
1608 				<< "  highp uint offset = globalSize.x * ((globalSize.y * "
1609 				"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
1610 				"gl_GlobalInvocationID.x;\n"
1611 				<< "  uint localId = gl_SubgroupID;\n"
1612 				<< "  uint id = globalSize.x * ((globalSize.y * "
1613 				"gl_WorkGroupID.z) + gl_WorkGroupID.y) + "
1614 				"gl_WorkGroupID.x + localId;\n"
1615 				<< "  uint tempResult = 0;\n"
1616 				<< bdy.str()
1617 				<< "  result[offset] = tempResult;\n"
1618 				<< "}\n";
1619 
1620 			programCollection.glslSources.add("comp")
1621 					<< glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1622 		}
1623 		else
1624 		{
1625 			{
1626 				const string vertex =
1627 					"#version 450\n"
1628 					"#extension GL_KHR_shader_subgroup_basic: enable\n"
1629 					"#extension GL_KHR_shader_subgroup_ballot: enable\n"
1630 					"layout(set = 0, binding = 0, std430) buffer Buffer1\n"
1631 					"{\n"
1632 					"  uint result[];\n"
1633 					"};\n"
1634 					"layout(set = 0, binding = 4, std430) buffer Buffer2\n"
1635 					"{\n"
1636 					"  uint tempBuffer[];\n"
1637 					"};\n"
1638 					"layout(set = 0, binding = 5, std430) buffer Buffer3\n"
1639 					"{\n"
1640 					"  uint subgroupID;\n"
1641 					"};\n"
1642 					"layout(set = 0, binding = 6, std430) buffer Buffer4\n"
1643 					"{\n"
1644 					"  uint value;\n"
1645 					"};\n"
1646 					"layout(set = 0, binding = 7, r32ui) uniform uimage2D tempImage;\n"
1647 					"void main (void)\n"
1648 					"{\n"
1649 					"  uint id = 0;\n"
1650 					"  if (subgroupElect())\n"
1651 					"  {\n"
1652 					"    id = atomicAdd(subgroupID, 1);\n"
1653 					"  }\n"
1654 					"  id = subgroupBroadcastFirst(id);\n"
1655 					"  uint localId = id;\n"
1656 					"  uint tempResult = 0;\n"
1657 					+ bdy.str() +
1658 					"  result[gl_VertexIndex] = tempResult;\n"
1659 					"  float pixelSize = 2.0f/1024.0f;\n"
1660 					"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
1661 					"  gl_Position = vec4(float(gl_VertexIndex) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
1662 					"  gl_PointSize = 1.0f;\n"
1663 					"}\n";
1664 				programCollection.glslSources.add("vert")
1665 					<< glu::VertexSource(vertex) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1666 			}
1667 
1668 			{
1669 				const string tesc =
1670 					"#version 450\n"
1671 					"#extension GL_KHR_shader_subgroup_basic: enable\n"
1672 					"#extension GL_KHR_shader_subgroup_ballot: enable\n"
1673 					"layout(vertices=1) out;\n"
1674 					"layout(set = 0, binding = 1, std430) buffer Buffer1\n"
1675 					"{\n"
1676 					"  uint result[];\n"
1677 					"};\n"
1678 					"layout(set = 0, binding = 8, std430) buffer Buffer2\n"
1679 					"{\n"
1680 					"  uint tempBuffer[];\n"
1681 					"};\n"
1682 					"layout(set = 0, binding = 9, std430) buffer Buffer3\n"
1683 					"{\n"
1684 					"  uint subgroupID;\n"
1685 					"};\n"
1686 					"layout(set = 0, binding = 10, std430) buffer Buffer4\n"
1687 					"{\n"
1688 					"  uint value;\n"
1689 					"};\n"
1690 					"layout(set = 0, binding = 11, r32ui) uniform uimage2D tempImage;\n"
1691 					"void main (void)\n"
1692 					"{\n"
1693 					"  uint id = 0;\n"
1694 					"  if (subgroupElect())\n"
1695 					"  {\n"
1696 					"    id = atomicAdd(subgroupID, 1);\n"
1697 					"  }\n"
1698 					"  id = subgroupBroadcastFirst(id);\n"
1699 					"  uint localId = id;\n"
1700 					"  uint tempResult = 0;\n"
1701 					+ bdy.str() +
1702 					"  result[gl_PrimitiveID] = tempResult;\n"
1703 					"  if (gl_InvocationID == 0)\n"
1704 					"  {\n"
1705 					"    gl_TessLevelOuter[0] = 1.0f;\n"
1706 					"    gl_TessLevelOuter[1] = 1.0f;\n"
1707 					"  }\n"
1708 					"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1709 					"}\n";
1710 				programCollection.glslSources.add("tesc")
1711 					<< glu::TessellationControlSource(tesc) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1712 			}
1713 
1714 			{
1715 				const string tese =
1716 					"#version 450\n"
1717 					"#extension GL_KHR_shader_subgroup_basic: enable\n"
1718 					"#extension GL_KHR_shader_subgroup_ballot: enable\n"
1719 					"layout(isolines) in;\n"
1720 					"layout(set = 0, binding = 2, std430) buffer Buffer1\n"
1721 					"{\n"
1722 					"  uint result[];\n"
1723 					"};\n"
1724 					"layout(set = 0, binding = 12, std430) buffer Buffer2\n"
1725 					"{\n"
1726 					"  uint tempBuffer[];\n"
1727 					"};\n"
1728 					"layout(set = 0, binding = 13, std430) buffer Buffer3\n"
1729 					"{\n"
1730 					"  uint subgroupID;\n"
1731 					"};\n"
1732 					"layout(set = 0, binding = 14, std430) buffer Buffer4\n"
1733 					"{\n"
1734 					"  uint value;\n"
1735 					"};\n"
1736 					"layout(set = 0, binding = 15, r32ui) uniform uimage2D tempImage;\n"
1737 					"void main (void)\n"
1738 					"{\n"
1739 					"  uint id = 0;\n"
1740 					"  if (subgroupElect())\n"
1741 					"  {\n"
1742 					"    id = atomicAdd(subgroupID, 1);\n"
1743 					"  }\n"
1744 					"  id = subgroupBroadcastFirst(id);\n"
1745 					"  uint localId = id;\n"
1746 					"  uint tempResult = 0;\n"
1747 					+ bdy.str() +
1748 					"  result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
1749 					"  float pixelSize = 2.0f/1024.0f;\n""  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
1750 					"}\n";
1751 				programCollection.glslSources.add("tese")
1752 					<< glu::TessellationEvaluationSource(tese) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1753 			}
1754 
1755 			{
1756 				const string geometry =
1757 					"#version 450\n"
1758 					"#extension GL_KHR_shader_subgroup_basic: enable\n"
1759 					"#extension GL_KHR_shader_subgroup_ballot: enable\n"
1760 					"layout(${TOPOLOGY}) in;\n"
1761 					"layout(points, max_vertices = 1) out;\n"
1762 					"layout(set = 0, binding = 3, std430) buffer Buffer1\n"
1763 					"{\n"
1764 					"  uint result[];\n"
1765 					"};\n"
1766 					"layout(set = 0, binding = 16, std430) buffer Buffer2\n"
1767 					"{\n"
1768 					"  uint tempBuffer[];\n"
1769 					"};\n"
1770 					"layout(set = 0, binding = 17, std430) buffer Buffer3\n"
1771 					"{\n"
1772 					"  uint subgroupID;\n"
1773 					"};\n"
1774 					"layout(set = 0, binding = 18, std430) buffer Buffer4\n"
1775 					"{\n"
1776 					"  uint value;\n"
1777 					"};\n"
1778 					"layout(set = 0, binding = 19, r32ui) uniform uimage2D tempImage;\n"
1779 					"void main (void)\n"
1780 					"{\n"
1781 					"  uint id = 0;\n"
1782 					"  if (subgroupElect())\n"
1783 					"  {\n"
1784 					"    id = atomicAdd(subgroupID, 1);\n"
1785 					"  }\n"
1786 					"  id = subgroupBroadcastFirst(id);\n"
1787 					"  uint localId = id;\n"
1788 					"  uint tempResult = 0;\n"
1789 					 + bdy.str() +
1790 					"  result[gl_PrimitiveIDIn] = tempResult;\n"
1791 					"  gl_Position = gl_in[0].gl_Position;\n"
1792 					"  EmitVertex();\n"
1793 					"  EndPrimitive();\n"
1794 					"}\n";
1795 				subgroups::addGeometryShadersFromTemplate(geometry, vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u),
1796 														  programCollection.glslSources);
1797 			}
1798 
1799 			{
1800 				const string fragment =
1801 					"#version 450\n"
1802 					"#extension GL_KHR_shader_subgroup_basic: enable\n"
1803 					"#extension GL_KHR_shader_subgroup_ballot: enable\n"
1804 					"layout(location = 0) out uint result;\n"
1805 					"layout(set = 0, binding = 20, std430) buffer Buffer1\n"
1806 					"{\n"
1807 					"  uint tempBuffer[];\n"
1808 					"};\n"
1809 					"layout(set = 0, binding = 21, std430) buffer Buffer2\n"
1810 					"{\n"
1811 					"  uint subgroupID;\n"
1812 					"};\n"
1813 					"layout(set = 0, binding = 22, std430) buffer Buffer3\n"
1814 					"{\n"
1815 					"  uint value;\n"
1816 					"};\n"
1817 					"layout(set = 0, binding = 23, r32ui) uniform uimage2D tempImage;\n"
1818 					"void main (void)\n"
1819 					"{\n"
1820 					"  if (gl_HelperInvocation) return;\n"
1821 					"  uint id = 0;\n"
1822 					"  if (subgroupElect())\n"
1823 					"  {\n"
1824 					"    id = atomicAdd(subgroupID, 1);\n"
1825 					"  }\n"
1826 					"  id = subgroupBroadcastFirst(id);\n"
1827 					"  uint localId = id;\n"
1828 					"  uint tempResult = 0;\n"
1829 					+ bdy.str() +
1830 					"  result = tempResult;\n"
1831 					"}\n";
1832 				programCollection.glslSources.add("fragment")
1833 					<< glu::FragmentSource(fragment)<< vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
1834 			}
1835 
1836 		subgroups::addNoSubgroupShader(programCollection);
1837 		}
1838 	}
1839 }
1840 
supportedCheck(Context & context,CaseDefinition caseDef)1841 void supportedCheck (Context& context, CaseDefinition caseDef)
1842 {
1843 	DE_UNREF(caseDef);
1844 	if (!subgroups::isSubgroupSupported(context))
1845 		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
1846 }
1847 
noSSBOtest(Context & context,const CaseDefinition caseDef)1848 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
1849 {
1850 	if (!subgroups::areSubgroupOperationsSupportedForStage(
1851 				context, caseDef.shaderStage))
1852 	{
1853 		if (subgroups::areSubgroupOperationsRequiredForStage(
1854 					caseDef.shaderStage))
1855 		{
1856 			return tcu::TestStatus::fail(
1857 					   "Shader stage " +
1858 					   subgroups::getShaderStageName(caseDef.shaderStage) +
1859 					   " is required to support subgroup operations!");
1860 		}
1861 		else
1862 		{
1863 			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
1864 		}
1865 	}
1866 
1867 	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BASIC_BIT))
1868 	{
1869 		return tcu::TestStatus::fail(
1870 				   "Subgroup feature " +
1871 				   subgroups::getSubgroupFeatureName(VK_SUBGROUP_FEATURE_BASIC_BIT) +
1872 				   " is a required capability!");
1873 	}
1874 
1875 	if (OPTYPE_ELECT != caseDef.opType && VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1876 	{
1877 		if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
1878 		{
1879 			TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1880 		}
1881 	}
1882 
1883 	const deUint32						inputDatasCount	= OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? 3u : 2u;
1884 	std::vector<subgroups::SSBOData>	inputDatas		(inputDatasCount);
1885 
1886 	inputDatas[0].format = VK_FORMAT_R32_UINT;
1887 	inputDatas[0].layout = subgroups::SSBOData::LayoutStd140;
1888 	inputDatas[0].numElements = SHADER_BUFFER_SIZE/4ull;
1889 	inputDatas[0].initializeType = subgroups::SSBOData::InitializeNonZero;
1890 
1891 	inputDatas[1].format = VK_FORMAT_R32_UINT;
1892 	inputDatas[1].layout = subgroups::SSBOData::LayoutStd140;
1893 	inputDatas[1].numElements = 1ull;
1894 	inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1895 
1896 	if(OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType )
1897 	{
1898 		inputDatas[2].format = VK_FORMAT_R32_UINT;
1899 		inputDatas[2].layout = subgroups::SSBOData::LayoutPacked;
1900 		inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1901 		inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1902 		inputDatas[2].isImage = true;
1903 	}
1904 
1905 	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
1906 	{
1907 		if (OPTYPE_ELECT == caseDef.opType)
1908 			return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1909 		else
1910 			return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount,
1911 				(OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType) ?
1912 					checkVertexPipelineStagesSubgroupBarriersWithImageNoSSBO :
1913 					checkVertexPipelineStagesSubgroupBarriersNoSSBO
1914 			);
1915 	}
1916 	else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
1917 	{
1918 		return subgroups::makeFragmentFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount,
1919 			(OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType) ?
1920 				checkFragmentSubgroupBarriersWithImageNoSSBO :
1921 				checkFragmentSubgroupBarriersNoSSBO
1922 		);
1923 	}
1924 	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
1925 	{
1926 		if (OPTYPE_ELECT == caseDef.opType)
1927 			return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1928 		else
1929 			return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount,
1930 				(OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType) ?
1931 					checkVertexPipelineStagesSubgroupBarriersWithImageNoSSBO :
1932 					checkVertexPipelineStagesSubgroupBarriersNoSSBO
1933 			);
1934 	}
1935 
1936 	if (OPTYPE_ELECT == caseDef.opType)
1937 		return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO, caseDef.shaderStage);
1938 
1939 	return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount,
1940 		(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) ?
1941 			((OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType) ?
1942 				checkVertexPipelineStagesSubgroupBarriersWithImageNoSSBO :
1943 				checkVertexPipelineStagesSubgroupBarriersNoSSBO) :
1944 			((OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType) ?
1945 				checkTessellationEvaluationSubgroupBarriersWithImageNoSSBO :
1946 				checkTessellationEvaluationSubgroupBarriersNoSSBO),
1947 		caseDef.shaderStage);
1948 }
1949 
test(Context & context,const CaseDefinition caseDef)1950 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
1951 {
1952 	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BASIC_BIT))
1953 	{
1954 		return tcu::TestStatus::fail(
1955 					"Subgroup feature " +
1956 					subgroups::getSubgroupFeatureName(VK_SUBGROUP_FEATURE_BASIC_BIT) +
1957 					" is a required capability!");
1958 	}
1959 
1960 	if (OPTYPE_ELECT != caseDef.opType && VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1961 	{
1962 		if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
1963 		{
1964 			TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1965 		}
1966 	}
1967 
1968 	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1969 	{
1970 		if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
1971 		{
1972 				return tcu::TestStatus::fail("Shader stage " +
1973 										subgroups::getShaderStageName(caseDef.shaderStage) +
1974 										" is required to support subgroup operations!");
1975 		}
1976 
1977 		if (OPTYPE_ELECT == caseDef.opType)
1978 		{
1979 			return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkComputeSubgroupElect);
1980 		}
1981 		else
1982 		{
1983 			const deUint32 inputDatasCount = 3;
1984 			subgroups::SSBOData inputDatas[inputDatasCount];
1985 			inputDatas[0].format = VK_FORMAT_R32_UINT;
1986 			inputDatas[0].layout = subgroups::SSBOData::LayoutStd430;
1987 			inputDatas[0].numElements = SHADER_BUFFER_SIZE;
1988 			inputDatas[0].initializeType = subgroups::SSBOData::InitializeNone;
1989 
1990 			inputDatas[1].format = VK_FORMAT_R32_UINT;
1991 			inputDatas[1].layout = subgroups::SSBOData::LayoutStd430;
1992 			inputDatas[1].numElements = 1;
1993 			inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1994 
1995 			inputDatas[2].format = VK_FORMAT_R32_UINT;
1996 			inputDatas[2].layout = subgroups::SSBOData::LayoutPacked;
1997 			inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1998 			inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1999 			inputDatas[2].isImage = true;
2000 
2001 			return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, inputDatas, inputDatasCount, checkComputeSubgroupBarriers);
2002 		}
2003 	}
2004 	else
2005 	{
2006 		if (!subgroups::isFragmentSSBOSupportedForDevice(context))
2007 		{
2008 			TCU_THROW(NotSupportedError, "Subgroup basic operation require that the fragment stage be able to write to SSBOs!");
2009 		}
2010 
2011 		VkPhysicalDeviceSubgroupProperties subgroupProperties;
2012 		subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
2013 		subgroupProperties.pNext = DE_NULL;
2014 
2015 		VkPhysicalDeviceProperties2 properties;
2016 		properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
2017 		properties.pNext = &subgroupProperties;
2018 
2019 		context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
2020 
2021 		VkShaderStageFlagBits stages = (VkShaderStageFlagBits)(caseDef.shaderStage  & subgroupProperties.supportedStages);
2022 
2023 		if ( VK_SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
2024 		{
2025 			if ( (stages & VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
2026 				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
2027 			else
2028 				stages = VK_SHADER_STAGE_FRAGMENT_BIT;
2029 		}
2030 
2031 		if ((VkShaderStageFlagBits)0u == stages)
2032 			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
2033 
2034 		if (OPTYPE_ELECT == caseDef.opType)
2035 		{
2036 			const deUint32 inputCount = 5u;
2037 			subgroups::SSBOData inputData[inputCount];
2038 
2039 			inputData[0].format			= VK_FORMAT_R32_UINT;
2040 			inputData[0].layout			 = subgroups::SSBOData::LayoutStd430;
2041 			inputData[0].numElements	= 1;
2042 			inputData[0].initializeType	= subgroups::SSBOData::InitializeZero;
2043 			inputData[0].binding		= 4u;
2044 			inputData[0].stages			= VK_SHADER_STAGE_VERTEX_BIT;
2045 
2046 			inputData[1].format			= VK_FORMAT_R32_UINT;
2047 			inputData[1].layout			 = subgroups::SSBOData::LayoutStd430;
2048 			inputData[1].numElements	= 1;
2049 			inputData[1].initializeType	= subgroups::SSBOData::InitializeZero;
2050 			inputData[1].binding		= 5u;
2051 			inputData[1].stages			= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
2052 
2053 			inputData[2].format			= VK_FORMAT_R32_UINT;
2054 			inputData[2].layout			= subgroups::SSBOData::LayoutStd430;
2055 			inputData[2].numElements	= 1;
2056 			inputData[2].initializeType	= subgroups::SSBOData::InitializeZero;
2057 			inputData[2].binding		= 6u;
2058 			inputData[2].stages			= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
2059 
2060 			inputData[3].format			= VK_FORMAT_R32_UINT;
2061 			inputData[3].layout			= subgroups::SSBOData::LayoutStd430;
2062 			inputData[3].numElements	= 1;
2063 			inputData[3].initializeType	= subgroups::SSBOData::InitializeZero;
2064 			inputData[3].binding		= 7u;
2065 			inputData[3].stages			= VK_SHADER_STAGE_GEOMETRY_BIT;
2066 
2067 			inputData[4].format			= VK_FORMAT_R32_UINT;
2068 			inputData[4].layout			= subgroups::SSBOData::LayoutStd430;
2069 			inputData[4].numElements	= 1;
2070 			inputData[4].initializeType	= subgroups::SSBOData::InitializeZero;
2071 			inputData[4].binding		= 8u;
2072 			inputData[4].stages			= VK_SHADER_STAGE_FRAGMENT_BIT;
2073 
2074 			return subgroups::allStages(context, VK_FORMAT_R32_UINT, inputData, inputCount, checkVertexPipelineStagesSubgroupElect, stages);
2075 		}
2076 		else
2077 		{
2078 			const VkShaderStageFlagBits stagesBits[] =
2079 			{
2080 				VK_SHADER_STAGE_VERTEX_BIT,
2081 				VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
2082 				VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
2083 				VK_SHADER_STAGE_GEOMETRY_BIT,
2084 				VK_SHADER_STAGE_FRAGMENT_BIT,
2085 			};
2086 
2087 			const deUint32 inputDatasCount = DE_LENGTH_OF_ARRAY(stagesBits) * 4u;
2088 			subgroups::SSBOData inputDatas[inputDatasCount];
2089 
2090 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stagesBits); ++ndx)
2091 			{
2092 				const deUint32 index = ndx*4;
2093 				inputDatas[index].format				= VK_FORMAT_R32_UINT;
2094 				inputDatas[index].layout				= subgroups::SSBOData::LayoutStd430;
2095 				inputDatas[index].numElements			= SHADER_BUFFER_SIZE;
2096 				inputDatas[index].initializeType		= subgroups::SSBOData::InitializeNonZero;
2097 				inputDatas[index].binding				= index + 4u;
2098 				inputDatas[index].stages				= stagesBits[ndx];
2099 
2100 				inputDatas[index + 1].format			= VK_FORMAT_R32_UINT;
2101 				inputDatas[index + 1].layout			= subgroups::SSBOData::LayoutStd430;
2102 				inputDatas[index + 1].numElements		= 1;
2103 				inputDatas[index + 1].initializeType	= subgroups::SSBOData::InitializeZero;
2104 				inputDatas[index + 1].binding			= index + 5u;
2105 				inputDatas[index + 1].stages			= stagesBits[ndx];
2106 
2107 				inputDatas[index + 2].format			= VK_FORMAT_R32_UINT;
2108 				inputDatas[index + 2].layout			= subgroups::SSBOData::LayoutStd430;
2109 				inputDatas[index + 2].numElements		= 1;
2110 				inputDatas[index + 2].initializeType	= subgroups::SSBOData::InitializeNonZero;
2111 				inputDatas[index + 2].binding			= index + 6u;
2112 				inputDatas[index + 2].stages			= stagesBits[ndx];
2113 
2114 				inputDatas[index + 3].format			= VK_FORMAT_R32_UINT;
2115 				inputDatas[index + 3].layout			= subgroups::SSBOData::LayoutStd430;
2116 				inputDatas[index + 3].numElements		= SHADER_BUFFER_SIZE;
2117 				inputDatas[index + 3].initializeType	= subgroups::SSBOData::InitializeNone;
2118 				inputDatas[index + 3].isImage			= true;
2119 				inputDatas[index + 3].binding			= index + 7u;
2120 				inputDatas[index + 3].stages			= stagesBits[ndx];
2121 			}
2122 
2123 			return subgroups::allStages(context, VK_FORMAT_R32_UINT, inputDatas, inputDatasCount, checkVertexPipelineStagesSubgroupBarriers, stages);
2124 		}
2125 	}
2126 }
2127 }
2128 
2129 namespace vkt
2130 {
2131 namespace subgroups
2132 {
createSubgroupsBasicTests(tcu::TestContext & testCtx)2133 tcu::TestCaseGroup* createSubgroupsBasicTests(tcu::TestContext& testCtx)
2134 {
2135 	de::MovePtr<tcu::TestCaseGroup> graphicGroup(new tcu::TestCaseGroup(
2136 		testCtx, "graphics", "Subgroup basic category tests: graphics"));
2137 	de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(
2138 		testCtx, "compute", "Subgroup basic category tests: compute"));
2139 	de::MovePtr<tcu::TestCaseGroup> framebufferGroup(new tcu::TestCaseGroup(
2140 		testCtx, "framebuffer", "Subgroup basic category tests: framebuffer"));
2141 
2142 
2143 	const VkShaderStageFlags stages[] =
2144 	{
2145 		VK_SHADER_STAGE_FRAGMENT_BIT,
2146 		VK_SHADER_STAGE_VERTEX_BIT,
2147 		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
2148 		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
2149 		VK_SHADER_STAGE_GEOMETRY_BIT,
2150 	};
2151 
2152 	for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
2153 	{
2154 		const std::string op = de::toLower(getOpTypeName(opTypeIndex));
2155 
2156 		{
2157 			const CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_COMPUTE_BIT};
2158 			addFunctionCaseWithPrograms(computeGroup.get(), op, "",
2159 										supportedCheck, initPrograms, test, caseDef);
2160 		}
2161 
2162 		if (OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED == opTypeIndex)
2163 		{
2164 			// Shared isn't available in non compute shaders.
2165 			continue;
2166 		}
2167 
2168 		{
2169 			const CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_ALL_GRAPHICS};
2170 			addFunctionCaseWithPrograms(graphicGroup.get(),
2171 										op, "",
2172 										supportedCheck, initPrograms, test, caseDef);
2173 		}
2174 
2175 		if (OPTYPE_ELECT == opTypeIndex)
2176 		{
2177 			for (int stageIndex = 1; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
2178 			{
2179 				const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex]};
2180 				addFunctionCaseWithPrograms(framebufferGroup.get(),
2181 							op + "_" + getShaderStageName(caseDef.shaderStage), "",
2182 							supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
2183 			}
2184 		}
2185 		else
2186 		{
2187 			for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
2188 			{
2189 				const CaseDefinition caseDefFrag = {opTypeIndex, stages[stageIndex]};
2190 				addFunctionCaseWithPrograms(framebufferGroup.get(),
2191 							op + "_" + getShaderStageName(caseDefFrag.shaderStage), "",
2192 							supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDefFrag);
2193 			}
2194 		}
2195 
2196 	}
2197 
2198 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
2199 		testCtx, "basic", "Subgroup basic category tests"));
2200 
2201 	group->addChild(graphicGroup.release());
2202 	group->addChild(computeGroup.release());
2203 	group->addChild(framebufferGroup.release());
2204 
2205 	return group.release();
2206 }
2207 
2208 } // subgroups
2209 } // vkt
2210