1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 LunarG, Inc.
6 * Copyright (c) 2023 Nintendo
7 *
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
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
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.
19 *
20 *//*!
21 * \file
22 * \brief Shader Object Create Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktShaderObjectCreateTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vktCustomInstancesDevices.hpp"
31 #include "tcuCommandLine.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkRefUtil.hpp"
34 #include "deRandom.hpp"
35 #include "vktShaderObjectCreateUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37
38 namespace vkt
39 {
40 namespace ShaderObject
41 {
42
43 namespace
44 {
45
46 class ShaderObjectCreateInstance : public vkt::TestInstance
47 {
48 public:
ShaderObjectCreateInstance(Context & context,const bool useMeshShaders)49 ShaderObjectCreateInstance (Context& context, const bool useMeshShaders)
50 : vkt::TestInstance (context)
51 , m_useMeshShaders (useMeshShaders)
52 {}
~ShaderObjectCreateInstance(void)53 virtual ~ShaderObjectCreateInstance (void) {}
54
55 tcu::TestStatus iterate (void) override;
56
57 private:
58 const bool m_useMeshShaders;
59 };
60
iterate(void)61 tcu::TestStatus ShaderObjectCreateInstance::iterate (void)
62 {
63 const vk::VkInstance instance = m_context.getInstance();
64 const vk::InstanceDriver instanceDriver (m_context.getPlatformInterface(), instance);
65 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
66 const vk::VkDevice device = m_context.getDevice();
67 tcu::TestLog& log = m_context.getTestContext().getLog();
68 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
69 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
70
71 const auto& binaries = m_context.getBinaryCollection();
72 const auto& vert = binaries.get("vert");
73 const auto& tesc = binaries.get("tesc");
74 const auto& tese = binaries.get("tese");
75 const auto& geom = binaries.get("geom");
76 const auto& frag = binaries.get("frag");
77 const auto& comp = binaries.get("comp");
78
79 const vk::VkDescriptorSetLayoutBinding layoutBinding =
80 {
81 0u, // deUint32 binding;
82 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
83 1u, // deUint32 arraySize;
84 vk::VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags;
85 DE_NULL // const VkSampler* pImmutableSamplers;
86 };
87
88 const vk::VkDescriptorSetLayoutCreateInfo descriptorLayoutParams =
89 {
90 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
91 DE_NULL, // const void* pNext;
92 (vk::VkDescriptorSetLayoutCreateFlags)0, // VkDescriptorSetLayoutCreateFlags flags;
93 1u, // deUint32 count;
94 &layoutBinding // const VkDescriptorSetLayoutBinding pBinding;
95 };
96
97 const auto descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &descriptorLayoutParams);
98
99 // Todo: remove const_cast if spec is updated
100 vk::VkDescriptorSetLayout* setLayout = const_cast<vk::VkDescriptorSetLayout*>(&descriptorSetLayout.get());
101
102 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos =
103 {
104 {
105 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
106 DE_NULL, // const void* pNext;
107 0u, // VkShaderCreateFlagsEXT flags;
108 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
109 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_VERTEX_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage;
110 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
111 vert.getSize(), // size_t codeSize;
112 vert.getBinary(), // const void* pCode;
113 "main", // const char* pName;
114 0u, // uint32_t setLayoutCount;
115 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
116 0u, // uint32_t pushConstantRangeCount;
117 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
118 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
119 },
120 {
121 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
122 DE_NULL, // const void* pNext;
123 0u, // VkShaderCreateFlagsEXT flags;
124 vk::VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
125 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_FRAGMENT_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage;
126 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
127 frag.getSize(), // size_t codeSize;
128 frag.getBinary(), // const void* pCode;
129 "main", // const char* pName;
130 0u, // uint32_t setLayoutCount;
131 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
132 0u, // uint32_t pushConstantRangeCount;
133 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
134 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
135 },
136 {
137 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
138 DE_NULL, // const void* pNext;
139 0u, // VkShaderCreateFlagsEXT flags;
140 vk::VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
141 0u, // VkShaderStageFlags nextStage;
142 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
143 comp.getSize(), // size_t codeSize;
144 comp.getBinary(), // const void* pCode;
145 "main", // const char* pName;
146 1u, // uint32_t setLayoutCount;
147 setLayout, // VkDescriptorSetLayout* pSetLayouts;
148 0u, // uint32_t pushConstantRangeCount;
149 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
150 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
151 },
152 };
153
154 if (m_context.getDeviceFeatures().tessellationShader)
155 {
156 shaderCreateInfos.push_back(
157 {
158 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
159 DE_NULL, // const void* pNext;
160 0u, // VkShaderCreateFlagsEXT flags;
161 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage;
162 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage;
163 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
164 tesc.getSize(), // size_t codeSize;
165 tesc.getBinary(), // const void* pCode;
166 "main", // const char* pName;
167 0u, // uint32_t setLayoutCount;
168 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
169 0u, // uint32_t pushConstantRangeCount;
170 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
171 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
172 }
173 );
174 shaderCreateInfos.push_back(
175 {
176 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
177 DE_NULL, // const void* pNext;
178 0u, // VkShaderCreateFlagsEXT flags;
179 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,// VkShaderStageFlagBits stage;
180 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage;
181 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
182 tese.getSize(), // size_t codeSize;
183 tese.getBinary(), // const void* pCode;
184 "main", // const char* pName;
185 0u, // uint32_t setLayoutCount;
186 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
187 0u, // uint32_t pushConstantRangeCount;
188 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
189 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
190 }
191 );
192 }
193
194 if (m_context.getDeviceFeatures().geometryShader)
195 {
196 shaderCreateInfos.push_back(
197 {
198 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
199 DE_NULL, // const void* pNext;
200 0u, // VkShaderCreateFlagsEXT flags;
201 vk::VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage;
202 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_GEOMETRY_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage;
203 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
204 geom.getSize(), // size_t codeSize;
205 geom.getBinary(), // const void* pCode;
206 "main", // const char* pName;
207 0u, // uint32_t setLayoutCount;
208 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
209 0u, // uint32_t pushConstantRangeCount;
210 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
211 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
212 }
213 );
214 }
215
216 if (m_useMeshShaders)
217 {
218 const auto& mesh = binaries.get("mesh");
219 const auto& task = binaries.get("task");
220 if (m_context.getMeshShaderFeaturesEXT().meshShader)
221 {
222 shaderCreateInfos.push_back(
223 {
224 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
225 DE_NULL, // const void* pNext;
226 0u, // VkShaderCreateFlagsEXT flags;
227 vk::VK_SHADER_STAGE_MESH_BIT_EXT, // VkShaderStageFlagBits stage;
228 0u, // VkShaderStageFlags nextStage;
229 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
230 mesh.getSize(), // size_t codeSize;
231 mesh.getBinary(), // const void* pCode;
232 "main", // const char* pName;
233 0u, // uint32_t setLayoutCount;
234 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
235 0u, // uint32_t pushConstantRangeCount;
236 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
237 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
238 }
239 );
240 }
241
242 if (m_context.getMeshShaderFeaturesEXT().taskShader)
243 {
244 shaderCreateInfos.push_back(
245 {
246 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
247 DE_NULL, // const void* pNext;
248 0u, // VkShaderCreateFlagsEXT flags;
249 vk::VK_SHADER_STAGE_TASK_BIT_EXT, // VkShaderStageFlagBits stage;
250 0u, // VkShaderStageFlags nextStage;
251 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
252 task.getSize(), // size_t codeSize;
253 task.getBinary(), // const void* pCode;
254 "main", // const char* pName;
255 0u, // uint32_t setLayoutCount;
256 DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
257 0u, // uint32_t pushConstantRangeCount;
258 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
259 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
260 }
261 );
262 }
263 }
264
265 std::vector<vk::VkShaderEXT> shadersSeparate (shaderCreateInfos.size());
266 std::vector<vk::VkShaderEXT> shadersTogether (shaderCreateInfos.size());
267 for (deUint32 i = 0; i < (deUint32)shaderCreateInfos.size(); ++i)
268 {
269 vk.createShadersEXT(device, 1, &shaderCreateInfos[i], DE_NULL, &shadersSeparate[i]);
270 }
271 vk.createShadersEXT(device, (deUint32)shaderCreateInfos.size(), &shaderCreateInfos[0], DE_NULL, &shadersTogether[0]);
272
273 bool match = true;
274 for (deUint32 i = 0; i < (deUint32)shaderCreateInfos.size(); ++i)
275 {
276 size_t dataSizeSeparate = 0;
277 size_t dataSizeTogether = 0;
278 vk.getShaderBinaryDataEXT(device, shadersSeparate[i], &dataSizeSeparate, DE_NULL);
279 vk.getShaderBinaryDataEXT(device, shadersTogether[i], &dataSizeTogether, DE_NULL);
280 if (dataSizeSeparate != dataSizeTogether)
281 {
282 log << tcu::TestLog::Message << "Data size of shader created separately is " << dataSizeSeparate << ", but data size of shader created in the same call with others is " << dataSizeTogether << tcu::TestLog::EndMessage;
283 match = false;
284 break;
285 }
286 std::vector<deUint8> dataSeparate(dataSizeSeparate);
287 std::vector<deUint8> dataTogether(dataSizeTogether);
288 vk.getShaderBinaryDataEXT(device, shadersSeparate[i], &dataSizeSeparate, &dataSeparate[0]);
289 vk.getShaderBinaryDataEXT(device, shadersTogether[i], &dataSizeTogether, &dataTogether[0]);
290 for (deUint32 j = 0; j < dataSizeSeparate; ++j)
291 {
292 if (dataSeparate[j] != dataTogether[j])
293 {
294 log << tcu::TestLog::Message << "Data of shader created separately and data of shader created in the same call with others does not match at index " << j << tcu::TestLog::EndMessage;
295 match = false;
296 break;
297 }
298 }
299 if (!match)
300 break;
301 }
302
303 for (const auto& shader : shadersSeparate)
304 vk.destroyShaderEXT(device, shader, DE_NULL);
305 for (const auto& shader : shadersTogether)
306 vk.destroyShaderEXT(device, shader, DE_NULL);
307
308 if (!match)
309 return tcu::TestStatus::fail("Fail");
310
311 return tcu::TestStatus::pass("Pass");
312 }
313
314 class ShaderObjectCreateCase : public vkt::TestCase
315 {
316 public:
ShaderObjectCreateCase(tcu::TestContext & testCtx,const std::string & name,const bool useMeshShaders)317 ShaderObjectCreateCase (tcu::TestContext& testCtx, const std::string& name, const bool useMeshShaders)
318 : vkt::TestCase (testCtx, name)
319 , m_useMeshShaders (useMeshShaders)
320 {}
~ShaderObjectCreateCase(void)321 virtual ~ShaderObjectCreateCase (void) {}
322
323 void checkSupport (vkt::Context& context) const override;
324 virtual void initPrograms (vk::SourceCollections& programCollection) const override;
createInstance(Context & context) const325 TestInstance* createInstance (Context& context) const override { return new ShaderObjectCreateInstance(context, m_useMeshShaders); }
326 private:
327 bool m_useMeshShaders;
328 };
329
checkSupport(Context & context) const330 void ShaderObjectCreateCase::checkSupport(Context& context) const
331 {
332 context.requireDeviceFunctionality("VK_EXT_shader_object");
333 }
334
initPrograms(vk::SourceCollections & programCollection) const335 void ShaderObjectCreateCase::initPrograms(vk::SourceCollections& programCollection) const
336 {
337 std::stringstream vert;
338 std::stringstream geom;
339 std::stringstream tesc;
340 std::stringstream tese;
341 std::stringstream frag;
342 std::stringstream comp;
343 std::stringstream mesh;
344 std::stringstream task;
345
346 vert
347 << "#version 450\n"
348 << "layout (location=0) in vec2 inPos;\n"
349 << "void main() {\n"
350 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
351 << " gl_Position = vec4(pos, 0.0f, 1.0f);\n"
352 << "}\n";
353
354 tesc
355 << "#version 450\n"
356 << "\n"
357 << "layout(vertices = 3) out;\n"
358 << "\n"
359 << "void main (void)\n"
360 << "{\n"
361 << " gl_TessLevelInner[0] = 5.0;\n"
362 << " gl_TessLevelInner[1] = 5.0;\n"
363 << "\n"
364 << " gl_TessLevelOuter[0] = 5.0;\n"
365 << " gl_TessLevelOuter[1] = 5.0;\n"
366 << " gl_TessLevelOuter[2] = 5.0;\n"
367 << " gl_TessLevelOuter[3] = 5.0;\n"
368 << "}\n";
369
370 tese
371 << "#version 450\n"
372 << "\n"
373 << "layout(quads) in;\n"
374 << "\n"
375 << "void main (void)\n"
376 << "{\n"
377 << " highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
378 << " highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
379 << " gl_Position = vec4(x, y, 0.0, 1.0);\n"
380 << "}\n";
381
382 geom
383 << "#version 450\n"
384 << "layout(points) in;\n"
385 << "layout(points, max_vertices = 1) out;\n"
386 << "\n"
387 << "void main(void)\n"
388 << "{\n"
389 << " gl_Position = gl_in[0].gl_Position;\n"
390 << " EmitVertex();\n"
391 << " EndPrimitive();\n"
392 << "}\n";
393
394 frag
395 << "#version 450\n"
396 << "layout (location=0) out vec4 outColor;\n"
397 << "void main() {\n"
398 << " outColor = vec4(1.0f);\n"
399 << "}\n";
400
401 comp
402 << "#version 450\n"
403 << "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n"
404 << "layout(binding = 0) buffer Output {\n"
405 << " uint values[16];\n"
406 << "} buffer_out;\n\n"
407 << "void main() {\n"
408 << " buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
409 << "}\n";
410
411 mesh
412 << "#version 460\n"
413 << "#extension GL_EXT_mesh_shader : require\n"
414 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
415 << "layout(max_vertices = 3) out;\n"
416 << "layout(max_primitives = 1) out;\n"
417 << "layout(triangles) out;\n"
418 << "void main() {\n"
419 << " SetMeshOutputsEXT(3,1);\n"
420 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0, 1);\n"
421 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 1.0, -1.0, 0, 1);\n"
422 << " gl_MeshVerticesEXT[2].gl_Position = vec4( 0.0, 1.0, 0, 1);\n"
423 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0,1,2);\n"
424 << "}\n";
425
426 task
427 << "#version 450\n"
428 << "#extension GL_EXT_mesh_shader : enable\n"
429 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
430 << "struct TaskData {\n"
431 << " int t;\n"
432 << "};\n"
433 << "taskPayloadSharedEXT TaskData td;\n"
434 << "void main ()\n"
435 << "{\n"
436 << " td.t = 1;\n"
437 << " EmitMeshTasksEXT(1u, 1u, 1u);\n"
438 << "}\n";
439
440 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
441 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
442 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
443 programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
444 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
445 programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
446 if (m_useMeshShaders)
447 {
448 programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
449 programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
450 }
451 }
452
453 class ShaderObjectStageInstance : public vkt::TestInstance
454 {
455 public:
ShaderObjectStageInstance(Context & context,const vk::VkShaderStageFlagBits stage,const bool fail,const bool useMeshShaders)456 ShaderObjectStageInstance (Context& context, const vk::VkShaderStageFlagBits stage, const bool fail, const bool useMeshShaders)
457 : vkt::TestInstance (context)
458 , m_stage (stage)
459 , m_fail (fail)
460 , m_useMeshShaders (useMeshShaders)
461 {}
462
~ShaderObjectStageInstance(void)463 virtual ~ShaderObjectStageInstance (void) {}
464
465 tcu::TestStatus iterate (void) override;
466 private:
467 const vk::VkShaderStageFlagBits m_stage;
468 const bool m_fail;
469 const bool m_useMeshShaders;
470 };
471
iterate(void)472 tcu::TestStatus ShaderObjectStageInstance::iterate (void)
473 {
474 const vk::VkInstance instance = m_context.getInstance();
475 const vk::InstanceDriver instanceDriver (m_context.getPlatformInterface(), instance);
476 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
477 const vk::VkDevice device = m_context.getDevice();
478 tcu::TestLog& log = m_context.getTestContext().getLog();
479 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
480 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
481
482 const auto& binaries = m_context.getBinaryCollection();
483
484 de::Random random (102030);
485 std::vector<vk::VkShaderStageFlagBits> stages =
486 {
487 vk::VK_SHADER_STAGE_VERTEX_BIT,
488 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
489 vk::VK_SHADER_STAGE_COMPUTE_BIT,
490 };
491 if (m_context.getDeviceFeatures().tessellationShader)
492 {
493 stages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
494 stages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
495 }
496 if (m_context.getDeviceFeatures().geometryShader)
497 {
498 stages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
499 }
500 if (m_useMeshShaders)
501 {
502 if (m_context.getMeshShaderFeaturesEXT().meshShader)
503 stages.push_back(vk::VK_SHADER_STAGE_MESH_BIT_EXT);
504 if (m_context.getMeshShaderFeaturesEXT().taskShader)
505 stages.push_back(vk::VK_SHADER_STAGE_TASK_BIT_EXT);
506 }
507
508 const deUint32 count = m_stage == vk::VK_SHADER_STAGE_ALL ? 50 : 10;
509
510 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
511 vk::DescriptorSetLayoutBuilder()
512 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
513 .build(vk, device));
514
515
516 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos;
517
518 for (deUint32 i = 0; i < count; ++i)
519 {
520 vk::VkShaderStageFlagBits stage;
521 if (m_stage == vk::VK_SHADER_STAGE_ALL)
522 stage = stages[random.getUint32() % stages.size()];
523 else
524 stage = m_stage;
525
526 bool useLayout = stage == vk::VK_SHADER_STAGE_COMPUTE_BIT;
527
528 const auto& src = binaries.get(getShaderName(stage) + std::to_string(i % 10));
529 shaderCreateInfos.push_back(
530 {
531 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
532 DE_NULL, // const void* pNext;
533 0u, // VkShaderCreateFlagsEXT flags;
534 stage, // VkShaderStageFlagBits stage;
535 vk::getShaderObjectNextStages(stage, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage;
536 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
537 src.getSize(), // size_t codeSize;
538 src.getBinary(), // const void* pCode;
539 "main", // const char* pName;
540 useLayout ? 1u : 0u, // uint32_t setLayoutCount;
541 useLayout ? &*descriptorSetLayout : DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
542 0u, // uint32_t pushConstantRangeCount;
543 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
544 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
545 });
546 }
547
548 std::vector<vk::VkShaderEXT> shaders (count, VK_NULL_HANDLE);
549 vk::VkResult result;
550 result = vk.createShadersEXT(device, count, &shaderCreateInfos[0], DE_NULL, &shaders[0]);
551 if (result != vk::VK_SUCCESS)
552 {
553 log << tcu::TestLog::Message << "vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage;
554 return tcu::TestStatus::fail("Fail");
555 }
556
557 std::vector<size_t> binarySizes (count);
558 std::vector<std::vector<deUint8>> binaryData (count);
559 for (size_t i = 0; i < count; ++i)
560 {
561 vk.getShaderBinaryDataEXT(device, shaders[i], &binarySizes[i], DE_NULL);
562 binaryData[i].resize(binarySizes[i]);
563 vk.getShaderBinaryDataEXT(device, shaders[i], &binarySizes[i], (void*)&binaryData[i][0]);
564 }
565
566 for (const auto& shader : shaders)
567 vk.destroyShaderEXT(device, shader, DE_NULL);
568
569 const deUint32 failIndex = random.getUint32() % count;
570
571 for (deUint32 i = 0; i < count; ++i)
572 {
573 shaderCreateInfos[i].codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT;
574 if (m_fail && failIndex == i)
575 shaderCreateInfos[i].codeSize = 1;
576 else
577 shaderCreateInfos[i].codeSize = binarySizes[i];
578 shaderCreateInfos[i].pCode = &binaryData[i][0];
579 }
580
581 deUint32 garbage = 1234u;
582 std::vector<vk::VkShaderEXT> binaryShaders (count, garbage); // Fill with garbage
583 result = vk.createShadersEXT(device, count, &shaderCreateInfos[0], DE_NULL, &binaryShaders[0]);
584
585 if (m_fail)
586 {
587 if (result != vk::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT)
588 {
589 log << tcu::TestLog::Message << "Shader at index " << failIndex << "was created with size 0, but vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage;
590 return tcu::TestStatus::fail("Fail");
591 }
592
593 for (deUint32 i = 0; i < failIndex; ++i)
594 {
595 if (binaryShaders[i] == garbage)
596 {
597 log << tcu::TestLog::Message << "vkCreateShadersEXT returned VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT and failed at index " << failIndex << ", but shader at index " << i << "was not created" << tcu::TestLog::EndMessage;
598 return tcu::TestStatus::fail("Fail");
599 }
600 vk.destroyShaderEXT(device, binaryShaders[i], DE_NULL);
601 }
602 if (binaryShaders[failIndex] != VK_NULL_HANDLE)
603 {
604 log << tcu::TestLog::Message << "vkCreateShadersEXT returned VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT, creating shader at index " << failIndex << " failed, but the shader is not VK_NULL_HANDLE" << tcu::TestLog::EndMessage;
605 return tcu::TestStatus::fail("Fail");
606 }
607 }
608 else
609 {
610 if (result != vk::VK_SUCCESS)
611 {
612 log << tcu::TestLog::Message << "vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage;
613 return tcu::TestStatus::fail("Fail");
614 }
615
616 for (const auto& shader : binaryShaders)
617 vk.destroyShaderEXT(device, shader, DE_NULL);
618 }
619
620 return tcu::TestStatus::pass("Pass");
621 }
622
623 class ShaderObjectStageCase : public vkt::TestCase
624 {
625 public:
ShaderObjectStageCase(tcu::TestContext & testCtx,const std::string & name,const vk::VkShaderStageFlagBits stage,const bool fail,const bool useMeshShaders)626 ShaderObjectStageCase (tcu::TestContext& testCtx, const std::string& name, const vk::VkShaderStageFlagBits stage, const bool fail, const bool useMeshShaders)
627 : vkt::TestCase (testCtx, name)
628 , m_stage (stage)
629 , m_fail (fail)
630 , m_useMeshShaders (useMeshShaders)
631 {}
~ShaderObjectStageCase(void)632 virtual ~ShaderObjectStageCase (void) {}
633
634 void checkSupport (vkt::Context& context) const override;
635 virtual void initPrograms (vk::SourceCollections& programCollection) const override;
createInstance(Context & context) const636 TestInstance* createInstance (Context& context) const override { return new ShaderObjectStageInstance(context, m_stage, m_fail, m_useMeshShaders); }
637 private:
638 const vk::VkShaderStageFlagBits m_stage;
639 const bool m_fail;
640 const bool m_useMeshShaders;
641 };
642
checkSupport(Context & context) const643 void ShaderObjectStageCase::checkSupport (Context& context) const
644 {
645 context.requireDeviceFunctionality("VK_EXT_shader_object");
646 if (m_useMeshShaders)
647 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
648
649 if (m_stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
650 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
651 if (m_stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
652 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
653 if (m_stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT && context.getMeshShaderFeaturesEXT().taskShader == VK_FALSE)
654 TCU_THROW(NotSupportedError, "Task shaders not supported");
655 if (m_stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT && context.getMeshShaderFeaturesEXT().meshShader == VK_FALSE)
656 TCU_THROW(NotSupportedError, "Mesh shaders not supported");
657 }
658
initPrograms(vk::SourceCollections & programCollection) const659 void ShaderObjectStageCase::initPrograms (vk::SourceCollections& programCollection) const
660 {
661 for (deUint32 i = 0; i < 10; ++i)
662 {
663 std::stringstream vert;
664 std::stringstream geom;
665 std::stringstream tesc;
666 std::stringstream tese;
667 std::stringstream frag;
668 std::stringstream comp;
669 std::stringstream mesh;
670 std::stringstream task;
671
672 vert
673 << "#version 450\n"
674 << "layout (location=0) in vec2 inPos;\n"
675 << "void main() {\n"
676 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
677 << " gl_Position = vec4(pos * float(" << i << "), 0.0f, 1.0f);\n"
678 << "}\n";
679
680 tesc
681 << "#version 450\n"
682 << "\n"
683 << "layout(vertices = 3) out;\n"
684 << "\n"
685 << "void main (void)\n"
686 << "{\n"
687 << " gl_TessLevelInner[0] = 5.0 + float(" << i << ");\n"
688 << " gl_TessLevelInner[1] = 5.0 + float(" << i << ");\n"
689 << "\n"
690 << " gl_TessLevelOuter[0] = 5.0;\n"
691 << " gl_TessLevelOuter[1] = 5.0;\n"
692 << " gl_TessLevelOuter[2] = 5.0;\n"
693 << " gl_TessLevelOuter[3] = 5.0;\n"
694 << "}\n";
695
696 tese
697 << "#version 450\n"
698 << "\n"
699 << "layout(quads) in;\n"
700 << "\n"
701 << "void main (void)\n"
702 << "{\n"
703 << " highp float x = gl_TessCoord.x * float(" << i << ") - 1.0;\n"
704 << " highp float y = gl_TessCoord.y * float(" << i << ") - 1.0;\n"
705 << " gl_Position = vec4(x, y, 0.0, 1.0);\n"
706 << "}\n";
707
708 geom
709 << "#version 450\n"
710 << "layout(points) in;\n"
711 << "layout(points, max_vertices = 1) out;\n"
712 << "\n"
713 << "void main(void)\n"
714 << "{\n"
715 << " gl_Position = gl_in[0].gl_Position;\n"
716 << " gl_Position.xy += vec2(float(" << i << "));\n"
717 << " EmitVertex();\n"
718 << " EndPrimitive();\n"
719 << "}\n";
720
721 frag
722 << "#version 450\n"
723 << "layout (location=0) out vec4 outColor;\n"
724 << "void main() {\n"
725 << " outColor = vec4(1.0f / (1.0f + float(" << i << ")));\n"
726 << "}\n";
727
728 comp
729 << "#version 450\n"
730 << "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n"
731 << "layout(binding = 0) buffer Output {\n"
732 << " uint values[16];\n"
733 << "} buffer_out;\n\n"
734 << "void main() {\n"
735 << " buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x + " << i << ";\n"
736 << "}\n";
737
738 mesh
739 << "#version 460\n"
740 << "#extension GL_EXT_mesh_shader : require\n"
741 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
742 << "layout(max_vertices = 3) out;\n"
743 << "layout(max_primitives = 1) out;\n"
744 << "layout(triangles) out;\n"
745 << "void main() {\n"
746 << " SetMeshOutputsEXT(3,1);\n"
747 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0, 1);\n"
748 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 1.0, -1.0, 0, 1);\n"
749 << " gl_MeshVerticesEXT[2].gl_Position = vec4( 0.0, 1.0, 0, 1);\n"
750 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0,1,2);\n"
751 << "}\n";
752
753 task
754 << "#version 450\n"
755 << "#extension GL_EXT_mesh_shader : enable\n"
756 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
757 << "struct TaskData {\n"
758 << " int t;\n"
759 << "};\n"
760 << "taskPayloadSharedEXT TaskData td;\n"
761 << "void main ()\n"
762 << "{\n"
763 << " td.t = 1;\n"
764 << " EmitMeshTasksEXT(1u, 1u, 1u);\n"
765 << "}\n";
766
767 programCollection.glslSources.add("vert" + std::to_string(i)) << glu::VertexSource(vert.str());
768 programCollection.glslSources.add("tesc" + std::to_string(i)) << glu::TessellationControlSource(tesc.str());
769 programCollection.glslSources.add("tese" + std::to_string(i)) << glu::TessellationEvaluationSource(tese.str());
770 programCollection.glslSources.add("geom" + std::to_string(i)) << glu::GeometrySource(geom.str());
771 programCollection.glslSources.add("frag" + std::to_string(i)) << glu::FragmentSource(frag.str());
772 programCollection.glslSources.add("comp" + std::to_string(i)) << glu::ComputeSource(comp.str());
773 if (m_useMeshShaders)
774 {
775 programCollection.glslSources.add("mesh" + std::to_string(i)) << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
776 programCollection.glslSources.add("task" + std::to_string(i)) << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
777 }
778 }
779 }
780
781 }
782
createShaderObjectCreateTests(tcu::TestContext & testCtx)783 tcu::TestCaseGroup* createShaderObjectCreateTests (tcu::TestContext& testCtx)
784 {
785 de::MovePtr<tcu::TestCaseGroup> createGroup(new tcu::TestCaseGroup(testCtx, "create"));
786
787 de::MovePtr<tcu::TestCaseGroup> multipleGroup(new tcu::TestCaseGroup(testCtx, "multiple"));
788
789 multipleGroup->addChild(new ShaderObjectCreateCase(testCtx, "all", false));
790 multipleGroup->addChild(new ShaderObjectCreateCase(testCtx, "all_with_mesh", true));
791
792 createGroup->addChild(multipleGroup.release());
793
794 const struct
795 {
796 vk::VkShaderStageFlagBits stage;
797 const bool useMeshShaders;
798 const char* name;
799 } stageTests[] =
800 {
801 { vk::VK_SHADER_STAGE_VERTEX_BIT, false, "vert" },
802 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, false, "tesc" },
803 { vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, false, "tese" },
804 { vk::VK_SHADER_STAGE_GEOMETRY_BIT, false, "geom" },
805 { vk::VK_SHADER_STAGE_FRAGMENT_BIT, false, "frag" },
806 { vk::VK_SHADER_STAGE_COMPUTE_BIT, false, "comp" },
807 { vk::VK_SHADER_STAGE_MESH_BIT_EXT, true, "mesh" },
808 { vk::VK_SHADER_STAGE_TASK_BIT_EXT, true, "task" },
809 { vk::VK_SHADER_STAGE_ALL, false, "all" },
810 { vk::VK_SHADER_STAGE_ALL, true, "all_with_mesh" },
811 };
812
813 const struct
814 {
815 bool fail;
816 const char* name;
817 } failTests[] =
818 {
819 { false, "succeed" },
820 { true, "fail" },
821 };
822
823 for (const auto& stage : stageTests)
824 {
825 de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stage.name));
826 for (const auto& failTest : failTests)
827 {
828 stageGroup->addChild(new ShaderObjectStageCase(testCtx, failTest.name, stage.stage, failTest.fail, stage.useMeshShaders));
829 }
830 createGroup->addChild(stageGroup.release());
831 }
832
833 return createGroup.release();
834 }
835
836 } // ShaderObject
837 } // vkt
838