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