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"
271 programCollection.glslSources.add("vert")
272 << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
274 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
276 programCollection.glslSources.add("vert")
277 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
279 std::ostringstream src;
281 src << "#version 450\n"
282 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
283 << "layout(points) in;\n"
284 << "layout(points, max_vertices = 1) out;\n"
285 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
287 << " uint result[];\n"
289 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
294 << "void main (void)\n"
296 << " uint tempResult = 0;\n"
297 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
298 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
299 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
300 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
301 << " result[gl_PrimitiveIDIn] = tempResult;\n"
304 programCollection.glslSources.add("geom")
305 << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
307 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
309 programCollection.glslSources.add("vert")
310 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
312 programCollection.glslSources.add("tese")
313 << glu::TessellationEvaluationSource("#version 450\nlayout(isolines) in;\nvoid main (void) {}\n");
315 std::ostringstream src;
317 src << "#version 450\n"
318 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
319 << "layout(vertices=1) out;\n"
320 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
322 << " uint result[];\n"
324 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
329 << "void main (void)\n"
331 << " uint tempResult = 0;\n"
332 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
333 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
334 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
335 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
336 << " result[gl_PrimitiveID] = tempResult;\n"
339 programCollection.glslSources.add("tesc")
340 << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
342 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
344 programCollection.glslSources.add("vert")
345 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
347 programCollection.glslSources.add("tesc")
348 << glu::TessellationControlSource("#version 450\nlayout(vertices=1) out;\nvoid main (void) { for(uint i = 0; i < 4; i++) { gl_TessLevelOuter[i] = 1.0f; } }\n");
350 std::ostringstream src;
352 src << "#version 450\n"
353 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
354 << "layout(isolines) in;\n"
355 << "layout(set = 0, binding = 0, std430) buffer Buffer1\n"
357 << " uint result[];\n"
359 << "layout(set = 0, binding = 1, std430) buffer Buffer2\n"
364 << "void main (void)\n"
366 << " uint tempResult = 0;\n"
367 << " tempResult |= !bool(uvec4(0) == subgroupBallot(true)) ? 0x1 : 0;\n"
368 << " bool bData = data[gl_SubgroupInvocationID] != 0;\n"
369 << " tempResult |= !bool(uvec4(0) == subgroupBallot(bData)) ? 0x2 : 0;\n"
370 << " tempResult |= uvec4(0) == subgroupBallot(false) ? 0x4 : 0;\n"
371 << " result[gl_PrimitiveID * 2 + uint(gl_TessCoord.x + 0.5)] = tempResult;\n"
374 programCollection.glslSources.add("tese")
375 << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
379 DE_FATAL("Unsupported shader stage");
383 tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
385 if (!subgroups::isSubgroupSupported(context))
386 TCU_THROW(NotSupportedError, "Subgroup operations are not supported");
388 if (!subgroups::areSubgroupOperationsSupportedForStage(
389 context, caseDef.shaderStage))
391 if (subgroups::areSubgroupOperationsRequiredForStage(
392 caseDef.shaderStage))
394 return tcu::TestStatus::fail(
396 subgroups::getShaderStageName(caseDef.shaderStage) +
397 " is required to support subgroup operations!");
401 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
405 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
407 TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
410 //Tests which don't use the SSBO
411 if (caseDef.noSSBO && VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
413 subgroups::SSBOData inputData[1];
414 inputData[0].format = VK_FORMAT_R32_UINT;
415 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
416 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
418 return subgroups::makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, inputData, 1, checkVertexPipelineStages);
421 if ((VK_SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage) &&
422 (VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage))
424 if (!subgroups::isVertexSSBOSupportedForDevice(context))
426 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
430 if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
432 subgroups::SSBOData inputData[1];
433 inputData[0].format = VK_FORMAT_R32_UINT;
434 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
435 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
437 return subgroups::makeFragmentTest(context, VK_FORMAT_R32_UINT,
438 inputData, 1, checkFragment);
440 else if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
442 subgroups::SSBOData inputData[1];
443 inputData[0].format = VK_FORMAT_R32_UINT;
444 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
445 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
447 return subgroups::makeComputeTest(context, VK_FORMAT_R32_UINT,
448 inputData, 1, checkCompute);
450 else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
452 subgroups::SSBOData inputData[1];
453 inputData[0].format = VK_FORMAT_R32_UINT;
454 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
455 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
457 return subgroups::makeVertexTest(context, VK_FORMAT_R32_UINT,
458 inputData, 1, checkVertexPipelineStages);
460 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
462 subgroups::SSBOData inputData[1];
463 inputData[0].format = VK_FORMAT_R32_UINT;
464 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
465 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
467 return subgroups::makeGeometryTest(context, VK_FORMAT_R32_UINT,
468 inputData, 1, checkVertexPipelineStages);
470 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
472 subgroups::SSBOData inputData[1];
473 inputData[0].format = VK_FORMAT_R32_UINT;
474 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
475 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
477 return subgroups::makeTessellationControlTest(context, VK_FORMAT_R32_UINT,
478 inputData, 1, checkVertexPipelineStages);
480 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
482 subgroups::SSBOData inputData[1];
483 inputData[0].format = VK_FORMAT_R32_UINT;
484 inputData[0].numElements = subgroups::maxSupportedSubgroupSize();
485 inputData[0].initializeType = subgroups::SSBOData::InitializeNonZero;
487 return subgroups::makeTessellationEvaluationTest(context, VK_FORMAT_R32_UINT,
488 inputData, 1, checkVertexPipelineStages);
492 TCU_THROW(InternalError, "Unhandled shader stage");
501 tcu::TestCaseGroup* createSubgroupsBallotTests(tcu::TestContext& testCtx)
503 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
504 testCtx, "ballot", "Subgroup ballot category tests"));
506 const VkShaderStageFlags stages[] =
508 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
509 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
510 VK_SHADER_STAGE_GEOMETRY_BIT,
511 VK_SHADER_STAGE_VERTEX_BIT,
512 VK_SHADER_STAGE_FRAGMENT_BIT,
513 VK_SHADER_STAGE_COMPUTE_BIT
516 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
518 const VkShaderStageFlags stage = stages[stageIndex];
520 CaseDefinition caseDef = {stage, false};
522 std::ostringstream name;
524 name << getShaderStageName(stage);
526 addFunctionCaseWithPrograms(group.get(), name.str(),
527 "", initPrograms, test, caseDef);
529 if (VK_SHADER_STAGE_VERTEX_BIT == stage )
531 caseDef.noSSBO = true;
532 addFunctionCaseWithPrograms(group.get(), name.str()+"_framebuffer", "",
533 initFrameBufferPrograms, test, caseDef);
537 return group.release();