1 /*------------------------------------------------------------------------
2 * OpenGL Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017-2019 The Khronos Group Inc.
6 * Copyright (c) 2017 Codeplay Software Ltd.
7 * Copyright (c) 2019 NVIDIA Corporation.
8 *
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
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
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.
20 *
21 */ /*!
22 * \file
23 * \brief Subgroups Tests
24 */ /*--------------------------------------------------------------------*/
25
26 #include "glcSubgroupsShuffleTests.hpp"
27 #include "glcSubgroupsTestsUtils.hpp"
28
29 #include <string>
30 #include <vector>
31
32 using namespace tcu;
33 using namespace std;
34
35 namespace glc
36 {
37 namespace subgroups
38 {
39 namespace
40 {
41 enum OpType
42 {
43 OPTYPE_SHUFFLE = 0,
44 OPTYPE_SHUFFLE_XOR,
45 OPTYPE_SHUFFLE_UP,
46 OPTYPE_SHUFFLE_DOWN,
47 OPTYPE_LAST
48 };
49
checkVertexPipelineStages(std::vector<const void * > datas,uint32_t width,uint32_t)50 static bool checkVertexPipelineStages(std::vector<const void *> datas, uint32_t width, uint32_t)
51 {
52 return glc::subgroups::check(datas, width, 1);
53 }
54
checkComputeStage(std::vector<const void * > datas,const uint32_t numWorkgroups[3],const uint32_t localSize[3],uint32_t)55 static bool checkComputeStage(std::vector<const void *> datas, const uint32_t numWorkgroups[3],
56 const uint32_t localSize[3], uint32_t)
57 {
58 return glc::subgroups::checkCompute(datas, numWorkgroups, localSize, 1);
59 }
60
getOpTypeName(int opType)61 std::string getOpTypeName(int opType)
62 {
63 switch (opType)
64 {
65 default:
66 DE_FATAL("Unsupported op type");
67 return "";
68 case OPTYPE_SHUFFLE:
69 return "subgroupShuffle";
70 case OPTYPE_SHUFFLE_XOR:
71 return "subgroupShuffleXor";
72 case OPTYPE_SHUFFLE_UP:
73 return "subgroupShuffleUp";
74 case OPTYPE_SHUFFLE_DOWN:
75 return "subgroupShuffleDown";
76 }
77 }
78
79 struct CaseDefinition
80 {
81 int opType;
82 ShaderStageFlags shaderStage;
83 Format format;
84 };
85
to_string(int x)86 const std::string to_string(int x)
87 {
88 std::ostringstream oss;
89 oss << x;
90 return oss.str();
91 }
92
DeclSource(CaseDefinition caseDef,int baseBinding)93 const std::string DeclSource(CaseDefinition caseDef, int baseBinding)
94 {
95 return "layout(binding = " + to_string(baseBinding) +
96 ", std430) readonly buffer BufferB0\n"
97 "{\n"
98 " " +
99 subgroups::getFormatNameForGLSL(caseDef.format) +
100 " data1[];\n"
101 "};\n"
102 "layout(binding = " +
103 to_string(baseBinding + 1) +
104 ", std430) readonly buffer BufferB1\n"
105 "{\n"
106 " uint data2[];\n"
107 "};\n";
108 }
109
TestSource(CaseDefinition caseDef)110 const std::string TestSource(CaseDefinition caseDef)
111 {
112 std::string idTable[OPTYPE_LAST];
113 idTable[OPTYPE_SHUFFLE] = "id_in";
114 idTable[OPTYPE_SHUFFLE_XOR] = "gl_SubgroupInvocationID ^ id_in";
115 idTable[OPTYPE_SHUFFLE_UP] = "gl_SubgroupInvocationID - id_in";
116 idTable[OPTYPE_SHUFFLE_DOWN] = "gl_SubgroupInvocationID + id_in";
117
118 const std::string testSource =
119 " uint temp_res;\n"
120 " uvec4 mask = subgroupBallot(true);\n"
121 " uint id_in = data2[gl_SubgroupInvocationID] & (gl_SubgroupSize - 1u);\n"
122 " " +
123 subgroups::getFormatNameForGLSL(caseDef.format) + " op = " + getOpTypeName(caseDef.opType) +
124 "(data1[gl_SubgroupInvocationID], id_in);\n"
125 " uint id = " +
126 idTable[caseDef.opType] +
127 ";\n"
128 " if ((id < gl_SubgroupSize) && subgroupBallotBitExtract(mask, id))\n"
129 " {\n"
130 " temp_res = (op == data1[id]) ? 1u : 0u;\n"
131 " }\n"
132 " else\n"
133 " {\n"
134 " temp_res = 1u; // Invocation we read from was inactive, so we can't verify results!\n"
135 " }\n";
136
137 return testSource;
138 }
139
initFrameBufferPrograms(SourceCollections & programCollection,CaseDefinition caseDef)140 void initFrameBufferPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
141 {
142 subgroups::setFragmentShaderFrameBuffer(programCollection);
143
144 if (SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage)
145 subgroups::setVertexShaderFrameBuffer(programCollection);
146
147 const std::string extSource = (OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType) ?
148 "#extension GL_KHR_shader_subgroup_shuffle: enable\n" :
149 "#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
150
151 const std::string testSource = TestSource(caseDef);
152
153 if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
154 {
155 std::ostringstream vertexSrc;
156 vertexSrc << "${VERSION_DECL}\n"
157 << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
158 << "layout(location = 0) in highp vec4 in_position;\n"
159 << "layout(location = 0) out float result;\n"
160 << "layout(binding = 0, std140) uniform Buffer0\n"
161 << "{\n"
162 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
163 << subgroups::maxSupportedSubgroupSize() << "];\n"
164 << "};\n"
165 << "layout(binding = 1, std140) uniform Buffer1\n"
166 << "{\n"
167 << " uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
168 << "};\n"
169 << "\n"
170 << "void main (void)\n"
171 << "{\n"
172 << testSource << " result = float(temp_res);\n"
173 << " gl_Position = in_position;\n"
174 << " gl_PointSize = 1.0f;\n"
175 << "}\n";
176 programCollection.add("vert") << glu::VertexSource(vertexSrc.str());
177 }
178 else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
179 {
180 std::ostringstream geometry;
181
182 geometry << "${VERSION_DECL}\n"
183 << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
184 << "layout(points) in;\n"
185 << "layout(points, max_vertices = 1) out;\n"
186 << "layout(location = 0) out float out_color;\n"
187 << "layout(binding = 0, std140) uniform Buffer0\n"
188 << "{\n"
189 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
190 << subgroups::maxSupportedSubgroupSize() << "];\n"
191 << "};\n"
192 << "layout(binding = 1, std140) uniform Buffer1\n"
193 << "{\n"
194 << " uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
195 << "};\n"
196 << "\n"
197 << "void main (void)\n"
198 << "{\n"
199 << testSource << " out_color = float(temp_res);\n"
200 << " gl_Position = gl_in[0].gl_Position;\n"
201 << " EmitVertex();\n"
202 << " EndPrimitive();\n"
203 << "}\n";
204
205 programCollection.add("geometry") << glu::GeometrySource(geometry.str());
206 }
207 else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
208 {
209 std::ostringstream controlSource;
210
211 controlSource << "${VERSION_DECL}\n"
212 << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
213 << "layout(vertices = 2) out;\n"
214 << "layout(location = 0) out float out_color[];\n"
215 << "layout(binding = 0, std140) uniform Buffer0\n"
216 << "{\n"
217 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
218 << subgroups::maxSupportedSubgroupSize() << "];\n"
219 << "};\n"
220 << "layout(binding = 1, std140) uniform Buffer1\n"
221 << "{\n"
222 << " uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
223 << "};\n"
224 << "\n"
225 << "void main (void)\n"
226 << "{\n"
227 << " if (gl_InvocationID == 0)\n"
228 << " {\n"
229 << " gl_TessLevelOuter[0] = 1.0f;\n"
230 << " gl_TessLevelOuter[1] = 1.0f;\n"
231 << " }\n"
232 << testSource << " out_color[gl_InvocationID] = float(temp_res);\n"
233 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
234 << "}\n";
235
236 programCollection.add("tesc") << glu::TessellationControlSource(controlSource.str());
237 subgroups::setTesEvalShaderFrameBuffer(programCollection);
238 }
239 else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
240 {
241 std::ostringstream evaluationSource;
242 evaluationSource << "${VERSION_DECL}\n"
243 << extSource << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
244 << "layout(isolines, equal_spacing, ccw ) in;\n"
245 << "layout(location = 0) out float out_color;\n"
246 << "layout(binding = 0, std140) uniform Buffer0\n"
247 << "{\n"
248 << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " data1["
249 << subgroups::maxSupportedSubgroupSize() << "];\n"
250 << "};\n"
251 << "layout(binding = 1, std140) uniform Buffer1\n"
252 << "{\n"
253 << " uint data2[" << subgroups::maxSupportedSubgroupSize() << "];\n"
254 << "};\n"
255 << "\n"
256 << "void main (void)\n"
257 << "{\n"
258 << testSource << " out_color = float(temp_res);\n"
259 << " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
260 << "}\n";
261
262 subgroups::setTesCtrlShaderFrameBuffer(programCollection);
263 programCollection.add("tese") << glu::TessellationEvaluationSource(evaluationSource.str());
264 }
265 else
266 {
267 DE_FATAL("Unsupported shader stage");
268 }
269 }
270
initPrograms(SourceCollections & programCollection,CaseDefinition caseDef)271 void initPrograms(SourceCollections &programCollection, CaseDefinition caseDef)
272 {
273 const std::string versionSource = "${VERSION_DECL}\n";
274 const std::string vSource = "#extension GL_KHR_shader_subgroup_ballot: enable\n";
275 const std::string eSource = (OPTYPE_SHUFFLE == caseDef.opType || OPTYPE_SHUFFLE_XOR == caseDef.opType) ?
276 "#extension GL_KHR_shader_subgroup_shuffle: enable\n" :
277 "#extension GL_KHR_shader_subgroup_shuffle_relative: enable\n";
278 const std::string extSource = vSource + eSource;
279
280 const std::string testSource = TestSource(caseDef);
281
282 if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
283 {
284 std::ostringstream src;
285
286 src << versionSource + extSource << "layout (${LOCAL_SIZE_X}, ${LOCAL_SIZE_Y}, ${LOCAL_SIZE_Z}) in;\n"
287 << "layout(binding = 0, std430) buffer Buffer0\n"
288 << "{\n"
289 << " uint result[];\n"
290 << "};\n"
291 << DeclSource(caseDef, 1) << "\n"
292 << "void main (void)\n"
293 << "{\n"
294 << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
295 << " highp uint offset = globalSize.x * ((globalSize.y * "
296 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
297 "gl_GlobalInvocationID.x;\n"
298 << testSource << " result[offset] = temp_res;\n"
299 << "}\n";
300
301 programCollection.add("comp") << glu::ComputeSource(src.str());
302 }
303 else
304 {
305 const std::string declSource = DeclSource(caseDef, 4);
306
307 {
308 const string vertex =
309 versionSource + extSource +
310 "layout(binding = 0, std430) buffer Buffer0\n"
311 "{\n"
312 " uint result[];\n"
313 "} b0;\n" +
314 declSource +
315 "\n"
316 "void main (void)\n"
317 "{\n" +
318 testSource +
319 " b0.result[gl_VertexID] = temp_res;\n"
320 " float pixelSize = 2.0f/1024.0f;\n"
321 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
322 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
323 " gl_PointSize = 1.0f;\n"
324 "}\n";
325
326 programCollection.add("vert") << glu::VertexSource(vertex);
327 }
328
329 {
330 const string tesc = versionSource + extSource +
331 "layout(vertices=1) out;\n"
332 "layout(binding = 1, std430) buffer Buffer1\n"
333 "{\n"
334 " uint result[];\n"
335 "} b1;\n" +
336 declSource +
337 "\n"
338 "void main (void)\n"
339 "{\n" +
340 testSource +
341 " b1.result[gl_PrimitiveID] = temp_res;\n"
342 " if (gl_InvocationID == 0)\n"
343 " {\n"
344 " gl_TessLevelOuter[0] = 1.0f;\n"
345 " gl_TessLevelOuter[1] = 1.0f;\n"
346 " }\n"
347 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
348 "}\n";
349
350 programCollection.add("tesc") << glu::TessellationControlSource(tesc);
351 }
352
353 {
354 const string tese = versionSource + extSource +
355 "layout(isolines) in;\n"
356 "layout(binding = 2, std430) buffer Buffer2\n"
357 "{\n"
358 " uint result[];\n"
359 "} b2;\n" +
360 declSource +
361 "\n"
362 "void main (void)\n"
363 "{\n" +
364 testSource +
365 " b2.result[gl_PrimitiveID * 2 + int(gl_TessCoord.x + 0.5)] = temp_res;\n"
366 " float pixelSize = 2.0f/1024.0f;\n"
367 " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
368 "}\n";
369
370 programCollection.add("tese") << glu::TessellationEvaluationSource(tese);
371 }
372
373 {
374 const string geometry =
375 // version is added by addGeometryShadersFromTemplate
376 extSource +
377 "layout(${TOPOLOGY}) in;\n"
378 "layout(points, max_vertices = 1) out;\n"
379 "layout(binding = 3, std430) buffer Buffer3\n"
380 "{\n"
381 " uint result[];\n"
382 "} b3;\n" +
383 declSource +
384 "\n"
385 "void main (void)\n"
386 "{\n" +
387 testSource +
388 " b3.result[gl_PrimitiveIDIn] = temp_res;\n"
389 " gl_Position = gl_in[0].gl_Position;\n"
390 " EmitVertex();\n"
391 " EndPrimitive();\n"
392 "}\n";
393
394 subgroups::addGeometryShadersFromTemplate(geometry, programCollection);
395 }
396 {
397 const string fragment = versionSource + extSource +
398 "precision highp int;\n"
399 "precision highp float;\n"
400 "layout(location = 0) out uint result;\n" +
401 declSource +
402 "void main (void)\n"
403 "{\n" +
404 testSource +
405 " result = temp_res;\n"
406 "}\n";
407
408 programCollection.add("fragment") << glu::FragmentSource(fragment);
409 }
410
411 subgroups::addNoSubgroupShader(programCollection);
412 }
413 }
414
supportedCheck(Context & context,CaseDefinition caseDef)415 void supportedCheck(Context &context, CaseDefinition caseDef)
416 {
417 if (!subgroups::isSubgroupSupported(context))
418 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
419
420 switch (caseDef.opType)
421 {
422 case OPTYPE_SHUFFLE:
423 case OPTYPE_SHUFFLE_XOR:
424 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_BIT))
425 {
426 TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
427 }
428 break;
429 default:
430 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
431 {
432 TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
433 }
434 break;
435 }
436
437 if (subgroups::isDoubleFormat(caseDef.format) && !subgroups::isDoubleSupportedForDevice(context))
438 TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
439 }
440
noSSBOtest(Context & context,const CaseDefinition caseDef)441 tcu::TestStatus noSSBOtest(Context &context, const CaseDefinition caseDef)
442 {
443 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
444 {
445 if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
446 {
447 return tcu::TestStatus::fail("Shader stage " + subgroups::getShaderStageName(caseDef.shaderStage) +
448 " is required to support subgroup operations!");
449 }
450 else
451 {
452 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
453 }
454 }
455
456 subgroups::SSBOData inputData[2];
457 inputData[0].format = caseDef.format;
458 inputData[0].layout = subgroups::SSBOData::LayoutStd140;
459 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
460 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
461 inputData[0].binding = 0u;
462
463 inputData[1].format = FORMAT_R32_UINT;
464 inputData[1].layout = subgroups::SSBOData::LayoutStd140;
465 inputData[1].numElements = inputData[0].numElements;
466 inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
467 inputData[1].binding = 1u;
468
469 if (SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
470 return subgroups::makeVertexFrameBufferTest(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages);
471 else if (SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
472 return subgroups::makeGeometryFrameBufferTest(context, FORMAT_R32_UINT, inputData, 2,
473 checkVertexPipelineStages);
474 else if (SHADER_STAGE_TESS_CONTROL_BIT == caseDef.shaderStage)
475 return subgroups::makeTessellationEvaluationFrameBufferTest(
476 context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, SHADER_STAGE_TESS_CONTROL_BIT);
477 else if (SHADER_STAGE_TESS_EVALUATION_BIT == caseDef.shaderStage)
478 return subgroups::makeTessellationEvaluationFrameBufferTest(
479 context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, SHADER_STAGE_TESS_EVALUATION_BIT);
480 else
481 TCU_THROW(InternalError, "Unhandled shader stage");
482 }
483
test(Context & context,const CaseDefinition caseDef)484 tcu::TestStatus test(Context &context, const CaseDefinition caseDef)
485 {
486 switch (caseDef.opType)
487 {
488 case OPTYPE_SHUFFLE:
489 case OPTYPE_SHUFFLE_XOR:
490 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_BIT))
491 {
492 TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle operations");
493 }
494 break;
495 default:
496 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))
497 {
498 TCU_THROW(NotSupportedError, "Device does not support subgroup shuffle relative operations");
499 }
500 break;
501 }
502
503 if (subgroups::isDoubleFormat(caseDef.format) && !subgroups::isDoubleSupportedForDevice(context))
504 {
505 TCU_THROW(NotSupportedError, "Device does not support subgroup double operations");
506 }
507
508 if (SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
509 {
510 if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage))
511 {
512 return tcu::TestStatus::fail("Shader stage " + subgroups::getShaderStageName(caseDef.shaderStage) +
513 " is required to support subgroup operations!");
514 }
515 subgroups::SSBOData inputData[2];
516 inputData[0].format = caseDef.format;
517 inputData[0].layout = subgroups::SSBOData::LayoutStd430;
518 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
519 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
520 inputData[0].binding = 1u;
521
522 inputData[1].format = FORMAT_R32_UINT;
523 inputData[1].layout = subgroups::SSBOData::LayoutStd430;
524 inputData[1].numElements = inputData[0].numElements;
525 inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
526 inputData[1].binding = 2u;
527
528 return subgroups::makeComputeTest(context, FORMAT_R32_UINT, inputData, 2, checkComputeStage);
529 }
530
531 else
532 {
533 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
534
535 ShaderStageFlags stages = (ShaderStageFlags)(caseDef.shaderStage & supportedStages);
536
537 if (SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context))
538 {
539 if ((stages & SHADER_STAGE_FRAGMENT_BIT) == 0)
540 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
541 else
542 stages = SHADER_STAGE_FRAGMENT_BIT;
543 }
544
545 if ((ShaderStageFlags)0u == stages)
546 TCU_THROW(NotSupportedError, "Subgroup operations are not supported for any graphic shader");
547
548 subgroups::SSBOData inputData[2];
549 inputData[0].format = caseDef.format;
550 inputData[0].layout = subgroups::SSBOData::LayoutStd430;
551 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
552 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
553 inputData[0].binding = 4u;
554 inputData[0].stages = stages;
555
556 inputData[1].format = FORMAT_R32_UINT;
557 inputData[1].layout = subgroups::SSBOData::LayoutStd430;
558 inputData[1].numElements = inputData[0].numElements;
559 inputData[1].initializeType = subgroups::SSBOData::InitializeNonZero;
560 inputData[1].binding = 5u;
561 inputData[1].stages = stages;
562
563 return subgroups::allStages(context, FORMAT_R32_UINT, inputData, 2, checkVertexPipelineStages, stages);
564 }
565 }
566 } // namespace
567
createSubgroupsShuffleTests(deqp::Context & testCtx)568 deqp::TestCaseGroup *createSubgroupsShuffleTests(deqp::Context &testCtx)
569 {
570
571 de::MovePtr<deqp::TestCaseGroup> graphicGroup(
572 new deqp::TestCaseGroup(testCtx, "graphics", "Subgroup shuffle category tests: graphics"));
573 de::MovePtr<deqp::TestCaseGroup> computeGroup(
574 new deqp::TestCaseGroup(testCtx, "compute", "Subgroup shuffle category tests: compute"));
575 de::MovePtr<deqp::TestCaseGroup> framebufferGroup(
576 new deqp::TestCaseGroup(testCtx, "framebuffer", "Subgroup shuffle category tests: framebuffer"));
577
578 const Format formats[] = {
579 FORMAT_R32_SINT, FORMAT_R32G32_SINT, FORMAT_R32G32B32_SINT, FORMAT_R32G32B32A32_SINT,
580 FORMAT_R32_UINT, FORMAT_R32G32_UINT, FORMAT_R32G32B32_UINT, FORMAT_R32G32B32A32_UINT,
581 FORMAT_R32_SFLOAT, FORMAT_R32G32_SFLOAT, FORMAT_R32G32B32_SFLOAT, FORMAT_R32G32B32A32_SFLOAT,
582 FORMAT_R64_SFLOAT, FORMAT_R64G64_SFLOAT, FORMAT_R64G64B64_SFLOAT, FORMAT_R64G64B64A64_SFLOAT,
583 FORMAT_R32_BOOL, FORMAT_R32G32_BOOL, FORMAT_R32G32B32_BOOL, FORMAT_R32G32B32A32_BOOL,
584 };
585
586 const ShaderStageFlags stages[] = {
587 SHADER_STAGE_VERTEX_BIT,
588 SHADER_STAGE_TESS_EVALUATION_BIT,
589 SHADER_STAGE_TESS_CONTROL_BIT,
590 SHADER_STAGE_GEOMETRY_BIT,
591 };
592
593 for (int formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(formats); ++formatIndex)
594 {
595 const Format format = formats[formatIndex];
596
597 for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex)
598 {
599
600 const string name = de::toLower(getOpTypeName(opTypeIndex)) + "_" + subgroups::getFormatNameForGLSL(format);
601
602 {
603 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_ALL_GRAPHICS, format};
604 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(
605 graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
606 }
607
608 {
609 const CaseDefinition caseDef = {opTypeIndex, SHADER_STAGE_COMPUTE_BIT, format};
610 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(
611 computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef);
612 }
613
614 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
615 {
616 const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format};
617 SubgroupFactory<CaseDefinition>::addFunctionCaseWithPrograms(
618 framebufferGroup.get(), name + "_" + getShaderStageName(caseDef.shaderStage), "", supportedCheck,
619 initFrameBufferPrograms, noSSBOtest, caseDef);
620 }
621 }
622 }
623
624 de::MovePtr<deqp::TestCaseGroup> group(
625 new deqp::TestCaseGroup(testCtx, "shuffle", "Subgroup shuffle category tests"));
626
627 group->addChild(graphicGroup.release());
628 group->addChild(computeGroup.release());
629 group->addChild(framebufferGroup.release());
630
631 return group.release();
632 }
633
634 } // namespace subgroups
635 } // namespace glc
636