1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2017 Codeplay Software Ltd.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Subgroups Tests
23 */ /*--------------------------------------------------------------------*/
25 #include "vktSubgroupsBallotTests.hpp"
26 #include "vktSubgroupsTestsUtils.hpp"
38 static bool checkVertexPipelineStages(std::vector<const void*> datas,
39 deUint32 width, deUint32)
41 const deUint32* data =
42 reinterpret_cast<const deUint32*>(datas[0]);
43 for (deUint32 x = 0; x < width; ++x)
45 deUint32 val = data[x];
56 static bool checkFragment(std::vector<const void*> datas,
57 deUint32 width, deUint32 height, deUint32)
59 const deUint32* data =
60 reinterpret_cast<const deUint32*>(datas[0]);
61 for (deUint32 x = 0; x < width; ++x)
63 for (deUint32 y = 0; y < height; ++y)
65 deUint32 val = data[x * height + y];
77 static bool checkCompute(std::vector<const void*> datas,
78 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
81 const deUint32* data =
82 reinterpret_cast<const deUint32*>(datas[0]);
84 for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
86 for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
88 for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
90 for (deUint32 lX = 0; lX < localSize[0]; ++lX)
92 for (deUint32 lY = 0; lY < localSize[1]; ++lY)
94 for (deUint32 lZ = 0; lZ < localSize[2];
97 const deUint32 globalInvocationX =
98 nX * localSize[0] + lX;
99 const deUint32 globalInvocationY =
100 nY * localSize[1] + lY;
101 const deUint32 globalInvocationZ =
102 nZ * localSize[2] + lZ;
104 const deUint32 globalSizeX =
105 numWorkgroups[0] * localSize[0];
106 const deUint32 globalSizeY =
107 numWorkgroups[1] * localSize[1];
109 const deUint32 offset =
116 if (0x7 != data[offset])
130 struct CaseDefinition
132 VkShaderStageFlags shaderStage;
136 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
138 std::ostringstream fragmentSrc;
140 if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
142 std::ostringstream vertexSrc;
144 vertexSrc << "#version 450\n"
145 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
146 << "layout(location = 0) in highp vec4 in_position;\n"
147 << "layout(location = 0) out float out_color;\n"
148 << "layout(set = 0, binding = 0) uniform Buffer1\n"
150 << " uint data[" << subgroups::maxSupportedSubgroupSize() << "];\n"
153 << "void main (void)\n"
155 << " uint tempResult = 0;\n"
156 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
157 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
158 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
159 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
160 << " out_color = float(tempResult);\n"
161 << " gl_Position = in_position;\n"
162 << " gl_PointSize = 1.0f;\n"
165 programCollection.glslSources.add("vert") << glu::VertexSource(vertexSrc.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
167 fragmentSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
168 << "layout(location = 0) in float in_color;\n"
169 << "layout(location = 0) out uint out_color;\n"
172 << " out_color = uint(in_color);\n"
174 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSrc.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
178 DE_FATAL("Unsupported shader stage");
182 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
184 if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
186 std::ostringstream src;
188 src << "#version 450\n"
189 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
190 << "layout (local_size_x_id = 0, local_size_y_id = 1, "
191 "local_size_z_id = 2) in;\n"
192 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
194 << " uint result[];\n"
196 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
201 << subgroups::getSharedMemoryBallotHelper()
202 << "void main (void)\n"
204 << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
205 << " highp uint offset = globalSize.x * ((globalSize.y * "
206 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
207 "gl_GlobalInvocationID.x;\n"
208 << " uint tempResult = 0;\n"
209 << " tempResult |= sharedMemoryBallot(true) == subgroupBallot(true) ? 0x1 : 0;\n"
210 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
211 << " tempResult |= sharedMemoryBallot(bData) == subgroupBallot(bData) ? 0x2 : 0;\n"
212 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
213 << " result[offset] = tempResult;\n"
216 programCollection.glslSources.add("comp")
217 << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
219 else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
221 programCollection.glslSources.add("vert")
222 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
224 std::ostringstream frag;
226 frag << "#version 450\n"
227 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
228 << "layout(location = 0) out uint result;\n"
229 << "layout(set = 0, binding = 0, std430) readonly buffer Buffer1\n"
233 << "void main (void)\n"
235 << " uint tempResult = 0;\n"
236 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
237 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
238 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
239 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
240 << " result = tempResult;\n"
243 programCollection.glslSources.add("frag")
244 << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
246 else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
248 std::ostringstream src;
250 src << "#version 450\n"
251 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
252 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
254 << " uint result[];\n"
256 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
261 << "void main (void)\n"
263 << " uint tempResult = 0;\n"
264 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
265 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
266 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
267 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
268 << " result[gl_VertexIndex] = tempResult;\n"
269 << " gl_PointSize = 1.0f;\n"
272 programCollection.glslSources.add("vert")
273 << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
275 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
277 programCollection.glslSources.add("vert")
278 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
280 std::ostringstream src;
282 src << "#version 450\n"
283 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
284 << "layout(points) in;\n"
285 << "layout(points, max_vertices = 1) out;\n"
286 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
288 << " uint result[];\n"
290 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
295 << "void main (void)\n"
297 << " uint tempResult = 0;\n"
298 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
299 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
300 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
301 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
302 << " result[gl_PrimitiveIDIn] = tempResult;\n"
305 programCollection.glslSources.add("geom")
306 << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
308 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
310 programCollection.glslSources.add("vert")
311 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
313 programCollection.glslSources.add("tese")
314 << glu::TessellationEvaluationSource("#version 450\nlayout(isolines) in;\nvoid main (void) {}\n");
316 std::ostringstream src;
318 src << "#version 450\n"
319 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
320 << "layout(vertices=1) out;\n"
321 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
323 << " uint result[];\n"
325 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
330 << "void main (void)\n"
332 << " uint tempResult = 0;\n"
333 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
334 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
335 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
336 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
337 << " result[gl_PrimitiveID] = tempResult;\n"
340 programCollection.glslSources.add("tesc")
341 << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
343 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
345 programCollection.glslSources.add("vert")
346 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
348 programCollection.glslSources.add("tesc")
349 << glu::TessellationControlSource("#version 450\nlayout(vertices=1) out;\nvoid main (void) { for(uint i = 0; i < 4; i++) { gl_TessLevelOuter[i] = 1.0f; } }\n");
351 std::ostringstream src;
353 src << "#version 450\n"
354 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
355 << "layout(isolines) in;\n"
356 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
358 << " uint result[];\n"
360 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
365 << "void main (void)\n"
367 << " uint tempResult = 0;\n"
368 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
369 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
370 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
371 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
372 << " result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
375 programCollection.glslSources.add("tese")
376 << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
380 DE_FATAL("Unsupported shader stage");
384 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
386 if (!subgroups::isSubgroupSupported(context))
387 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
389 if (!subgroups::areSubgroupOperationsSupportedForStage(
390 context, caseDef.shaderStage))
392 if (subgroups::areSubgroupOperationsRequiredForStage(
393 caseDef.shaderStage))
395 return tcu::TestStatus::fail(
397 subgroups::getShaderStageName(caseDef.shaderStage) +
398 " is required to support subgroup operations!");
402 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
406 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
408 TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
411 //Tests which don't use the SSBO
412 if (caseDef.noSSBO && VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
414 subgroups::SSBOData inputData[1];
415 inputData[0].format = VK_FORMAT_R32_UINT;
416 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
417 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
419 return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages);
422 if ((VK_SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage) &&
423 (VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage))
425 if (!subgroups::isVertexSSBOSupportedForDevice(context))
427 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
431 if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
433 subgroups::SSBOData inputData[1];
434 inputData[0].format = VK_FORMAT_R32_UINT;
435 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
436 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
438 return subgroups::makeFragmentTest(context, VK_FORMAT_R32_UINT,
439 inputData, 1, checkFragment);
441 else if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
443 subgroups::SSBOData inputData[1];
444 inputData[0].format = VK_FORMAT_R32_UINT;
445 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
446 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
448 return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT,
449 inputData, 1, checkCompute);
451 else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
453 subgroups::SSBOData inputData[1];
454 inputData[0].format = VK_FORMAT_R32_UINT;
455 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
456 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
458 return subgroups::makeVertexTest(context, VK_FORMAT_R32_UINT,
459 inputData, 1, checkVertexPipelineStages);
461 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
463 subgroups::SSBOData inputData[1];
464 inputData[0].format = VK_FORMAT_R32_UINT;
465 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
466 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
468 return subgroups::makeGeometryTest(context, VK_FORMAT_R32_UINT,
469 inputData, 1, checkVertexPipelineStages);
471 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
473 subgroups::SSBOData inputData[1];
474 inputData[0].format = VK_FORMAT_R32_UINT;
475 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
476 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
478 return subgroups::makeTessellationControlTest(context, VK_FORMAT_R32_UINT,
479 inputData, 1, checkVertexPipelineStages);
481 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
483 subgroups::SSBOData inputData[1];
484 inputData[0].format = VK_FORMAT_R32_UINT;
485 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
486 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
488 return subgroups::makeTessellationEvaluationTest(context, VK_FORMAT_R32_UINT,
489 inputData, 1, checkVertexPipelineStages);
493 TCU_THROW(InternalError, "Unhandled shader stage");
502 tcu::TestCaseGroup* createSubgroupsBallotTests(tcu::TestContext& testCtx)
504 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
505 testCtx, "ballot", "Subgroup ballot category tests"));
507 const VkShaderStageFlags stages[] =
509 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
510 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
511 VK_SHADER_STAGE_GEOMETRY_BIT,
512 VK_SHADER_STAGE_VERTEX_BIT,
513 VK_SHADER_STAGE_FRAGMENT_BIT,
514 VK_SHADER_STAGE_COMPUTE_BIT
517 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
519 const VkShaderStageFlags stage = stages[stageIndex];
521 CaseDefinition caseDef = {stage, false};
523 std::ostringstream name;
525 name << getShaderStageName(stage);
527 addFunctionCaseWithPrograms(group.get(), name.str(),
528 "", initPrograms, test, caseDef);
530 if (VK_SHADER_STAGE_VERTEX_BIT == stage )
532 caseDef.noSSBO = true;
533 addFunctionCaseWithPrograms(group.get(), name.str()+"_framebuffer", "",
534 initFrameBufferPrograms, test, caseDef);
538 return group.release();