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 "vktSubgroupsBuiltinMaskVarTests.hpp"
26 #include "vktSubgroupsTestsUtils.hpp"
40 static bool checkVertexPipelineStages(std::vector<const void*> datas,
41 deUint32 width, deUint32)
43 const deUint32* data =
44 reinterpret_cast<const deUint32*>(datas[0]);
45 for (deUint32 x = 0; x < width; ++x)
47 deUint32 val = data[x];
58 static bool checkFragment(std::vector<const void*> datas,
59 deUint32 width, deUint32 height, deUint32)
61 const deUint32* data =
62 reinterpret_cast<const deUint32*>(datas[0]);
63 for (deUint32 x = 0; x < width; ++x)
65 for (deUint32 y = 0; y < height; ++y)
67 deUint32 val = data[(x * height + y)];
79 static bool checkCompute(std::vector<const void*> datas,
80 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
83 const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
85 for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX)
87 for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY)
89 for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ)
91 for (deUint32 lX = 0; lX < localSize[0]; ++lX)
93 for (deUint32 lY = 0; lY < localSize[1]; ++lY)
95 for (deUint32 lZ = 0; lZ < localSize[2];
98 const deUint32 globalInvocationX =
99 nX * localSize[0] + lX;
100 const deUint32 globalInvocationY =
101 nY * localSize[1] + lY;
102 const deUint32 globalInvocationZ =
103 nZ * localSize[2] + lZ;
105 const deUint32 globalSizeX =
106 numWorkgroups[0] * localSize[0];
107 const deUint32 globalSizeY =
108 numWorkgroups[1] * localSize[1];
110 const deUint32 offset =
117 if (0x1 != data[offset])
133 struct CaseDefinition
136 VkShaderStageFlags shaderStage;
141 std::string subgroupMask (const CaseDefinition& caseDef)
143 std::ostringstream bdy;
145 bdy << " uint tempResult = 0x1;\n"
146 << " uvec4 mask = subgroupBallot(true);\n"
147 << " const uvec4 var = " << caseDef.varName << ";\n"
148 << " for (uint i = 0; i < gl_SubgroupSize; i++)\n"
151 if ("gl_SubgroupEqMask" == caseDef.varName)
153 bdy << " if ((i == gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
155 << " tempResult = 0;\n"
158 else if ("gl_SubgroupGeMask" == caseDef.varName)
160 bdy << " if ((i >= gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
162 << " tempResult = 0;\n"
165 else if ("gl_SubgroupGtMask" == caseDef.varName)
167 bdy << " if ((i > gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
169 << " tempResult = 0;\n"
172 else if ("gl_SubgroupLeMask" == caseDef.varName)
174 bdy << " if ((i <= gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
176 << " tempResult = 0;\n"
179 else if ("gl_SubgroupLtMask" == caseDef.varName)
181 bdy << " if ((i < gl_SubgroupInvocationID) ^^ subgroupBallotBitExtract(var, i))\n"
183 << " tempResult = 0;\n"
191 void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
193 std::ostringstream vertexSrc;
194 std::ostringstream fragmentSrc;
195 std::ostringstream bdy;
196 bdy << subgroupMask(caseDef);
198 if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
200 vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
201 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
202 << "layout(location = 0) out float out_color;\n"
203 << "layout(location = 0) in highp vec4 in_position;\n"
205 << "void main (void)\n"
208 << " out_color = float(tempResult);\n"
209 << " gl_Position = in_position;\n"
210 << " gl_PointSize = 1.0f;\n"
212 programCollection.glslSources.add("vert") << glu::VertexSource(vertexSrc.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
214 fragmentSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
215 << "layout(location = 0) in highp float in_color;\n"
216 << "layout(location = 0) out uint out_color;\n"
219 << " out_color = uint(in_color);\n"
221 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSrc.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
225 DE_FATAL("Unsupported shader stage");
229 void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
231 std::ostringstream bdy;
232 bdy << subgroupMask(caseDef);
234 if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
236 std::ostringstream src;
238 src << "#version 450\n"
239 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
240 << "layout (local_size_x_id = 0, local_size_y_id = 1, "
241 "local_size_z_id = 2) in;\n"
242 << "layout(set = 0, binding = 0, std430) buffer Output\n"
244 << " uint result[];\n"
247 << "void main (void)\n"
249 << " uvec3 globalSize = gl_NumWorkGroups * gl_WorkGroupSize;\n"
250 << " highp uint offset = globalSize.x * ((globalSize.y * "
251 "gl_GlobalInvocationID.z) + gl_GlobalInvocationID.y) + "
252 "gl_GlobalInvocationID.x;\n"
254 << " result[offset] = tempResult;\n"
257 programCollection.glslSources.add("comp")
258 << glu::ComputeSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
260 else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
262 programCollection.glslSources.add("vert")
263 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
265 std::ostringstream frag;
267 frag << "#version 450\n"
268 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
269 << "layout(location = 0) out uint result;\n"
270 << "void main (void)\n"
273 << " result = tempResult;\n"
276 programCollection.glslSources.add("frag")
277 << glu::FragmentSource(frag.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
279 else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
281 std::ostringstream src;
283 src << "#version 450\n"
284 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
285 << "layout(set = 0, binding = 0, std430) buffer Output\n"
287 << " uint result[];\n"
290 << "void main (void)\n"
293 << " result[gl_VertexIndex] = tempResult;\n"
296 programCollection.glslSources.add("vert")
297 << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
299 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
301 programCollection.glslSources.add("vert")
302 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
304 std::ostringstream src;
306 src << "#version 450\n"
307 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
308 << "layout(points) in;\n"
309 << "layout(points, max_vertices = 1) out;\n"
310 << "layout(set = 0, binding = 0, std430) buffer Output\n"
312 << " uint result[];\n"
315 << "void main (void)\n"
318 << " result[gl_PrimitiveIDIn] = tempResult;\n"
321 programCollection.glslSources.add("geom")
322 << glu::GeometrySource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
324 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
326 programCollection.glslSources.add("vert")
327 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
329 programCollection.glslSources.add("tese")
330 << glu::TessellationEvaluationSource("#version 450\nlayout(isolines) in;\nvoid main (void) {}\n");
332 std::ostringstream src;
334 src << "#version 450\n"
335 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
336 << "layout(vertices=1) out;\n"
337 << "layout(set = 0, binding = 0, std430) buffer Output\n"
339 << " uint result[];\n"
342 << "void main (void)\n"
345 << " result[gl_PrimitiveID] = tempResult;\n"
348 programCollection.glslSources.add("tesc")
349 << glu::TessellationControlSource(src.str()) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
351 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
353 programCollection.glslSources.add("vert")
354 << glu::VertexSource(subgroups::getVertShaderForStage(caseDef.shaderStage)) << vk::ShaderBuildOptions(vk::SPIRV_VERSION_1_3, 0u);
356 programCollection.glslSources.add("tesc")
357 << glu::TessellationControlSource("#version 450\nlayout(vertices=1) out;\nvoid main (void) { for(uint i = 0; i < 4; i++) { gl_TessLevelOuter[i] = 1.0f; } }\n");
359 std::ostringstream src;
361 src << "#version 450\n"
362 << "#extension GL_KHR_shader_subgroup_ballot: enable\n"
363 << "layout(isolines) in;\n"
364 << "layout(set = 0, binding = 0, std430) buffer Output\n"
366 << " uint result[];\n"
369 << "void main (void)\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 (!areSubgroupOperationsSupportedForStage(
390 context, caseDef.shaderStage))
392 if (areSubgroupOperationsRequiredForStage(caseDef.shaderStage))
394 return tcu::TestStatus::fail(
395 "Shader stage " + getShaderStageName(caseDef.shaderStage) +
396 " is required to support subgroup operations!");
400 TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage");
404 if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_BALLOT_BIT))
406 TCU_THROW(NotSupportedError, "Device does not support subgroup ballot operations");
409 //Tests which don't use the SSBO
410 if (caseDef.noSSBO && VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
412 return makeVertexFrameBufferTest(context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
415 if ((VK_SHADER_STAGE_FRAGMENT_BIT != caseDef.shaderStage) &&
416 (VK_SHADER_STAGE_COMPUTE_BIT != caseDef.shaderStage))
418 if (!subgroups::isVertexSSBOSupportedForDevice(context))
420 TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes");
424 if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage)
426 return makeComputeTest(
427 context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkCompute);
429 else if (VK_SHADER_STAGE_FRAGMENT_BIT == caseDef.shaderStage)
431 return makeFragmentTest(
432 context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkFragment);
434 else if (VK_SHADER_STAGE_VERTEX_BIT == caseDef.shaderStage)
436 return makeVertexTest(
437 context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
439 else if (VK_SHADER_STAGE_GEOMETRY_BIT == caseDef.shaderStage)
441 return makeGeometryTest(
442 context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
444 else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage)
446 return makeTessellationControlTest(
447 context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
449 else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage)
451 return makeTessellationEvaluationTest(
452 context, VK_FORMAT_R32_UINT, DE_NULL, 0, checkVertexPipelineStages);
456 TCU_THROW(InternalError, "Unhandled shader stage");
460 tcu::TestCaseGroup* createSubgroupsBuiltinMaskVarTests(tcu::TestContext& testCtx)
462 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(
463 testCtx, "builtin_mask_var", "Subgroup builtin mask variable tests"));
465 const char* const all_stages_vars[] =
474 const VkShaderStageFlags stages[] =
476 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
477 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
478 VK_SHADER_STAGE_GEOMETRY_BIT,
479 VK_SHADER_STAGE_VERTEX_BIT,
480 VK_SHADER_STAGE_FRAGMENT_BIT,
481 VK_SHADER_STAGE_COMPUTE_BIT,
484 for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex)
486 const VkShaderStageFlags stage = stages[stageIndex];
488 for (int a = 0; a < DE_LENGTH_OF_ARRAY(all_stages_vars); ++a)
490 const std::string var = all_stages_vars[a];
492 CaseDefinition caseDef = {"gl_" + var, stage, false};
494 addFunctionCaseWithPrograms(group.get(),
495 de::toLower(var) + "_" +
496 getShaderStageName(stage), "",
497 initPrograms, test, caseDef);
499 if (VK_SHADER_STAGE_VERTEX_BIT == stage)
501 caseDef.noSSBO = true;
502 addFunctionCaseWithPrograms(group.get(),
503 de::toLower(var) + "_" +
504 getShaderStageName(stage)+"_framebuffer", "",
505 initFrameBufferPrograms, test, caseDef);
510 return group.release();