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 "vktSubgroupsBallotTests.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 {
checkVertexPipelineStages(std::vector<const void * > datas,deUint32 width,deUint32)38 static bool checkVertexPipelineStages(std::vector<const void*> datas,
39 									  deUint32 width, deUint32)
40 {
41 	return vkt::subgroups::check(datas, width, 0x7);
42 }
43 
checkCompute(std::vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32)44 static bool checkCompute(std::vector<const void*> datas,
45 						 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
46 						 deUint32)
47 {
48 	return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 0x7);
49 }
50 
51 struct CaseDefinition
52 {
53 	VkShaderStageFlags	shaderStage;
54 };
55 
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)56 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
57 {
58 	const vk::SpirVAsmBuildOptions	buildOptionsSpr	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3);
59 	std::ostringstream				subgroupSizeStr;
60 	subgroupSizeStr << subgroups::maxSupportedSubgroupSize();
61 
62 	subgroups::setFragmentShaderFrameBuffer(programCollection);
63 
64 	if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
65 		subgroups::setVertexShaderFrameBuffer(programCollection);
66 
67 	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
68 	{
69 		/*
70 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
71 			"layout(location = 0) in highp vec4 in_position;\n"
72 			"layout(location = 0) out float out_color;\n"
73 			"layout(set = 0, binding = 0) uniform Buffer1\n"
74 			"{\n"
75 			"  uint data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
76 			"};\n"
77 			"\n"
78 			"void main (void)\n"
79 			"{\n"
80 			"  uint tempResult = 0;\n"
81 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
82 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
83 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
84 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
85 			"  out_color = float(tempResult);\n"
86 			"  gl_Position = in_position;\n"
87 			"  gl_PointSize = 1.0f;\n"
88 			"}\n";
89 		*/
90 		const string vertex =
91 			"; SPIR-V\n"
92 			"; Version: 1.3\n"
93 			"; Generator: Khronos Glslang Reference Front End; 2\n"
94 			"; Bound: 76\n"
95 			"; Schema: 0\n"
96 			"OpCapability Shader\n"
97 			"OpCapability GroupNonUniform\n"
98 			"OpCapability GroupNonUniformBallot\n"
99 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
100 			"OpMemoryModel Logical GLSL450\n"
101 			"OpEntryPoint Vertex %4 \"main\" %35 %62 %70 %72\n"
102 			"OpDecorate %30 ArrayStride 16\n"
103 			"OpMemberDecorate %31 0 Offset 0\n"
104 			"OpDecorate %31 Block\n"
105 			"OpDecorate %33 DescriptorSet 0\n"
106 			"OpDecorate %33 Binding 0\n"
107 			"OpDecorate %35 RelaxedPrecision\n"
108 			"OpDecorate %35 BuiltIn SubgroupLocalInvocationId\n"
109 			"OpDecorate %36 RelaxedPrecision\n"
110 			"OpDecorate %62 Location 0\n"
111 			"OpMemberDecorate %68 0 BuiltIn Position\n"
112 			"OpMemberDecorate %68 1 BuiltIn PointSize\n"
113 			"OpMemberDecorate %68 2 BuiltIn ClipDistance\n"
114 			"OpMemberDecorate %68 3 BuiltIn CullDistance\n"
115 			"OpDecorate %68 Block\n"
116 			"OpDecorate %72 Location 0\n"
117 			"%2 = OpTypeVoid\n"
118 			"%3 = OpTypeFunction %2\n"
119 			"%6 = OpTypeInt 32 0\n"
120 			"%7 = OpTypePointer Function %6\n"
121 			"%9 = OpConstant %6 0\n"
122 			"%10 = OpTypeVector %6 4\n"
123 			"%11 = OpConstantComposite %10 %9 %9 %9 %9\n"
124 			"%12 = OpTypeBool\n"
125 			"%13 = OpConstantTrue %12\n"
126 			"%14 = OpConstant %6 3\n"
127 			"%16 = OpTypeVector %12 4\n"
128 			"%20 = OpTypeInt 32 1\n"
129 			"%21 = OpConstant %20 1\n"
130 			"%22 = OpConstant %20 0\n"
131 			"%27 = OpTypePointer Function %12\n"
132 			"%29 = OpConstant %6 " + subgroupSizeStr.str() + "\n"
133 			"%30 = OpTypeArray %6 %29\n"
134 			"%31 = OpTypeStruct %30\n"
135 			"%32 = OpTypePointer Uniform %31\n"
136 			"%33 = OpVariable %32 Uniform\n"
137 			"%34 = OpTypePointer Input %6\n"
138 			"%35 = OpVariable %34 Input\n"
139 			"%37 = OpTypePointer Uniform %6\n"
140 			"%46 = OpConstant %20 2\n"
141 			"%51 = OpConstantFalse %12\n"
142 			"%55 = OpConstant %20 4\n"
143 			"%60 = OpTypeFloat 32\n"
144 			"%61 = OpTypePointer Output %60\n"
145 			"%62 = OpVariable %61 Output\n"
146 			"%65 = OpTypeVector %60 4\n"
147 			"%66 = OpConstant %6 1\n"
148 			"%67 = OpTypeArray %60 %66\n"
149 			"%68 = OpTypeStruct %65 %60 %67 %67\n"
150 			"%69 = OpTypePointer Output %68\n"
151 			"%70 = OpVariable %69 Output\n"
152 			"%71 = OpTypePointer Input %65\n"
153 			"%72 = OpVariable %71 Input\n"
154 			"%74 = OpTypePointer Output %65\n"
155 			"%76 = OpConstant %60 1\n"
156 			"%4 = OpFunction %2 None %3\n"
157 			"%5 = OpLabel\n"
158 			"%8 = OpVariable %7 Function\n"
159 			"%28 = OpVariable %27 Function\n"
160 			"OpStore %8 %9\n"
161 			"%15 = OpGroupNonUniformBallot %10 %14 %13\n"
162 			"%17 = OpIEqual %16 %11 %15\n"
163 			"%18 = OpAll %12 %17\n"
164 			"%19 = OpLogicalNot %12 %18\n"
165 			"%23 = OpSelect %20 %19 %21 %22\n"
166 			"%24 = OpBitcast %6 %23\n"
167 			"%25 = OpLoad %6 %8\n"
168 			"%26 = OpBitwiseOr %6 %25 %24\n"
169 			"OpStore %8 %26\n"
170 			"%36 = OpLoad %6 %35\n"
171 			"%38 = OpAccessChain %37 %33 %22 %36\n"
172 			"%39 = OpLoad %6 %38\n"
173 			"%40 = OpINotEqual %12 %39 %9\n"
174 			"OpStore %28 %40\n"
175 			"%41 = OpLoad %12 %28\n"
176 			"%42 = OpGroupNonUniformBallot %10 %14 %41\n"
177 			"%43 = OpIEqual %16 %11 %42\n"
178 			"%44 = OpAll %12 %43\n"
179 			"%45 = OpLogicalNot %12 %44\n"
180 			"%47 = OpSelect %20 %45 %46 %22\n"
181 			"%48 = OpBitcast %6 %47\n"
182 			"%49 = OpLoad %6 %8\n"
183 			"%50 = OpBitwiseOr %6 %49 %48\n"
184 			"OpStore %8 %50\n"
185 			"%52 = OpGroupNonUniformBallot %10 %14 %51\n"
186 			"%53 = OpIEqual %16 %11 %52\n"
187 			"%54 = OpAll %12 %53\n"
188 			"%56 = OpSelect %20 %54 %55 %22\n"
189 			"%57 = OpBitcast %6 %56\n"
190 			"%58 = OpLoad %6 %8\n"
191 			"%59 = OpBitwiseOr %6 %58 %57\n"
192 			"OpStore %8 %59\n"
193 			"%63 = OpLoad %6 %8\n"
194 			"%64 = OpConvertUToF %60 %63\n"
195 			"OpStore %62 %64\n"
196 			"%73 = OpLoad %65 %72\n"
197 			"%75 = OpAccessChain %74 %70 %22\n"
198 			"OpStore %75 %73\n"
199 			"%77 = OpAccessChain %61 %70 %21\n"
200 			"OpStore %77 %76\n"
201 			"OpReturn\n"
202 			"OpFunctionEnd\n";
203 		programCollection.spirvAsmSources.add("vert") << vertex << buildOptionsSpr;
204 	}
205 	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
206 	{
207 		/*
208 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
209 			"layout(points) in;\n"
210 			"layout(points, max_vertices = 1) out;\n"
211 			"layout(location = 0) out float out_color;\n"
212 			"layout(set = 0, binding = 0) uniform Buffer1\n"
213 			"{\n"
214 			"  uint data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
215 			"};\n"
216 			"\n"
217 			"void main (void)\n"
218 			"{\n"
219 			"  uint tempResult = 0;\n"
220 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
221 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
222 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
223 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
224 			"  out_color = float(tempResult);\n"
225 			"  gl_Position = gl_in[0].gl_Position;\n"
226 			"  EmitVertex();\n"
227 			"  EndPrimitive();\n"
228 			"}\n";
229 		*/
230 		const string geometry =
231 			"; SPIR-V\n"
232 			"; Version: 1.3\n"
233 			"; Generator: Khronos Glslang Reference Front End; 2\n"
234 			"; Bound: 80\n"
235 			"; Schema: 0\n"
236 			"OpCapability Geometry\n"
237 			"OpCapability GroupNonUniform\n"
238 			"OpCapability GroupNonUniformBallot\n"
239 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
240 			"OpMemoryModel Logical GLSL450\n"
241 			"OpEntryPoint Geometry %4 \"main\" %35 %62 %70 %74\n"
242 			"OpExecutionMode %4 InputPoints\n"
243 			"OpExecutionMode %4 Invocations 1\n"
244 			"OpExecutionMode %4 OutputPoints\n"
245 			"OpExecutionMode %4 OutputVertices 1\n"
246 			"OpDecorate %30 ArrayStride 16\n"
247 			"OpMemberDecorate %31 0 Offset 0\n"
248 			"OpDecorate %31 Block\n"
249 			"OpDecorate %33 DescriptorSet 0\n"
250 			"OpDecorate %33 Binding 0\n"
251 			"OpDecorate %35 RelaxedPrecision\n"
252 			"OpDecorate %35 BuiltIn SubgroupLocalInvocationId\n"
253 			"OpDecorate %36 RelaxedPrecision\n"
254 			"OpDecorate %62 Location 0\n"
255 			"OpMemberDecorate %68 0 BuiltIn Position\n"
256 			"OpMemberDecorate %68 1 BuiltIn PointSize\n"
257 			"OpMemberDecorate %68 2 BuiltIn ClipDistance\n"
258 			"OpMemberDecorate %68 3 BuiltIn CullDistance\n"
259 			"OpDecorate %68 Block\n"
260 			"OpMemberDecorate %71 0 BuiltIn Position\n"
261 			"OpMemberDecorate %71 1 BuiltIn PointSize\n"
262 			"OpMemberDecorate %71 2 BuiltIn ClipDistance\n"
263 			"OpMemberDecorate %71 3 BuiltIn CullDistance\n"
264 			"OpDecorate %71 Block\n"
265 			"%2 = OpTypeVoid\n"
266 			"%3 = OpTypeFunction %2\n"
267 			"%6 = OpTypeInt 32 0\n"
268 			"%7 = OpTypePointer Function %6\n"
269 			"%9 = OpConstant %6 0\n"
270 			"%10 = OpTypeVector %6 4\n"
271 			"%11 = OpConstantComposite %10 %9 %9 %9 %9\n"
272 			"%12 = OpTypeBool\n"
273 			"%13 = OpConstantTrue %12\n"
274 			"%14 = OpConstant %6 3\n"
275 			"%16 = OpTypeVector %12 4\n"
276 			"%20 = OpTypeInt 32 1\n"
277 			"%21 = OpConstant %20 1\n"
278 			"%22 = OpConstant %20 0\n"
279 			"%27 = OpTypePointer Function %12\n"
280 			"%29 = OpConstant %6 " + subgroupSizeStr.str() + "\n"
281 			"%30 = OpTypeArray %6 %29\n"
282 			"%31 = OpTypeStruct %30\n"
283 			"%32 = OpTypePointer Uniform %31\n"
284 			"%33 = OpVariable %32 Uniform\n"
285 			"%34 = OpTypePointer Input %6\n"
286 			"%35 = OpVariable %34 Input\n"
287 			"%37 = OpTypePointer Uniform %6\n"
288 			"%46 = OpConstant %20 2\n"
289 			"%51 = OpConstantFalse %12\n"
290 			"%55 = OpConstant %20 4\n"
291 			"%60 = OpTypeFloat 32\n"
292 			"%61 = OpTypePointer Output %60\n"
293 			"%62 = OpVariable %61 Output\n"
294 			"%65 = OpTypeVector %60 4\n"
295 			"%66 = OpConstant %6 1\n"
296 			"%67 = OpTypeArray %60 %66\n"
297 			"%68 = OpTypeStruct %65 %60 %67 %67\n"
298 			"%69 = OpTypePointer Output %68\n"
299 			"%70 = OpVariable %69 Output\n"
300 			"%71 = OpTypeStruct %65 %60 %67 %67\n"
301 			"%72 = OpTypeArray %71 %66\n"
302 			"%73 = OpTypePointer Input %72\n"
303 			"%74 = OpVariable %73 Input\n"
304 			"%75 = OpTypePointer Input %65\n"
305 			"%78 = OpTypePointer Output %65\n"
306 			"%4 = OpFunction %2 None %3\n"
307 			"%5 = OpLabel\n"
308 			"%8 = OpVariable %7 Function\n"
309 			"%28 = OpVariable %27 Function\n"
310 			"OpStore %8 %9\n"
311 			"%15 = OpGroupNonUniformBallot %10 %14 %13\n"
312 			"%17 = OpIEqual %16 %11 %15\n"
313 			"%18 = OpAll %12 %17\n"
314 			"%19 = OpLogicalNot %12 %18\n"
315 			"%23 = OpSelect %20 %19 %21 %22\n"
316 			"%24 = OpBitcast %6 %23\n"
317 			"%25 = OpLoad %6 %8\n"
318 			"%26 = OpBitwiseOr %6 %25 %24\n"
319 			"OpStore %8 %26\n"
320 			"%36 = OpLoad %6 %35\n"
321 			"%38 = OpAccessChain %37 %33 %22 %36\n"
322 			"%39 = OpLoad %6 %38\n"
323 			"%40 = OpINotEqual %12 %39 %9\n"
324 			"OpStore %28 %40\n"
325 			"%41 = OpLoad %12 %28\n"
326 			"%42 = OpGroupNonUniformBallot %10 %14 %41\n"
327 			"%43 = OpIEqual %16 %11 %42\n"
328 			"%44 = OpAll %12 %43\n"
329 			"%45 = OpLogicalNot %12 %44\n"
330 			"%47 = OpSelect %20 %45 %46 %22\n"
331 			"%48 = OpBitcast %6 %47\n"
332 			"%49 = OpLoad %6 %8\n"
333 			"%50 = OpBitwiseOr %6 %49 %48\n"
334 			"OpStore %8 %50\n"
335 			"%52 = OpGroupNonUniformBallot %10 %14 %51\n"
336 			"%53 = OpIEqual %16 %11 %52\n"
337 			"%54 = OpAll %12 %53\n"
338 			"%56 = OpSelect %20 %54 %55 %22\n"
339 			"%57 = OpBitcast %6 %56\n"
340 			"%58 = OpLoad %6 %8\n"
341 			"%59 = OpBitwiseOr %6 %58 %57\n"
342 			"OpStore %8 %59\n"
343 			"%63 = OpLoad %6 %8\n"
344 			"%64 = OpConvertUToF %60 %63\n"
345 			"OpStore %62 %64\n"
346 			"%76 = OpAccessChain %75 %74 %22 %22\n"
347 			"%77 = OpLoad %65 %76\n"
348 			"%79 = OpAccessChain %78 %70 %22\n"
349 			"OpStore %79 %77\n"
350 			"OpEmitVertex\n"
351 			"OpEndPrimitive\n"
352 			"OpReturn\n"
353 			"OpFunctionEnd\n";
354 		programCollection.spirvAsmSources.add("geometry") << geometry << buildOptionsSpr;
355 	}
356 	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
357 	{
358 		/*
359 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
360 			"layout(vertices = 2) out;\n"
361 			"layout(location = 0) out float out_color[];\n"
362 			"layout(set = 0, binding = 0) uniform Buffer1\n"
363 			"{\n"
364 			"  uint data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
365 			"};\n"
366 			"\n"
367 			"void main (void)\n"
368 			"{\n"
369 			"  if (gl_InvocationID == 0)\n"
370 			  {\n"
371 			"    gl_TessLevelOuter[0] = 1.0f;\n"
372 			"    gl_TessLevelOuter[1] = 1.0f;\n"
373 			"  }\n"
374 			"  uint tempResult = 0;\n"
375 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
376 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
377 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
378 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
379 			"  out_color[gl_InvocationID] = float(tempResult);\n"
380 			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
381 			"}\n";
382 		*/
383 		const string controlSource =
384 			"; SPIR-V\n"
385 			"; Version: 1.3\n"
386 			"; Generator: Khronos Glslang Reference Front End; 2\n"
387 			"; Bound: 102\n"
388 			"; Schema: 0\n"
389 			"OpCapability Tessellation\n"
390 			"OpCapability GroupNonUniform\n"
391 			"OpCapability GroupNonUniformBallot\n"
392 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
393 			"OpMemoryModel Logical GLSL450\n"
394 			"OpEntryPoint TessellationControl %4 \"main\" %8 %20 %50 %78 %89 %95\n"
395 			"OpExecutionMode %4 OutputVertices 2\n"
396 			"OpDecorate %8 BuiltIn InvocationId\n"
397 			"OpDecorate %20 Patch\n"
398 			"OpDecorate %20 BuiltIn TessLevelOuter\n"
399 			"OpDecorate %45 ArrayStride 16\n"
400 			"OpMemberDecorate %46 0 Offset 0\n"
401 			"OpDecorate %46 Block\n"
402 			"OpDecorate %48 DescriptorSet 0\n"
403 			"OpDecorate %48 Binding 0\n"
404 			"OpDecorate %50 RelaxedPrecision\n"
405 			"OpDecorate %50 BuiltIn SubgroupLocalInvocationId\n"
406 			"OpDecorate %51 RelaxedPrecision\n"
407 			"OpDecorate %78 Location 0\n"
408 			"OpMemberDecorate %86 0 BuiltIn Position\n"
409 			"OpMemberDecorate %86 1 BuiltIn PointSize\n"
410 			"OpMemberDecorate %86 2 BuiltIn ClipDistance\n"
411 			"OpMemberDecorate %86 3 BuiltIn CullDistance\n"
412 			"OpDecorate %86 Block\n"
413 			"OpMemberDecorate %91 0 BuiltIn Position\n"
414 			"OpMemberDecorate %91 1 BuiltIn PointSize\n"
415 			"OpMemberDecorate %91 2 BuiltIn ClipDistance\n"
416 			"OpMemberDecorate %91 3 BuiltIn CullDistance\n"
417 			"OpDecorate %91 Block\n"
418 			"%2 = OpTypeVoid\n"
419 			"%3 = OpTypeFunction %2\n"
420 			"%6 = OpTypeInt 32 1\n"
421 			"%7 = OpTypePointer Input %6\n"
422 			"%8 = OpVariable %7 Input\n"
423 			"%10 = OpConstant %6 0\n"
424 			"%11 = OpTypeBool\n"
425 			"%15 = OpTypeFloat 32\n"
426 			"%16 = OpTypeInt 32 0\n"
427 			"%17 = OpConstant %16 4\n"
428 			"%18 = OpTypeArray %15 %17\n"
429 			"%19 = OpTypePointer Output %18\n"
430 			"%20 = OpVariable %19 Output\n"
431 			"%21 = OpConstant %15 1\n"
432 			"%22 = OpTypePointer Output %15\n"
433 			"%24 = OpConstant %6 1\n"
434 			"%26 = OpTypePointer Function %16\n"
435 			"%28 = OpConstant %16 0\n"
436 			"%29 = OpTypeVector %16 4\n"
437 			"%30 = OpConstantComposite %29 %28 %28 %28 %28\n"
438 			"%31 = OpConstantTrue %11\n"
439 			"%32 = OpConstant %16 3\n"
440 			"%34 = OpTypeVector %11 4\n"
441 			"%42 = OpTypePointer Function %11\n"
442 			"%44 = OpConstant %16 " + subgroupSizeStr.str() + "\n"
443 			"%45 = OpTypeArray %16 %44\n"
444 			"%46 = OpTypeStruct %45\n"
445 			"%47 = OpTypePointer Uniform %46\n"
446 			"%48 = OpVariable %47 Uniform\n"
447 			"%49 = OpTypePointer Input %16\n"
448 			"%50 = OpVariable %49 Input\n"
449 			"%52 = OpTypePointer Uniform %16\n"
450 			"%61 = OpConstant %6 2\n"
451 			"%66 = OpConstantFalse %11\n"
452 			"%70 = OpConstant %6 4\n"
453 			"%75 = OpConstant %16 2\n"
454 			"%76 = OpTypeArray %15 %75\n"
455 			"%77 = OpTypePointer Output %76\n"
456 			"%78 = OpVariable %77 Output\n"
457 			"%83 = OpTypeVector %15 4\n"
458 			"%84 = OpConstant %16 1\n"
459 			"%85 = OpTypeArray %15 %84\n"
460 			"%86 = OpTypeStruct %83 %15 %85 %85\n"
461 			"%87 = OpTypeArray %86 %75\n"
462 			"%88 = OpTypePointer Output %87\n"
463 			"%89 = OpVariable %88 Output\n"
464 			"%91 = OpTypeStruct %83 %15 %85 %85\n"
465 			"%92 = OpConstant %16 32\n"
466 			"%93 = OpTypeArray %91 %92\n"
467 			"%94 = OpTypePointer Input %93\n"
468 			"%95 = OpVariable %94 Input\n"
469 			"%97 = OpTypePointer Input %83\n"
470 			"%100 = OpTypePointer Output %83\n"
471 			"%4 = OpFunction %2 None %3\n"
472 			"%5 = OpLabel\n"
473 			"%27 = OpVariable %26 Function\n"
474 			"%43 = OpVariable %42 Function\n"
475 			"%9 = OpLoad %6 %8\n"
476 			"%12 = OpIEqual %11 %9 %10\n"
477 			"OpSelectionMerge %14 None\n"
478 			"OpBranchConditional %12 %13 %14\n"
479 			"%13 = OpLabel\n"
480 			"%23 = OpAccessChain %22 %20 %10\n"
481 			"OpStore %23 %21\n"
482 			"%25 = OpAccessChain %22 %20 %24\n"
483 			"OpStore %25 %21\n"
484 			"OpBranch %14\n"
485 			"%14 = OpLabel\n"
486 			"OpStore %27 %28\n"
487 			"%33 = OpGroupNonUniformBallot %29 %32 %31\n"
488 			"%35 = OpIEqual %34 %30 %33\n"
489 			"%36 = OpAll %11 %35\n"
490 			"%37 = OpLogicalNot %11 %36\n"
491 			"%38 = OpSelect %6 %37 %24 %10\n"
492 			"%39 = OpBitcast %16 %38\n"
493 			"%40 = OpLoad %16 %27\n"
494 			"%41 = OpBitwiseOr %16 %40 %39\n"
495 			"OpStore %27 %41\n"
496 			"%51 = OpLoad %16 %50\n"
497 			"%53 = OpAccessChain %52 %48 %10 %51\n"
498 			"%54 = OpLoad %16 %53\n"
499 			"%55 = OpINotEqual %11 %54 %28\n"
500 			"OpStore %43 %55\n"
501 			"%56 = OpLoad %11 %43\n"
502 			"%57 = OpGroupNonUniformBallot %29 %32 %56\n"
503 			"%58 = OpIEqual %34 %30 %57\n"
504 			"%59 = OpAll %11 %58\n"
505 			"%60 = OpLogicalNot %11 %59\n"
506 			"%62 = OpSelect %6 %60 %61 %10\n"
507 			"%63 = OpBitcast %16 %62\n"
508 			"%64 = OpLoad %16 %27\n"
509 			"%65 = OpBitwiseOr %16 %64 %63\n"
510 			"OpStore %27 %65\n"
511 			"%67 = OpGroupNonUniformBallot %29 %32 %66\n"
512 			"%68 = OpIEqual %34 %30 %67\n"
513 			"%69 = OpAll %11 %68\n"
514 			"%71 = OpSelect %6 %69 %70 %10\n"
515 			"%72 = OpBitcast %16 %71\n"
516 			"%73 = OpLoad %16 %27\n"
517 			"%74 = OpBitwiseOr %16 %73 %72\n"
518 			"OpStore %27 %74\n"
519 			"%79 = OpLoad %6 %8\n"
520 			"%80 = OpLoad %16 %27\n"
521 			"%81 = OpConvertUToF %15 %80\n"
522 			"%82 = OpAccessChain %22 %78 %79\n"
523 			"OpStore %82 %81\n"
524 			"%90 = OpLoad %6 %8\n"
525 			"%96 = OpLoad %6 %8\n"
526 			"%98 = OpAccessChain %97 %95 %96 %10\n"
527 			"%99 = OpLoad %83 %98\n"
528 			"%101 = OpAccessChain %100 %89 %90 %10\n"
529 			"OpStore %101 %99\n"
530 			"OpReturn\n"
531 			"OpFunctionEnd\n";
532 
533 		programCollection.spirvAsmSources.add("tesc") << controlSource << buildOptionsSpr;
534 		subgroups::setTesEvalShaderFrameBuffer(programCollection);
535 
536 	}
537 	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
538 	{
539 		/*
540 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
541 			"layout(isolines, equal_spacing, ccw ) in;\n"
542 			"layout(location = 0) out float out_color;\n"
543 			"layout(set = 0, binding = 0) uniform Buffer1\n"
544 			"{\n"
545 			"  uint data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
546 			"};\n"
547 			"\n"
548 			"void main (void)\n"
549 			"{\n"
550 			"  uint tempResult = 0;\n"
551 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
552 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
553 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
554 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
555 			"  out_color = float(tempResult);\n"
556 			"  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
557 			"}\n";
558 		*/
559 		const string evaluationSource =
560 			"; SPIR-V\n"
561 			"; Version: 1.3\n"
562 			"; Generator: Khronos Glslang Reference Front End; 2\n"
563 			"; Bound: 91\n"
564 			"; Schema: 0\n"
565 			"OpCapability Tessellation\n"
566 			"OpCapability GroupNonUniform\n"
567 			"OpCapability GroupNonUniformBallot\n"
568 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
569 			"OpMemoryModel Logical GLSL450\n"
570 			"OpEntryPoint TessellationEvaluation %4 \"main\" %35 %62 %70 %75 %83\n"
571 			"OpExecutionMode %4 Isolines\n"
572 			"OpExecutionMode %4 SpacingEqual\n"
573 			"OpExecutionMode %4 VertexOrderCcw\n"
574 			"OpDecorate %30 ArrayStride 16\n"
575 			"OpMemberDecorate %31 0 Offset 0\n"
576 			"OpDecorate %31 Block\n"
577 			"OpDecorate %33 DescriptorSet 0\n"
578 			"OpDecorate %33 Binding 0\n"
579 			"OpDecorate %35 RelaxedPrecision\n"
580 			"OpDecorate %35 BuiltIn SubgroupLocalInvocationId\n"
581 			"OpDecorate %36 RelaxedPrecision\n"
582 			"OpDecorate %62 Location 0\n"
583 			"OpMemberDecorate %68 0 BuiltIn Position\n"
584 			"OpMemberDecorate %68 1 BuiltIn PointSize\n"
585 			"OpMemberDecorate %68 2 BuiltIn ClipDistance\n"
586 			"OpMemberDecorate %68 3 BuiltIn CullDistance\n"
587 			"OpDecorate %68 Block\n"
588 			"OpMemberDecorate %71 0 BuiltIn Position\n"
589 			"OpMemberDecorate %71 1 BuiltIn PointSize\n"
590 			"OpMemberDecorate %71 2 BuiltIn ClipDistance\n"
591 			"OpMemberDecorate %71 3 BuiltIn CullDistance\n"
592 			"OpDecorate %71 Block\n"
593 			"OpDecorate %83 BuiltIn TessCoord\n"
594 			"%2 = OpTypeVoid\n"
595 			"%3 = OpTypeFunction %2\n"
596 			"%6 = OpTypeInt 32 0\n"
597 			"%7 = OpTypePointer Function %6\n"
598 			"%9 = OpConstant %6 0\n"
599 			"%10 = OpTypeVector %6 4\n"
600 			"%11 = OpConstantComposite %10 %9 %9 %9 %9\n"
601 			"%12 = OpTypeBool\n"
602 			"%13 = OpConstantTrue %12\n"
603 			"%14 = OpConstant %6 3\n"
604 			"%16 = OpTypeVector %12 4\n"
605 			"%20 = OpTypeInt 32 1\n"
606 			"%21 = OpConstant %20 1\n"
607 			"%22 = OpConstant %20 0\n"
608 			"%27 = OpTypePointer Function %12\n"
609 			"%29 = OpConstant %6 " + subgroupSizeStr.str() + "\n"
610 			"%30 = OpTypeArray %6 %29\n"
611 			"%31 = OpTypeStruct %30\n"
612 			"%32 = OpTypePointer Uniform %31\n"
613 			"%33 = OpVariable %32 Uniform\n"
614 			"%34 = OpTypePointer Input %6\n"
615 			"%35 = OpVariable %34 Input\n"
616 			"%37 = OpTypePointer Uniform %6\n"
617 			"%46 = OpConstant %20 2\n"
618 			"%51 = OpConstantFalse %12\n"
619 			"%55 = OpConstant %20 4\n"
620 			"%60 = OpTypeFloat 32\n"
621 			"%61 = OpTypePointer Output %60\n"
622 			"%62 = OpVariable %61 Output\n"
623 			"%65 = OpTypeVector %60 4\n"
624 			"%66 = OpConstant %6 1\n"
625 			"%67 = OpTypeArray %60 %66\n"
626 			"%68 = OpTypeStruct %65 %60 %67 %67\n"
627 			"%69 = OpTypePointer Output %68\n"
628 			"%70 = OpVariable %69 Output\n"
629 			"%71 = OpTypeStruct %65 %60 %67 %67\n"
630 			"%72 = OpConstant %6 32\n"
631 			"%73 = OpTypeArray %71 %72\n"
632 			"%74 = OpTypePointer Input %73\n"
633 			"%75 = OpVariable %74 Input\n"
634 			"%76 = OpTypePointer Input %65\n"
635 			"%81 = OpTypeVector %60 3\n"
636 			"%82 = OpTypePointer Input %81\n"
637 			"%83 = OpVariable %82 Input\n"
638 			"%84 = OpTypePointer Input %60\n"
639 			"%89 = OpTypePointer Output %65\n"
640 			"%4 = OpFunction %2 None %3\n"
641 			"%5 = OpLabel\n"
642 			"%8 = OpVariable %7 Function\n"
643 			"%28 = OpVariable %27 Function\n"
644 			"OpStore %8 %9\n"
645 			"%15 = OpGroupNonUniformBallot %10 %14 %13\n"
646 			"%17 = OpIEqual %16 %11 %15\n"
647 			"%18 = OpAll %12 %17\n"
648 			"%19 = OpLogicalNot %12 %18\n"
649 			"%23 = OpSelect %20 %19 %21 %22\n"
650 			"%24 = OpBitcast %6 %23\n"
651 			"%25 = OpLoad %6 %8\n"
652 			"%26 = OpBitwiseOr %6 %25 %24\n"
653 			"OpStore %8 %26\n"
654 			"%36 = OpLoad %6 %35\n"
655 			"%38 = OpAccessChain %37 %33 %22 %36\n"
656 			"%39 = OpLoad %6 %38\n"
657 			"%40 = OpINotEqual %12 %39 %9\n"
658 			"OpStore %28 %40\n"
659 			"%41 = OpLoad %12 %28\n"
660 			"%42 = OpGroupNonUniformBallot %10 %14 %41\n"
661 			"%43 = OpIEqual %16 %11 %42\n"
662 			"%44 = OpAll %12 %43\n"
663 			"%45 = OpLogicalNot %12 %44\n"
664 			"%47 = OpSelect %20 %45 %46 %22\n"
665 			"%48 = OpBitcast %6 %47\n"
666 			"%49 = OpLoad %6 %8\n"
667 			"%50 = OpBitwiseOr %6 %49 %48\n"
668 			"OpStore %8 %50\n"
669 			"%52 = OpGroupNonUniformBallot %10 %14 %51\n"
670 			"%53 = OpIEqual %16 %11 %52\n"
671 			"%54 = OpAll %12 %53\n"
672 			"%56 = OpSelect %20 %54 %55 %22\n"
673 			"%57 = OpBitcast %6 %56\n"
674 			"%58 = OpLoad %6 %8\n"
675 			"%59 = OpBitwiseOr %6 %58 %57\n"
676 			"OpStore %8 %59\n"
677 			"%63 = OpLoad %6 %8\n"
678 			"%64 = OpConvertUToF %60 %63\n"
679 			"OpStore %62 %64\n"
680 			"%77 = OpAccessChain %76 %75 %22 %22\n"
681 			"%78 = OpLoad %65 %77\n"
682 			"%79 = OpAccessChain %76 %75 %21 %22\n"
683 			"%80 = OpLoad %65 %79\n"
684 			"%85 = OpAccessChain %84 %83 %9\n"
685 			"%86 = OpLoad %60 %85\n"
686 			"%87 = OpCompositeConstruct %65 %86 %86 %86 %86\n"
687 			"%88 = OpExtInst %65 %1 FMix %78 %80 %87\n"
688 			"%90 = OpAccessChain %89 %70 %22\n"
689 			"OpStore %90 %88\n"
690 			"OpReturn\n"
691 			"OpFunctionEnd\n";
692 		subgroups::setTesCtrlShaderFrameBuffer(programCollection);
693 		programCollection.spirvAsmSources.add("tese") << evaluationSource << buildOptionsSpr;
694 	}
695 	else
696 	{
697 		DE_FATAL("Unsupported shader stage");
698 	}
699 }
700 
701 
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)702 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
703 {
704 	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
705 	{
706 		std::ostringstream src;
707 
708 		src << "#version 450\n"
709 			<< "#extension GL_KHR_shader_subgroup_ballot: enable\n"
710 			<< "layout (local_size_x_id = 0, local_size_y_id = 1, "
711 			"local_size_z_id = 2) in;\n"
712 			<< "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
713 			<< "{\n"
714 			<< "  uint result[];\n"
715 			<< "};\n"
716 			<< "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
717 			<< "{\n"
718 			<< "  uint data[];\n"
719 			<< "};\n"
720 			<< "\n"
721 			<< subgroups::getSharedMemoryBallotHelper()
722 			<< "void main (void)\n"
723 			<< "{\n"
724 			<< "  uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
725 			<< "  highp uint offset = globalSize.x * ((globalSize.y * "
726 			"gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
727 			"gl_GlobalInvocationID.x;\n"
728 			<< "  uint tempResult = 0;\n"
729 			<< "  tempResult |= sharedMemoryBallot(true) == subgroupBallot(true) ? 0x1 : 0;\n"
730 			<< "  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
731 			<< "  tempResult |= sharedMemoryBallot(bData) == subgroupBallot(bData) ? 0x2 : 0;\n"
732 			<< "  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
733 			<< "  result[offset] = tempResult;\n"
734 			<< "}\n";
735 
736 		programCollection.glslSources.add("comp")
737 				<< glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
738 	}
739 	else
740 	{
741 		const string vertex =
742 			"#version 450\n"
743 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
744 			"layout(set = 0, binding = 0, std430) buffer Buffer1\n"
745 			"{\n"
746 			"  uint result[];\n"
747 			"};\n"
748 			"layout(set = 0, binding = 4, std430) readonly buffer Buffer2\n"
749 			"{\n"
750 			"  uint data[];\n"
751 			"};\n"
752 			"\n"
753 			"void main (void)\n"
754 			"{\n"
755 			"  uint tempResult = 0;\n"
756 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
757 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
758 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
759 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
760 			"  result[gl_VertexIndex] = tempResult;\n"
761 			"  float pixelSize = 2.0f/1024.0f;\n"
762 			"  float pixelPosition = pixelSize/2.0f - 1.0f;\n"
763 			"  gl_Position = vec4(float(gl_VertexIndex) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
764 			"  gl_PointSize = 1.0f;\n"
765 			"}\n";
766 
767 		const string tesc =
768 			"#version 450\n"
769 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
770 			"layout(vertices=1) out;\n"
771 			"layout(set = 0, binding = 1, std430) buffer Buffer1\n"
772 			"{\n"
773 			"  uint result[];\n"
774 			"};\n"
775 			"layout(set = 0, binding = 4, std430) readonly buffer Buffer2\n"
776 			"{\n"
777 			"  uint data[];\n"
778 			"};\n"
779 			"\n"
780 			"void main (void)\n"
781 			"{\n"
782 			"  uint tempResult = 0;\n"
783 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
784 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
785 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
786 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
787 			"  result[gl_PrimitiveID] = tempResult;\n"
788 			"  if (gl_InvocationID == 0)\n"
789 			"  {\n"
790 			"    gl_TessLevelOuter[0] = 1.0f;\n"
791 			"    gl_TessLevelOuter[1] = 1.0f;\n"
792 			"  }\n"
793 			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
794 			"}\n";
795 
796 		const string tese =
797 			"#version 450\n"
798 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
799 			"layout(isolines) in;\n"
800 			"layout(set = 0, binding = 2, std430) buffer Buffer1\n"
801 			"{\n"
802 			"  uint result[];\n"
803 			"};\n"
804 			"layout(set = 0, binding = 4, std430) readonly buffer Buffer2\n"
805 			"{\n"
806 			"  uint data[];\n"
807 			"};\n"
808 			"\n"
809 			"void main (void)\n"
810 			"{\n"
811 			"  uint tempResult = 0;\n"
812 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
813 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
814 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
815 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
816 			"  result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
817 			"  float pixelSize = 2.0f/1024.0f;\n"
818 			"  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
819 			"}\n";
820 
821 		const string geometry =
822 			"#version 450\n"
823 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
824 			"layout(${TOPOLOGY}) in;\n"
825 			"layout(points, max_vertices = 1) out;\n"
826 			"layout(set = 0, binding = 3, std430) buffer Buffer1\n"
827 			"{\n"
828 			"  uint result[];\n"
829 			"};\n"
830 			"layout(set = 0, binding = 4, std430) readonly buffer Buffer2\n"
831 			"{\n"
832 			"  uint data[];\n"
833 			"};\n"
834 			"\n"
835 			"void main (void)\n"
836 			"{\n"
837 			"  uint tempResult = 0;\n"
838 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
839 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
840 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
841 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
842 			"  result[gl_PrimitiveIDIn] = tempResult;\n"
843 			"  gl_Position = gl_in[0].gl_Position;\n"
844 			"  EmitVertex();\n"
845 			"  EndPrimitive();\n"
846 			"}\n";
847 
848 		const string fragment =
849 			"#version 450\n"
850 			"#extension GL_KHR_shader_subgroup_ballot: enable\n"
851 			"layout(location = 0) out uint result;\n"
852 			"layout(set = 0, binding = 4, std430) readonly buffer Buffer1\n"
853 			"{\n"
854 			"  uint data[];\n"
855 			"};\n"
856 			"void main (void)\n"
857 			"{\n"
858 			"  uint tempResult = 0;\n"
859 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
860 			"  bool bData = data[gl_SubgroupInvocationID] != 0;\n"
861 			"  tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
862 			"  tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
863 			"  result = tempResult;\n"
864 			"}\n";
865 
866 		subgroups::addNoSubgroupShader(programCollection);
867 
868 		programCollection.glslSources.add("vert")
869 				<< glu::VertexSource(vertex) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
870 		programCollection.glslSources.add("tesc")
871 				<< glu::TessellationControlSource(tesc) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
872 		programCollection.glslSources.add("tese")
873 				<< glu::TessellationEvaluationSource(tese) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
874 		subgroups::addGeometryShadersFromTemplate(geometry, vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u),
875 												  programCollection.glslSources);
876 		programCollection.glslSources.add("fragment")
877 				<< glu::FragmentSource(fragment)<< vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
878 	}
879 }
880 
supportedCheck(Context & context,CaseDefinition caseDef)881 void supportedCheck (Context& context, CaseDefinition caseDef)
882 {
883 	DE_UNREF(caseDef);
884 	if (!subgroups::isSubgroupSupported(context))
885 		TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
886 
887 	if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
888 	{
889 		TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
890 	}
891 }
892 
noSSBOtest(Context & context,const CaseDefinition caseDef)893 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
894 {
895 	if (!subgroups::areSubgroupOperationsSupportedForStage(
896 			context, caseDef.shaderStage))
897 	{
898 		if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
899 		{
900 			return tcu::TestStatus::fail(
901 					   "Shader stage " +
902 					   subgroups::getShaderStageName(caseDef.shaderStage) +
903 					   " is required to support subgroup operations!");
904 		}
905 		else
906 		{
907 			TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
908 		}
909 	}
910 
911 	subgroups::SSBOData inputData[1];
912 	inputData[0].format = VK_FORMAT_R32_UINT;
913 	inputData[0].layout = subgroups::SSBOData::LayoutStd140;
914 	inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
915 	inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
916 
917 	if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
918 		return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages);
919 	else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
920 		return subgroups::makeGeometryFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages);
921 	else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
922 		return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
923 	else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
924 		return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
925 	else
926 		TCU_THROW(InternalError, "Unhandled shader stage");
927 }
928 
test(Context & context,const CaseDefinition caseDef)929 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
930 {
931 	if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
932 	{
933 		if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
934 		{
935 				return tcu::TestStatus::fail(
936 						   "Shader stage " +
937 						   subgroups::getShaderStageName(caseDef.shaderStage) +
938 						   " is required to support subgroup operations!");
939 		}
940 		subgroups::SSBOData inputData[1];
941 		inputData[0].format = VK_FORMAT_R32_UINT;
942 		inputData[0].layout = subgroups::SSBOData::LayoutStd430;
943 		inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
944 		inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
945 
946 		return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT, inputData, 1, checkCompute);
947 	}
948 	else
949 	{
950 		VkPhysicalDeviceSubgroupProperties subgroupProperties;
951 		subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
952 		subgroupProperties.pNext = DE_NULL;
953 
954 		VkPhysicalDeviceProperties2 properties;
955 		properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
956 		properties.pNext = &subgroupProperties;
957 
958 		context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
959 
960 		VkShaderStageFlagBits stages = (VkShaderStageFlagBits)(caseDef.shaderStage  & subgroupProperties.supportedStages);
961 
962 		if ( VK_SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
963 		{
964 			if ( (stages & VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
965 				TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
966 			else
967 				stages = VK_SHADER_STAGE_FRAGMENT_BIT;
968 		}
969 
970 		if ((VkShaderStageFlagBits)0u == stages)
971 			TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
972 
973 		subgroups::SSBOData inputData;
974 		inputData.format			= VK_FORMAT_R32_UINT;
975 		inputData.layout            = subgroups::SSBOData::LayoutStd430;
976 		inputData.numElements		= subgroups::maxSupportedSubgroupSize();
977 		inputData.initializeType	= subgroups::SSBOData::InitializeNonZero;
978 		inputData.binding			= 4u;
979 		inputData.stages			= stages;
980 
981 		return subgroups::allStages(context, VK_FORMAT_R32_UINT, &inputData, 1, checkVertexPipelineStages, stages);
982 	}
983 }
984 }
985 
986 namespace vkt
987 {
988 namespace subgroups
989 {
createSubgroupsBallotTests(tcu::TestContext & testCtx)990 tcu::TestCaseGroup* createSubgroupsBallotTests(tcu::TestContext& testCtx)
991 {
992 	de::MovePtr<tcu::TestCaseGroup> graphicGroup(new tcu::TestCaseGroup(
993 		testCtx, "graphics", "Subgroup ballot category tests: graphics"));
994 	de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(
995 		testCtx, "compute", "Subgroup ballot category tests: compute"));
996 	de::MovePtr<tcu::TestCaseGroup> framebufferGroup(new tcu::TestCaseGroup(
997 		testCtx, "framebuffer", "Subgroup ballot category tests: framebuffer"));
998 
999 	const VkShaderStageFlags stages[] =
1000 	{
1001 		VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1002 		VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1003 		VK_SHADER_STAGE_GEOMETRY_BIT,
1004 		VK_SHADER_STAGE_VERTEX_BIT
1005 	};
1006 
1007 	{
1008 		const CaseDefinition caseDef = {VK_SHADER_STAGE_COMPUTE_BIT};
1009 		addFunctionCaseWithPrograms(computeGroup.get(), getShaderStageName(caseDef.shaderStage), "", supportedCheck, initPrograms, test, caseDef);
1010 	}
1011 
1012 	{
1013 			const CaseDefinition caseDef = {VK_SHADER_STAGE_ALL_GRAPHICS};
1014 			addFunctionCaseWithPrograms(graphicGroup.get(), "graphic", "", supportedCheck, initPrograms, test, caseDef);
1015 	}
1016 
1017 	for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
1018 	{
1019 		const CaseDefinition caseDef = {stages[stageIndex]};
1020 		addFunctionCaseWithPrograms(framebufferGroup.get(), getShaderStageName(caseDef.shaderStage), "",
1021 					supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
1022 	}
1023 
1024 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
1025 		testCtx, "ballot", "Subgroup ballot category tests"));
1026 
1027 	group->addChild(graphicGroup.release());
1028 	group->addChild(computeGroup.release());
1029 	group->addChild(framebufferGroup.release());
1030 
1031 	return group.release();
1032 }
1033 
1034 } // subgroups
1035 } // vkt
1036