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