1 /*------------------------------------------------------------------------
2 * OpenGL Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017-2019 The Khronos Group Inc.
6 * Copyright (c) 2017 Codeplay Software Ltd.
7 * Copyright (c) 2019 NVIDIA Corporation.
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * \brief Subgroups Tests
24 */ /*--------------------------------------------------------------------*/
26 #include "glcSubgroupsBasicTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
28 #include "gluContextInfo.hpp"
32 #include "tcuStringTemplate.hpp"
44 static const deUint32 ELECTED_VALUE = 42u;
45 static const deUint32 UNELECTED_VALUE = 13u;
46 static const deUint64 SHADER_BUFFER_SIZE = 4096ull;
48 static bool checkFragmentSubgroupBarriersNoSSBO(std::vector<const void*> datas,
49 deUint32 width, deUint32 height, deUint32)
51 const float* const resultData = reinterpret_cast<const float*>(datas[0]);
53 for (deUint32 x = 0u; x < width; ++x)
55 for (deUint32 y = 0u; y < height; ++y)
57 const deUint32 ndx = (x * height + y) * 4u;
58 if (1.0f == resultData[ndx +2])
60 if(resultData[ndx] != resultData[ndx +1])
65 else if (resultData[ndx] != resultData[ndx +3])
75 static bool checkVertexPipelineStagesSubgroupElectNoSSBO(std::vector<const void*> datas,
76 deUint32 width, deUint32)
78 const float* const resultData = reinterpret_cast<const float*>(datas[0]);
79 float poisonValuesFound = 0.0f;
80 float numSubgroupsUsed = 0.0f;
82 for (deUint32 x = 0; x < width; ++x)
84 deUint32 val = static_cast<deUint32>(resultData[x * 2]);
85 numSubgroupsUsed += resultData[x * 2 + 1];
90 // some garbage value was found!
95 poisonValuesFound += 1.0f;
99 return numSubgroupsUsed == poisonValuesFound;
102 static bool checkVertexPipelineStagesSubgroupElect(std::vector<const void*> datas,
103 deUint32 width, deUint32)
105 const deUint32* const resultData =
106 reinterpret_cast<const deUint32*>(datas[0]);
107 deUint32 poisonValuesFound = 0;
109 for (deUint32 x = 0; x < width; ++x)
111 deUint32 val = resultData[x];
116 // some garbage value was found!
118 case UNELECTED_VALUE:
126 // we used an atomicly incremented counter to note how many subgroups we used for the vertex shader
127 const deUint32 numSubgroupsUsed =
128 *reinterpret_cast<const deUint32*>(datas[1]);
130 return numSubgroupsUsed == poisonValuesFound;
133 static bool checkVertexPipelineStagesSubgroupBarriers(std::vector<const void*> datas,
134 deUint32 width, deUint32)
136 const deUint32* const resultData = reinterpret_cast<const deUint32*>(datas[0]);
138 // We used this SSBO to generate our unique value!
139 const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[3]);
141 for (deUint32 x = 0; x < width; ++x)
143 deUint32 val = resultData[x];
152 static bool checkVertexPipelineStagesSubgroupBarriersNoSSBO(std::vector<const void*> datas,
153 deUint32 width, deUint32)
155 const float* const resultData = reinterpret_cast<const float*>(datas[0]);
157 for (deUint32 x = 0u; x < width; ++x)
159 const deUint32 ndx = x*4u;
160 if (1.0f == resultData[ndx +2])
162 if(resultData[ndx] != resultData[ndx +1])
165 else if (resultData[ndx] != resultData[ndx +3])
173 static bool checkTessellationEvaluationSubgroupBarriersNoSSBO(std::vector<const void*> datas,
174 deUint32 width, deUint32)
176 const float* const resultData = reinterpret_cast<const float*>(datas[0]);
178 for (deUint32 x = 0u; x < width; ++x)
180 const deUint32 ndx = x*4u;
181 if (0.0f == resultData[ndx +2] && resultData[ndx] != resultData[ndx +3])
189 static bool checkComputeSubgroupElect(std::vector<const void*> datas,
190 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
193 return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
196 static bool checkComputeSubgroupBarriers(std::vector<const void*> datas,
197 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
200 // We used this SSBO to generate our unique value!
201 const deUint32 ref = *reinterpret_cast<const deUint32*>(datas[2]);
202 return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, ref);
208 OPTYPE_SUBGROUP_BARRIER,
209 OPTYPE_SUBGROUP_MEMORY_BARRIER,
210 OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER,
211 OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED,
212 OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE,
216 std::string getOpTypeName(int opType)
221 DE_FATAL("Unsupported op type");
224 return "subgroupElect";
225 case OPTYPE_SUBGROUP_BARRIER:
226 return "subgroupBarrier";
227 case OPTYPE_SUBGROUP_MEMORY_BARRIER:
228 return "subgroupMemoryBarrier";
229 case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
230 return "subgroupMemoryBarrierBuffer";
231 case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
232 return "subgroupMemoryBarrierShared";
233 case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
234 return "subgroupMemoryBarrierImage";
238 struct CaseDefinition
241 subgroups::ShaderStageFlags shaderStage;
244 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
246 if(subgroups::SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage)
248 const string fragmentGLSL =
250 "layout(location = 0) in vec4 in_color;\n"
251 "layout(location = 0) out vec4 out_color;\n"
254 " out_color = in_color;\n"
257 programCollection.add("fragment") << glu::FragmentSource(fragmentGLSL);
259 if (subgroups::SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
261 const string vertexGLSL =
265 " vec2 uv = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);\n"
266 " gl_Position = vec4(uv * 2.0f + -1.0f, 0.0f, 1.0f);\n"
267 " gl_PointSize = 1.0f;\n"
270 programCollection.add("vert") << glu::VertexSource(vertexGLSL);
272 else if (subgroups::SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
273 subgroups::setVertexShaderFrameBuffer(programCollection);
275 if (OPTYPE_ELECT == caseDef.opType)
277 std::ostringstream electedValue ;
278 std::ostringstream unelectedValue;
279 electedValue << ELECTED_VALUE;
280 unelectedValue << UNELECTED_VALUE;
282 if (subgroups::SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
284 const string vertexGLSL =
286 "#extension GL_KHR_shader_subgroup_basic: enable\n"
287 "layout(location = 0) out vec4 out_color;\n"
288 "layout(location = 0) in highp vec4 in_position;\n"
292 " if (subgroupElect())\n"
294 " out_color.r = " + electedValue.str() + ";\n"
295 " out_color.g = 1.0f;\n"
299 " out_color.r = " + unelectedValue.str() + ";\n"
300 " out_color.g = 0.0f;\n"
302 " gl_Position = in_position;\n"
303 " gl_PointSize = 1.0f;\n"
306 programCollection.add("vert") << glu::VertexSource(vertexGLSL);
308 else if (subgroups::SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
310 const string geometryGLSL =
312 "#extension GL_KHR_shader_subgroup_basic: enable\n"
313 "layout(points) in;\n"
314 "layout(points, max_vertices = 1) out;\n"
315 "layout(location = 0) out vec4 out_color;\n"
318 " if (subgroupElect())\n"
320 " out_color.r = " + electedValue.str() + ";\n"
321 " out_color.g = 1.0f;\n"
325 " out_color.r = " + unelectedValue.str() + ";\n"
326 " out_color.g = 0.0f;\n"
328 " gl_Position = gl_in[0].gl_Position;\n"
333 programCollection.add("geometry") << glu::GeometrySource(geometryGLSL);
335 else if (subgroups::SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
337 const string controlSourceGLSL =
339 "#extension GL_KHR_shader_subgroup_basic: enable\n"
340 "#extension GL_EXT_tessellation_shader : require\n"
341 "layout(vertices = 2) out;\n"
344 " if (gl_InvocationID == 0)\n"
346 " gl_TessLevelOuter[0] = 1.0f;\n"
347 " gl_TessLevelOuter[1] = 1.0f;\n"
349 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
352 programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
354 const string evaluationSourceGLSL =
356 "#extension GL_KHR_shader_subgroup_basic: enable\n"
357 "#extension GL_EXT_tessellation_shader : require\n"
358 "layout(isolines, equal_spacing, ccw ) in;\n"
359 "layout(location = 0) out vec4 out_color;\n"
363 " if (subgroupElect())\n"
365 " out_color.r = 71.f;\n" // << 2 * ELECTED_VALUE - UNELECTED_VALUE << ";\n"
366 " out_color.g = 2.0f;\n"
370 " out_color.r = " + unelectedValue.str() + ";\n"
371 " out_color.g = 0.0f;\n"
373 " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
376 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
378 else if (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
380 const string controlSourceGLSL =
382 "#extension GL_KHR_shader_subgroup_basic: enable\n"
383 "#extension GL_EXT_tessellation_shader : require\n"
384 "layout(vertices = 2) out;\n"
385 "layout(location = 0) out vec4 out_color[];\n"
388 " if (gl_InvocationID == 0)\n"
390 " gl_TessLevelOuter[0] = 1.0f;\n"
391 " gl_TessLevelOuter[1] = 1.0f;\n"
393 " if (subgroupElect())\n"
395 " out_color[gl_InvocationID].r = " + electedValue.str() + ";\n"
396 " out_color[gl_InvocationID].g = 1.0f;\n"
400 " out_color[gl_InvocationID].r = " + unelectedValue.str() + ";\n"
401 " out_color[gl_InvocationID].g = 0.0f;\n"
403 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
406 programCollection.add("tesc") << glu::TessellationControlSource(controlSourceGLSL);
408 const string evaluationSourceGLSL =
410 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
411 "#extension GL_EXT_tessellation_shader : require\n"
412 "layout(isolines, equal_spacing, ccw ) in;\n"
413 "layout(location = 0) in vec4 in_color[];\n"
414 "layout(location = 0) out vec4 out_color;\n"
418 " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
419 " out_color = in_color[0];\n"
422 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSourceGLSL);
426 DE_FATAL("Unsupported shader stage");
431 std::ostringstream bdy;
432 string color = (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage) ? "out_color[gl_InvocationID].b = 1.0f;\n" : "out_color.b = 1.0f;\n";
433 switch (caseDef.opType)
436 DE_FATAL("Unhandled op type!");
438 case OPTYPE_SUBGROUP_BARRIER:
439 case OPTYPE_SUBGROUP_MEMORY_BARRIER:
440 case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
442 bdy << " tempResult2 = tempBuffer[id];\n"
443 << " if (subgroupElect())\n"
445 << " tempResult = value;\n"
450 << " tempResult = tempBuffer[id];\n"
452 << " " << getOpTypeName(caseDef.opType) << "();\n";
455 case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
456 bdy << " tempResult2 = imageLoad(tempImage, ivec2(id, 0)).x;\n"
457 << " if (subgroupElect())\n"
459 << " tempResult = value;\n"
464 << " tempResult = imageLoad(tempImage, ivec2(id, 0)).x;\n"
466 << " subgroupMemoryBarrierImage();\n";
471 if (subgroups::SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
473 std::ostringstream fragment;
474 fragment << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
475 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
476 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
477 << "layout(location = 0) out vec4 out_color;\n"
479 << "layout(binding = 0) uniform Buffer1\n"
481 << " uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
484 << "layout(binding = 1) uniform Buffer2\n"
488 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
489 << "void main (void)\n"
491 << " if (gl_HelperInvocation) return;\n"
493 << " if (subgroupElect())\n"
495 << " id = uint(gl_FragCoord.x);\n"
497 << " id = subgroupBroadcastFirst(id);\n"
498 << " uint localId = id;\n"
499 << " uint tempResult = 0u;\n"
500 << " uint tempResult2 = 0u;\n"
501 << " out_color.b = 0.0f;\n"
503 << " out_color.r = float(tempResult);\n"
504 << " out_color.g = float(value);\n"
505 << " out_color.a = float(tempResult2);\n"
507 programCollection.add("fragment") << glu::FragmentSource(fragment.str());
509 else if (subgroups::SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
511 std::ostringstream vertex;
512 vertex << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
513 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
514 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
516 << "layout(location = 0) out vec4 out_color;\n"
517 << "layout(location = 0) in highp vec4 in_position;\n"
519 << "layout(binding = 0) uniform Buffer1\n"
521 << " uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
524 << "layout(binding = 1) uniform Buffer2\n"
528 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
529 << "void main (void)\n"
532 << " if (subgroupElect())\n"
534 << " id = gl_VertexID;\n"
536 << " id = subgroupBroadcastFirst(id);\n"
537 << " uint tempResult = 0u;\n"
538 << " uint tempResult2 = 0u;\n"
539 << " out_color.b = 0.0f;\n"
541 << " out_color.r = float(tempResult);\n"
542 << " out_color.g = float(value);\n"
543 << " out_color.a = float(tempResult2);\n"
544 << " gl_Position = in_position;\n"
545 << " gl_PointSize = 1.0f;\n"
547 programCollection.add("vert") << glu::VertexSource(vertex.str());
549 else if (subgroups::SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
551 std::ostringstream geometry;
553 geometry << "#version 450\n"
554 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
555 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
556 << "layout(points) in;\n"
557 << "layout(points, max_vertices = 1) out;\n"
558 << "layout(location = 0) out vec4 out_color;\n"
559 << "layout(binding = 0) uniform Buffer1\n"
561 << " uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
564 << "layout(binding = 1) uniform Buffer2\n"
568 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
569 << "void main (void)\n"
572 << " if (subgroupElect())\n"
574 << " id = gl_InvocationID;\n"
576 << " id = subgroupBroadcastFirst(id);\n"
577 << " uint tempResult = 0u;\n"
578 << " uint tempResult2 = 0u;\n"
579 << " out_color.b = 0.0f;\n"
581 << " out_color.r = float(tempResult);\n"
582 << " out_color.g = float(value);\n"
583 << " out_color.a = float(tempResult2);\n"
584 << " gl_Position = gl_in[0].gl_Position;\n"
585 << " EmitVertex();\n"
586 << " EndPrimitive();\n"
589 programCollection.add("geometry") << glu::GeometrySource(geometry.str());
591 else if (subgroups::SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
593 std::ostringstream controlSource;
594 std::ostringstream evaluationSource;
596 controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
597 << "#extension GL_EXT_tessellation_shader : require\n"
598 << "layout(vertices = 2) out;\n"
599 << "void main (void)\n"
601 << " if (gl_InvocationID == 0)\n"
603 << " gl_TessLevelOuter[0] = 1.0f;\n"
604 << " gl_TessLevelOuter[1] = 1.0f;\n"
606 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
609 evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
610 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
611 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
612 << "#extension GL_EXT_tessellation_shader : require\n"
613 << "layout(isolines, equal_spacing, ccw ) in;\n"
614 << "layout(location = 0) out vec4 out_color;\n"
615 << "layout(binding = 0) uniform Buffer1\n"
617 << " uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
620 << "layout(binding = 1) uniform Buffer2\n"
624 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
625 << "void main (void)\n"
628 << " if (subgroupElect())\n"
630 << " id = gl_PrimitiveID;\n"
632 << " id = subgroupBroadcastFirst(id);\n"
633 << " uint tempResult = 0u;\n"
634 << " uint tempResult2 = 0u;\n"
635 << " out_color.b = 0.0f;\n"
637 << " out_color.r = float(tempResult);\n"
638 << " out_color.g = float(value);\n"
639 << " out_color.a = float(tempResult2);\n"
640 << " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
643 programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
644 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
646 else if (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
648 std::ostringstream controlSource;
649 std::ostringstream evaluationSource;
651 controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
652 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
653 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
654 << "#extension GL_EXT_tessellation_shader : require\n"
655 << "layout(vertices = 2) out;\n"
656 << "layout(location = 0) out vec4 out_color[];\n"
657 << "layout(binding = 0) uniform Buffer1\n"
659 << " uint tempBuffer["<<SHADER_BUFFER_SIZE/4ull<<"];\n"
662 << "layout(binding = 1) uniform Buffer2\n"
666 << (OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? "layout(binding = 0, r32ui) readonly uniform highp uimage2D tempImage;\n" : "\n")
667 << "void main (void)\n"
670 << " if (gl_InvocationID == 0)\n"
672 << " gl_TessLevelOuter[0] = 1.0f;\n"
673 << " gl_TessLevelOuter[1] = 1.0f;\n"
675 << " if (subgroupElect())\n"
677 << " id = gl_InvocationID;\n"
679 << " id = subgroupBroadcastFirst(id);\n"
680 << " uint tempResult = 0u;\n"
681 << " uint tempResult2 = 0u;\n"
682 << " out_color[gl_InvocationID].b = 0.0f;\n"
684 << " out_color[gl_InvocationID].r = float(tempResult);\n"
685 << " out_color[gl_InvocationID].g = float(value);\n"
686 << " out_color[gl_InvocationID].a = float(tempResult2);\n"
687 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
690 evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
691 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
692 << "#extension GL_EXT_tessellation_shader : require\n"
693 << "layout(isolines, equal_spacing, ccw ) in;\n"
694 << "layout(location = 0) in vec4 in_color[];\n"
695 << "layout(location = 0) out vec4 out_color;\n"
697 << "void main (void)\n"
699 << " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
700 << " out_color = in_color[0];\n"
703 programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
704 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
708 DE_FATAL("Unsupported shader stage");
713 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
715 if (OPTYPE_ELECT == caseDef.opType)
717 if (subgroups::SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
719 std::ostringstream src;
721 src << "#version 450\n"
722 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
723 << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
724 << "layout(binding = 0, std430) buffer Buffer1\n"
726 << " uint result[];\n"
729 << subgroups::getSharedMemoryBallotHelper()
730 << "void main (void)\n"
732 << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
733 << " highp uint offset = globalSize.x * ((globalSize.y * "
734 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
735 "gl_GlobalInvocationID.x;\n"
736 << " uint value = " << UNELECTED_VALUE << ";\n"
737 << " if (subgroupElect())\n"
739 << " value = " << ELECTED_VALUE << ";\n"
741 << " uvec4 bits = bitCount(sharedMemoryBallot(value == " << ELECTED_VALUE << "));\n"
742 << " result[offset] = bits.x + bits.y + bits.z + bits.w;\n"
745 programCollection.add("comp") << glu::ComputeSource(src.str());
750 std::ostringstream vertex;
751 vertex << "#version 450\n"
752 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
753 << "layout(binding = 0, std430) buffer Buffer0\n"
755 << " uint result[];\n"
757 << "layout(binding = 4, std430) buffer Buffer4\n"
759 << " uint numSubgroupsExecuted;\n"
762 << "void main (void)\n"
764 << " if (subgroupElect())\n"
766 << " b0.result[gl_VertexID] = " << ELECTED_VALUE << ";\n"
767 << " atomicAdd(b4.numSubgroupsExecuted, 1);\n"
771 << " b0.result[gl_VertexID] = " << UNELECTED_VALUE << ";\n"
773 << " float pixelSize = 2.0f/1024.0f;\n"
774 << " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
775 << " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
776 << " gl_PointSize = 1.0f;\n"
778 programCollection.add("vert") << glu::VertexSource(vertex.str());
782 std::ostringstream tesc;
783 tesc << "#version 450\n"
784 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
785 << "layout(vertices=1) out;\n"
786 << "layout(binding = 1, std430) buffer Buffer1\n"
788 << " uint result[];\n"
790 << "layout(binding = 5, std430) buffer Buffer5\n"
792 << " uint numSubgroupsExecuted;\n"
795 << "void main (void)\n"
797 << " if (subgroupElect())\n"
799 << " b1.result[gl_PrimitiveID] = " << ELECTED_VALUE << ";\n"
800 << " atomicAdd(b5.numSubgroupsExecuted, 1);\n"
804 << " b1.result[gl_PrimitiveID] = " << UNELECTED_VALUE << ";\n"
806 << " if (gl_InvocationID == 0)\n"
808 << " gl_TessLevelOuter[0] = 1.0f;\n"
809 << " gl_TessLevelOuter[1] = 1.0f;\n"
811 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
813 programCollection.add("tesc") << glu::TessellationControlSource(tesc.str());
817 std::ostringstream tese;
818 tese << "#version 450\n"
819 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
820 << "layout(isolines) in;\n"
821 << "layout(binding = 2, std430) buffer Buffer2\n"
823 << " uint result[];\n"
825 << "layout(binding = 6, std430) buffer Buffer6\n"
827 << " uint numSubgroupsExecuted;\n"
830 << "void main (void)\n"
832 << " if (subgroupElect())\n"
834 << " b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << ELECTED_VALUE << ";\n"
835 << " atomicAdd(b6.numSubgroupsExecuted, 1);\n"
839 << " b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = " << UNELECTED_VALUE << ";\n"
841 << " float pixelSize = 2.0f/1024.0f;\n"
842 << " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
844 programCollection.add("tese") << glu::TessellationEvaluationSource(tese.str());
847 std::ostringstream geometry;
848 geometry << "#version 450\n"
849 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
850 << "layout(${TOPOLOGY}) in;\n"
851 << "layout(points, max_vertices = 1) out;\n"
852 << "layout(binding = 3, std430) buffer Buffer3\n"
854 << " uint result[];\n"
856 << "layout(binding = 7, std430) buffer Buffer7\n"
858 << " uint numSubgroupsExecuted;\n"
861 << "void main (void)\n"
863 << " if (subgroupElect())\n"
865 << " b3.result[gl_PrimitiveIDIn] = " << ELECTED_VALUE << ";\n"
866 << " atomicAdd(b7.numSubgroupsExecuted, 1);\n"
870 << " b3.result[gl_PrimitiveIDIn] = " << UNELECTED_VALUE << ";\n"
872 << " gl_Position = gl_in[0].gl_Position;\n"
873 << " EmitVertex();\n"
874 << " EndPrimitive();\n"
876 subgroups::addGeometryShadersFromTemplate(geometry.str(), programCollection);
880 std::ostringstream fragment;
881 fragment << "#version 450\n"
882 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
883 << "layout(location = 0) out uint data;\n"
884 << "layout(binding = 8, std430) buffer Buffer8\n"
886 << " uint numSubgroupsExecuted;\n"
888 << "void main (void)\n"
890 << " if (gl_HelperInvocation) return;\n"
891 << " if (subgroupElect())\n"
893 << " data = " << ELECTED_VALUE << ";\n"
894 << " atomicAdd(b8.numSubgroupsExecuted, 1);\n"
898 << " data = " << UNELECTED_VALUE << ";\n"
901 programCollection.add("fragment") << glu::FragmentSource(fragment.str());
903 subgroups::addNoSubgroupShader(programCollection);
908 std::ostringstream bdy;
910 switch (caseDef.opType)
913 DE_FATAL("Unhandled op type!");
915 case OPTYPE_SUBGROUP_BARRIER:
916 case OPTYPE_SUBGROUP_MEMORY_BARRIER:
917 case OPTYPE_SUBGROUP_MEMORY_BARRIER_BUFFER:
918 bdy << " if (subgroupElect())\n"
920 << " b${SSBO1}.tempBuffer[id] = b${SSBO2}.value;\n"
922 << " " << getOpTypeName(caseDef.opType) << "();\n"
923 << " tempResult = b${SSBO1}.tempBuffer[id];\n";
925 case OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED:
926 bdy << " if (subgroupElect())\n"
928 << " tempShared[localId] = b${SSBO2}.value;\n"
930 << " subgroupMemoryBarrierShared();\n"
931 << " tempResult = tempShared[localId];\n";
933 case OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE:
934 bdy << " if (subgroupElect())\n"
936 << " imageStore(tempImage${IMG1}, ivec2(id, 0), ivec4(b${SSBO2}.value));\n"
938 << " subgroupMemoryBarrierImage();\n"
939 << " tempResult = imageLoad(tempImage${IMG1}, ivec2(id, 0)).x;\n";
943 tcu::StringTemplate bdyTemplate(bdy.str());
945 if (subgroups::SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
947 std::ostringstream src;
948 map<string, string> bufferNameMapping;
949 bufferNameMapping.insert(pair<string, string>("SSBO1", "1"));
950 bufferNameMapping.insert(pair<string, string>("SSBO2", "2"));
951 bufferNameMapping.insert(pair<string, string>("IMG1", "0"));
953 src << "#version 450\n"
954 << "#extension GL_KHR_shader_subgroup_basic: enable\n"
955 << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
956 << "layout(binding = 0, std430) buffer Buffer0\n"
958 << " uint result[];\n"
960 << "layout(binding = 1, std430) buffer Buffer1\n"
962 << " uint tempBuffer[];\n"
964 << "layout(binding = 2, std430) buffer Buffer2\n"
968 << "layout(binding = 0, r32ui) uniform uimage2D tempImage0;\n"
969 << "shared uint tempShared[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
971 << "void main (void)\n"
973 << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
974 << " highp uint offset = globalSize.x * ((globalSize.y * "
975 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
976 "gl_GlobalInvocationID.x;\n"
977 << " uint localId = gl_SubgroupID;\n"
978 << " uint id = globalSize.x * ((globalSize.y * "
979 "gl_WorkGroupID.z) + gl_WorkGroupID.y) + "
980 "gl_WorkGroupID.x + localId;\n"
981 << " uint tempResult = 0;\n"
982 << bdyTemplate.specialize(bufferNameMapping)
983 << " b0.result[offset] = tempResult;\n"
986 programCollection.add("comp") << glu::ComputeSource(src.str());
991 map<string, string> bufferNameMapping;
992 bufferNameMapping.insert(pair<string, string>("SSBO1", "4"));
993 bufferNameMapping.insert(pair<string, string>("SSBO2", "6"));
994 bufferNameMapping.insert(pair<string, string>("IMG1", "0"));
996 const string vertex =
998 "#extension GL_KHR_shader_subgroup_basic: enable\n"
999 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1000 "layout(binding = 0, std430) buffer Buffer0\n"
1004 "layout(binding = 4, std430) buffer Buffer4\n"
1006 " uint tempBuffer[];\n"
1008 "layout(binding = 5, std430) buffer Buffer5\n"
1010 " uint subgroupID;\n"
1012 "layout(binding = 6, std430) buffer Buffer6\n"
1016 "layout(binding = 0, r32ui) uniform uimage2D tempImage0;\n"
1017 "void main (void)\n"
1020 " if (subgroupElect())\n"
1022 " id = atomicAdd(b5.subgroupID, 1);\n"
1024 " id = subgroupBroadcastFirst(id);\n"
1025 " uint localId = id;\n"
1026 " uint tempResult = 0;\n"
1027 + bdyTemplate.specialize(bufferNameMapping) +
1028 " b0.result[gl_VertexID] = tempResult;\n"
1029 " float pixelSize = 2.0f/1024.0f;\n"
1030 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
1031 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
1032 " gl_PointSize = 1.0f;\n"
1034 programCollection.add("vert") << glu::VertexSource(vertex);
1038 map<string, string> bufferNameMapping;
1039 bufferNameMapping.insert(pair<string, string>("SSBO1", "7"));
1040 bufferNameMapping.insert(pair<string, string>("SSBO2", "9"));
1041 bufferNameMapping.insert(pair<string, string>("IMG1", "1"));
1045 "#extension GL_KHR_shader_subgroup_basic: enable\n"
1046 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1047 "layout(vertices=1) out;\n"
1048 "layout(binding = 1, std430) buffer Buffer1\n"
1052 "layout(binding = 7, std430) buffer Buffer7\n"
1054 " uint tempBuffer[];\n"
1056 "layout(binding = 8, std430) buffer Buffer8\n"
1058 " uint subgroupID;\n"
1060 "layout(binding = 9, std430) buffer Buffer9\n"
1064 "layout(binding = 1, r32ui) uniform uimage2D tempImage1;\n"
1065 "void main (void)\n"
1068 " if (subgroupElect())\n"
1070 " id = atomicAdd(b8.subgroupID, 1);\n"
1072 " id = subgroupBroadcastFirst(id);\n"
1073 " uint localId = id;\n"
1074 " uint tempResult = 0;\n"
1075 + bdyTemplate.specialize(bufferNameMapping) +
1076 " b1.result[gl_PrimitiveID] = tempResult;\n"
1077 " if (gl_InvocationID == 0)\n"
1079 " gl_TessLevelOuter[0] = 1.0f;\n"
1080 " gl_TessLevelOuter[1] = 1.0f;\n"
1082 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1084 programCollection.add("tesc") << glu::TessellationControlSource(tesc);
1088 map<string, string> bufferNameMapping;
1089 bufferNameMapping.insert(pair<string, string>("SSBO1", "10"));
1090 bufferNameMapping.insert(pair<string, string>("SSBO2", "12"));
1091 bufferNameMapping.insert(pair<string, string>("IMG1", "2"));
1095 "#extension GL_KHR_shader_subgroup_basic: enable\n"
1096 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1097 "layout(isolines) in;\n"
1098 "layout(binding = 2, std430) buffer Buffer2\n"
1102 "layout(binding = 10, std430) buffer Buffer10\n"
1104 " uint tempBuffer[];\n"
1106 "layout(binding = 11, std430) buffer Buffer11\n"
1108 " uint subgroupID;\n"
1110 "layout(binding = 12, std430) buffer Buffer12\n"
1114 "layout(binding = 2, r32ui) uniform uimage2D tempImage2;\n"
1115 "void main (void)\n"
1118 " if (subgroupElect())\n"
1120 " id = atomicAdd(b11.subgroupID, 1);\n"
1122 " id = subgroupBroadcastFirst(id);\n"
1123 " uint localId = id;\n"
1124 " uint tempResult = 0;\n"
1125 + bdyTemplate.specialize(bufferNameMapping) +
1126 " b2.result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
1127 " float pixelSize = 2.0f/1024.0f;\n"" gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
1129 programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
1132 map<string, string> bufferNameMapping;
1133 bufferNameMapping.insert(pair<string, string>("SSBO1", "13"));
1134 bufferNameMapping.insert(pair<string, string>("SSBO2", "15"));
1135 bufferNameMapping.insert(pair<string, string>("IMG1", "3"));
1137 const string geometry =
1139 "#extension GL_KHR_shader_subgroup_basic: enable\n"
1140 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1141 "layout(${TOPOLOGY}) in;\n"
1142 "layout(points, max_vertices = 1) out;\n"
1143 "layout(binding = 3, std430) buffer Buffer3\n"
1147 "layout(binding = 13, std430) buffer Buffer13\n"
1149 " uint tempBuffer[];\n"
1151 "layout(binding = 14, std430) buffer Buffer14\n"
1153 " uint subgroupID;\n"
1155 "layout(binding = 15, std430) buffer Buffer15\n"
1159 "layout(binding = 3, r32ui) uniform uimage2D tempImage3;\n"
1160 "void main (void)\n"
1163 " if (subgroupElect())\n"
1165 " id = atomicAdd(b14.subgroupID, 1);\n"
1167 " id = subgroupBroadcastFirst(id);\n"
1168 " uint localId = id;\n"
1169 " uint tempResult = 0;\n"
1170 + bdyTemplate.specialize(bufferNameMapping) +
1171 " b3.result[gl_PrimitiveIDIn] = tempResult;\n"
1172 " gl_Position = gl_in[0].gl_Position;\n"
1174 " EndPrimitive();\n"
1176 subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
1180 map<string, string> bufferNameMapping;
1181 bufferNameMapping.insert(pair<string, string>("SSBO1", "16"));
1182 bufferNameMapping.insert(pair<string, string>("SSBO2", "18"));
1183 bufferNameMapping.insert(pair<string, string>("IMG1", "4"));
1185 const string fragment =
1187 "#extension GL_KHR_shader_subgroup_basic: enable\n"
1188 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
1189 "layout(location = 0) out uint result;\n"
1190 "layout(binding = 16, std430) buffer Buffer16\n"
1192 " uint tempBuffer[];\n"
1194 "layout(binding = 17, std430) buffer Buffer17\n"
1196 " uint subgroupID;\n"
1198 "layout(binding = 18, std430) buffer Buffer18\n"
1202 "layout(binding = 4, r32ui) uniform uimage2D tempImage4;\n"
1203 "void main (void)\n"
1205 " if (gl_HelperInvocation) return;\n"
1207 " if (subgroupElect())\n"
1209 " id = atomicAdd(b17.subgroupID, 1);\n"
1211 " id = subgroupBroadcastFirst(id);\n"
1212 " uint localId = id;\n"
1213 " uint tempResult = 0;\n"
1214 + bdyTemplate.specialize(bufferNameMapping) +
1215 " result = tempResult;\n"
1217 programCollection.add("fragment") << glu::FragmentSource(fragment);
1220 subgroups::addNoSubgroupShader(programCollection);
1225 void supportedCheck (Context& context, CaseDefinition caseDef)
1228 if (!subgroups::isSubgroupSupported(context))
1229 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
1232 tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef)
1234 if (!subgroups::areSubgroupOperationsSupportedForStage(
1235 context, caseDef.shaderStage))
1237 if (subgroups::areSubgroupOperationsRequiredForStage(
1238 caseDef.shaderStage))
1240 return tcu::TestStatus::fail(
1242 subgroups::getShaderStageName(caseDef.shaderStage) +
1243 " is required to support subgroup operations!");
1247 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
1251 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BASIC_BIT))
1253 return tcu::TestStatus::fail(
1254 "Subgroup feature " +
1255 subgroups::getSubgroupFeatureName(subgroups::SUBGROUP_FEATURE_BASIC_BIT) +
1256 " is a required capability!");
1259 if (OPTYPE_ELECT != caseDef.opType && subgroups::SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1261 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BALLOT_BIT))
1263 TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1267 const deUint32 inputDatasCount = OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType ? 3u : 2u;
1268 std::vector<subgroups::SSBOData> inputDatas (inputDatasCount);
1270 inputDatas[0].format = subgroups::FORMAT_R32_UINT;
1271 inputDatas[0].numElements = SHADER_BUFFER_SIZE/4ull;
1272 inputDatas[0].initializeType = subgroups::SSBOData::InitializeNonZero;
1273 inputDatas[0].binding = 0u;
1275 inputDatas[1].format = subgroups::FORMAT_R32_UINT;
1276 inputDatas[1].numElements = 1ull;
1277 inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1278 inputDatas[1].binding = 1u;
1280 if(OPTYPE_SUBGROUP_MEMORY_BARRIER_IMAGE == caseDef.opType )
1282 inputDatas[2].format = subgroups::FORMAT_R32_UINT;
1283 inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1284 inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1285 inputDatas[2].isImage = true;
1286 inputDatas[2].binding = 0u;
1289 if (subgroups::SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
1291 if (OPTYPE_ELECT == caseDef.opType)
1292 return subgroups::makeVertexFrameBufferTest(context, subgroups::FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1294 return subgroups::makeVertexFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkVertexPipelineStagesSubgroupBarriersNoSSBO);
1296 else if (subgroups::SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
1298 return subgroups::makeFragmentFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkFragmentSubgroupBarriersNoSSBO);
1300 else if (subgroups::SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
1302 if (OPTYPE_ELECT == caseDef.opType)
1303 return subgroups::makeGeometryFrameBufferTest(context, subgroups::FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO);
1305 return subgroups::makeGeometryFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount, checkVertexPipelineStagesSubgroupBarriersNoSSBO);
1308 if (OPTYPE_ELECT == caseDef.opType)
1309 return subgroups::makeTessellationEvaluationFrameBufferTest(context, subgroups::FORMAT_R32G32_SFLOAT, DE_NULL, 0u, checkVertexPipelineStagesSubgroupElectNoSSBO, caseDef.shaderStage);
1311 return subgroups::makeTessellationEvaluationFrameBufferTest(context, subgroups::FORMAT_R32G32B32A32_SFLOAT, &inputDatas[0], inputDatasCount,
1312 (subgroups::SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)? checkVertexPipelineStagesSubgroupBarriersNoSSBO : checkTessellationEvaluationSubgroupBarriersNoSSBO,
1313 caseDef.shaderStage);
1316 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
1318 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BASIC_BIT))
1320 return tcu::TestStatus::fail(
1321 "Subgroup feature " +
1322 subgroups::getSubgroupFeatureName(subgroups::SUBGROUP_FEATURE_BASIC_BIT) +
1323 " is a required capability!");
1326 if (OPTYPE_ELECT != caseDef.opType && subgroups::SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage)
1328 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, subgroups::SUBGROUP_FEATURE_BALLOT_BIT))
1330 TCU_THROW(NotSupportedError, "Subgroup basic operation non-compute stage test required that ballot operations are supported!");
1334 if (subgroups::SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
1336 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
1338 return tcu::TestStatus::fail("Shader stage " +
1339 subgroups::getShaderStageName(caseDef.shaderStage) +
1340 " is required to support subgroup operations!");
1343 if (OPTYPE_ELECT == caseDef.opType)
1345 return subgroups::makeComputeTest(context, subgroups::FORMAT_R32_UINT, DE_NULL, 0, checkComputeSubgroupElect);
1349 const deUint32 inputDatasCount = 3;
1350 subgroups::SSBOData inputDatas[inputDatasCount];
1351 inputDatas[0].format = subgroups::FORMAT_R32_UINT;
1352 inputDatas[0].numElements = SHADER_BUFFER_SIZE;
1353 inputDatas[0].initializeType = subgroups::SSBOData::InitializeNone;
1354 inputDatas[0].binding = 1u;
1356 inputDatas[1].format = subgroups::FORMAT_R32_UINT;
1357 inputDatas[1].numElements = 1;
1358 inputDatas[1].initializeType = subgroups::SSBOData::InitializeNonZero;
1359 inputDatas[1].binding = 2u;
1361 inputDatas[2].format = subgroups::FORMAT_R32_UINT;
1362 inputDatas[2].numElements = SHADER_BUFFER_SIZE;
1363 inputDatas[2].initializeType = subgroups::SSBOData::InitializeNone;
1364 inputDatas[2].isImage = true;
1365 inputDatas[2].binding = 0u;
1367 return subgroups::makeComputeTest(context, subgroups::FORMAT_R32_UINT, inputDatas, inputDatasCount, checkComputeSubgroupBarriers);
1372 if (!subgroups::isFragmentSSBOSupportedForDevice(context))
1374 TCU_THROW(NotSupportedError, "Subgroup basic operation require that the fragment stage be able to write to SSBOs!");
1377 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
1379 subgroups::ShaderStageFlags stages = (subgroups::ShaderStageFlags)(caseDef.shaderStage & supportedStages);
1381 if ( subgroups::SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
1383 if ( (stages & subgroups::SHADER_STAGE_FRAGMENT_BIT) == 0)
1384 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
1386 stages = subgroups::SHADER_STAGE_FRAGMENT_BIT;
1389 if ((subgroups::ShaderStageFlags)0u == stages)
1390 TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
1392 if (OPTYPE_ELECT == caseDef.opType)
1394 const deUint32 inputCount = 5u;
1395 subgroups::SSBOData inputData[inputCount];
1397 inputData[0].format = subgroups::FORMAT_R32_UINT;
1398 inputData[0].numElements = 1;
1399 inputData[0].initializeType = subgroups::SSBOData::InitializeZero;
1400 inputData[0].binding = 4u;
1401 inputData[0].stages = subgroups::SHADER_STAGE_VERTEX_BIT;
1403 inputData[1].format = subgroups::FORMAT_R32_UINT;
1404 inputData[1].numElements = 1;
1405 inputData[1].initializeType = subgroups::SSBOData::InitializeZero;
1406 inputData[1].binding = 5u;
1407 inputData[1].stages = subgroups::SHADER_STAGE_TESS_CONTROL_BIT;
1409 inputData[2].format = subgroups::FORMAT_R32_UINT;
1410 inputData[2].numElements = 1;
1411 inputData[2].initializeType = subgroups::SSBOData::InitializeZero;
1412 inputData[2].binding = 6u;
1413 inputData[2].stages = subgroups::SHADER_STAGE_TESS_EVALUATION_BIT;
1415 inputData[3].format = subgroups::FORMAT_R32_UINT;
1416 inputData[3].numElements = 1;
1417 inputData[3].initializeType = subgroups::SSBOData::InitializeZero;
1418 inputData[3].binding = 7u;
1419 inputData[3].stages = subgroups::SHADER_STAGE_GEOMETRY_BIT;
1421 inputData[4].format = subgroups::FORMAT_R32_UINT;
1422 inputData[4].numElements = 1;
1423 inputData[4].initializeType = subgroups::SSBOData::InitializeZero;
1424 inputData[4].binding = 8u;
1425 inputData[4].stages = subgroups::SHADER_STAGE_FRAGMENT_BIT;
1427 return subgroups::allStages(context, subgroups::FORMAT_R32_UINT, inputData, inputCount, checkVertexPipelineStagesSubgroupElect, stages);
1431 const subgroups::ShaderStageFlags stagesBits[] =
1433 subgroups::SHADER_STAGE_VERTEX_BIT,
1434 subgroups::SHADER_STAGE_TESS_CONTROL_BIT,
1435 subgroups::SHADER_STAGE_TESS_EVALUATION_BIT,
1436 subgroups::SHADER_STAGE_GEOMETRY_BIT,
1437 subgroups::SHADER_STAGE_FRAGMENT_BIT,
1440 const deUint32 inputDatasCount = DE_LENGTH_OF_ARRAY(stagesBits) * 4u;
1441 subgroups::SSBOData inputDatas[inputDatasCount];
1443 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stagesBits); ++ndx)
1445 const deUint32 index = ndx*4;
1446 const deUint32 ssboIndex = ndx*3;
1447 const deUint32 imgIndex = ndx;
1448 inputDatas[index].format = subgroups::FORMAT_R32_UINT;
1449 inputDatas[index].numElements = SHADER_BUFFER_SIZE;
1450 inputDatas[index].initializeType = subgroups::SSBOData::InitializeNonZero;
1451 inputDatas[index].binding = ssboIndex + 4u;
1452 inputDatas[index].stages = stagesBits[ndx];
1454 inputDatas[index + 1].format = subgroups::FORMAT_R32_UINT;
1455 inputDatas[index + 1].numElements = 1;
1456 inputDatas[index + 1].initializeType = subgroups::SSBOData::InitializeZero;
1457 inputDatas[index + 1].binding = ssboIndex + 5u;
1458 inputDatas[index + 1].stages = stagesBits[ndx];
1460 inputDatas[index + 2].format = subgroups::FORMAT_R32_UINT;
1461 inputDatas[index + 2].numElements = 1;
1462 inputDatas[index + 2].initializeType = subgroups::SSBOData::InitializeNonZero;
1463 inputDatas[index + 2].binding = ssboIndex + 6u;
1464 inputDatas[index + 2].stages = stagesBits[ndx];
1466 inputDatas[index + 3].format = subgroups::FORMAT_R32_UINT;
1467 inputDatas[index + 3].numElements = SHADER_BUFFER_SIZE;
1468 inputDatas[index + 3].initializeType = subgroups::SSBOData::InitializeNone;
1469 inputDatas[index + 3].isImage = true;
1470 inputDatas[index + 3].binding = imgIndex;
1471 inputDatas[index + 3].stages = stagesBits[ndx];
1474 return subgroups::allStages(context, subgroups::FORMAT_R32_UINT, inputDatas, inputDatasCount, checkVertexPipelineStagesSubgroupBarriers, stages);
1480 deqp::TestCaseGroup* createSubgroupsBasicTests(deqp::Context& testCtx)
1482 de::MovePtr<deqp::TestCaseGroup> graphicGroup(new deqp::TestCaseGroup(
1483 testCtx, "graphics", "Subgroup basic category tests: graphics"));
1484 de::MovePtr<deqp::TestCaseGroup> computeGroup(new deqp::TestCaseGroup(
1485 testCtx, "compute", "Subgroup basic category tests: compute"));
1486 de::MovePtr<deqp::TestCaseGroup> framebufferGroup(new deqp::TestCaseGroup(
1487 testCtx, "framebuffer", "Subgroup basic category tests: framebuffer"));
1489 const subgroups::ShaderStageFlags stages[] =
1491 SHADER_STAGE_FRAGMENT_BIT,
1492 SHADER_STAGE_VERTEX_BIT,
1493 SHADER_STAGE_TESS_EVALUATION_BIT,
1494 SHADER_STAGE_TESS_CONTROL_BIT,
1495 SHADER_STAGE_GEOMETRY_BIT,
1498 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
1500 const std::string op = de::toLower(getOpTypeName(opTypeIndex));
1503 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT};
1504 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(computeGroup.get(), op, "",
1505 supportedCheck, initPrograms, test, caseDef);
1508 if (OPTYPE_SUBGROUP_MEMORY_BARRIER_SHARED == opTypeIndex)
1510 // Shared isn't available in non compute shaders.
1515 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS};
1516 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(graphicGroup.get(),
1518 supportedCheck, initPrograms, test, caseDef);
1521 if (OPTYPE_ELECT == opTypeIndex)
1523 for (int stageIndex = 1; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
1525 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex]};
1526 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
1527 op + "_" + getShaderStageName(caseDef.shaderStage), "",
1528 supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef);
1533 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
1535 const CaseDefinition caseDefFrag = {opTypeIndex, stages[stageIndex]};
1536 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(framebufferGroup.get(),
1537 op + "_" + getShaderStageName(caseDefFrag.shaderStage), "",
1538 supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDefFrag);
1544 de::MovePtr<deqp::TestCaseGroup> group(new deqp::TestCaseGroup(
1545 testCtx, "basic", "Subgroup basic category tests"));
1547 group->addChild(graphicGroup.release());
1548 group->addChild(computeGroup.release());
1549 group->addChild(framebufferGroup.release());
1551 return group.release();