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 Link Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktShaderObjectCreateTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vktShaderObjectCreateUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deRandom.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36
37 namespace vkt
38 {
39 namespace ShaderObject
40 {
41
42 namespace
43 {
44
45 enum ShaderType
46 {
47 UNUSED,
48 LINKED,
49 UNLINKED,
50 };
51
52 struct Shaders
53 {
54 ShaderType vertex;
55 ShaderType tesellation_control;
56 ShaderType tesellation_evaluation;
57 ShaderType geometry;
58 ShaderType fragment;
59 };
60
61 struct MeshShaders
62 {
63 ShaderType task;
64 ShaderType mesh;
65 ShaderType fragment;
66 };
67
68 struct NextStages
69 {
70 vk::VkShaderStageFlags vertNextStage;
71 vk::VkShaderStageFlags tescNextStage;
72 vk::VkShaderStageFlags teseNextStage;
73 vk::VkShaderStageFlags geomNextStage;
74 };
75
76 struct MeshNextStages
77 {
78 vk::VkShaderStageFlags taskNextStage;
79 vk::VkShaderStageFlags meshNextStage;
80 };
81
82 enum BindType
83 {
84 SEPARATE,
85 ONE_LINKED_UNLINKED,
86 ALL,
87 };
88
89 struct TestParams
90 {
91 Shaders shaders;
92 bool randomOrder;
93 NextStages nextStages;
94 bool separateLinked;
95 BindType separateBind;
96 };
97
98 struct MeshParams
99 {
100 MeshShaders shaders;
101 bool randomOrder;
102 MeshNextStages nextStages;
103 };
104
105 class ShaderObjectLinkInstance : public vkt::TestInstance
106 {
107 public:
ShaderObjectLinkInstance(Context & context,const TestParams & params)108 ShaderObjectLinkInstance(Context &context, const TestParams ¶ms) : vkt::TestInstance(context), m_params(params)
109 {
110 }
~ShaderObjectLinkInstance(void)111 virtual ~ShaderObjectLinkInstance(void)
112 {
113 }
114
115 tcu::TestStatus iterate(void) override;
116
117 private:
118 vk::VkShaderStageFlags getNextStage(vk::VkShaderStageFlagBits currentStage);
119
120 TestParams m_params;
121 };
122
getNextStage(vk::VkShaderStageFlagBits currentStage)123 vk::VkShaderStageFlags ShaderObjectLinkInstance::getNextStage(vk::VkShaderStageFlagBits currentStage)
124 {
125 if (currentStage == vk::VK_SHADER_STAGE_VERTEX_BIT && m_params.shaders.vertex == LINKED)
126 {
127 if (m_params.shaders.tesellation_control != UNUSED)
128 {
129 if (m_params.shaders.tesellation_control == LINKED)
130 return vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
131 }
132 else if (m_params.shaders.geometry != UNUSED)
133 {
134 if (m_params.shaders.geometry == LINKED)
135 return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
136 }
137 else if (m_params.shaders.fragment != UNUSED)
138 {
139 if (m_params.shaders.fragment == LINKED)
140 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
141 }
142 }
143 else if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT &&
144 m_params.shaders.tesellation_control == LINKED && m_params.shaders.tesellation_evaluation == LINKED)
145 {
146 return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
147 }
148 else if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT &&
149 m_params.shaders.tesellation_evaluation == LINKED)
150 {
151 if (m_params.shaders.geometry != UNUSED)
152 {
153 if (m_params.shaders.geometry == LINKED)
154 return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
155 }
156 else if (m_params.shaders.fragment != UNUSED)
157 {
158 if (m_params.shaders.fragment == LINKED)
159 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
160 }
161 }
162 else if (currentStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT && m_params.shaders.geometry == LINKED)
163 {
164 if (m_params.shaders.fragment != UNUSED)
165 {
166 if (m_params.shaders.fragment == LINKED)
167 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
168 }
169 }
170
171 if (currentStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
172 return m_params.nextStages.vertNextStage;
173
174 if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
175 return m_params.nextStages.tescNextStage;
176
177 if (currentStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
178 return m_params.nextStages.teseNextStage;
179
180 if (currentStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
181 return m_params.nextStages.geomNextStage;
182
183 return 0;
184 }
185
iterate(void)186 tcu::TestStatus ShaderObjectLinkInstance::iterate(void)
187 {
188 const vk::VkInstance instance = m_context.getInstance();
189 const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
190 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
191 const vk::VkDevice device = m_context.getDevice();
192 const vk::VkQueue queue = m_context.getUniversalQueue();
193 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
194 auto &alloc = m_context.getDefaultAllocator();
195 tcu::TestLog &log = m_context.getTestContext().getLog();
196 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(
197 m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
198 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
199 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader;
200 const bool taskSupported = m_context.getMeshShaderFeaturesEXT().taskShader;
201 const bool meshSupported = m_context.getMeshShaderFeaturesEXT().meshShader;
202
203 vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
204 const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
205
206 const vk::VkImageCreateInfo createInfo = {
207 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
208 DE_NULL, // const void* pNext
209 0u, // VkImageCreateFlags flags
210 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType
211 colorAttachmentFormat, // VkFormat format
212 {32, 32, 1}, // VkExtent3D extent
213 1u, // uint32_t mipLevels
214 1u, // uint32_t arrayLayers
215 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
216 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
217 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
218 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
219 0, // uint32_t queueFamilyIndexCount
220 DE_NULL, // const uint32_t* pQueueFamilyIndices
221 vk::VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
222 };
223
224 de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
225 new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
226 const auto imageView =
227 vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
228 const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
229
230 const vk::VkDeviceSize colorOutputBufferSize =
231 renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
232 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
233 vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
234 vk::MemoryRequirement::HostVisible));
235
236 const auto &binaries = m_context.getBinaryCollection();
237 const auto &vert = binaries.get("vert");
238 const auto &tesc = binaries.get("tesc");
239 const auto &tese = binaries.get("tese");
240 const auto &geom = binaries.get("geom");
241 const auto &frag = binaries.get("frag");
242
243 vk::VkShaderEXT vertShader;
244 vk::VkShaderEXT tescShader;
245 vk::VkShaderEXT teseShader;
246 vk::VkShaderEXT geomShader;
247 vk::VkShaderEXT fragShader;
248
249 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos;
250
251 vk::VkShaderCreateInfoEXT vertShaderCreateInfo =
252 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert, tessellationSupported, geometrySupported);
253 vertShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_VERTEX_BIT);
254
255 if (m_params.shaders.vertex == LINKED)
256 {
257 vertShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
258 shaderCreateInfos.push_back(vertShaderCreateInfo);
259 }
260 else if (m_params.shaders.vertex == UNLINKED)
261 {
262 vk.createShadersEXT(device, 1, &vertShaderCreateInfo, DE_NULL, &vertShader);
263 }
264
265 vk::VkShaderCreateInfoEXT tescShaderCreateInfo = vk::makeShaderCreateInfo(
266 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tesc, tessellationSupported, geometrySupported);
267 tescShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
268
269 if (m_params.shaders.tesellation_control == LINKED)
270 {
271 tescShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
272 shaderCreateInfos.push_back(tescShaderCreateInfo);
273 }
274 else if (m_params.shaders.tesellation_control == UNLINKED)
275 {
276 vk.createShadersEXT(device, 1, &tescShaderCreateInfo, DE_NULL, &tescShader);
277 }
278
279 vk::VkShaderCreateInfoEXT teseShaderCreateInfo = vk::makeShaderCreateInfo(
280 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tese, tessellationSupported, geometrySupported);
281 teseShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
282
283 if (m_params.shaders.tesellation_evaluation == LINKED)
284 {
285 teseShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
286 shaderCreateInfos.push_back(teseShaderCreateInfo);
287 }
288 else if (m_params.shaders.tesellation_evaluation == UNLINKED)
289 {
290 vk.createShadersEXT(device, 1, &teseShaderCreateInfo, DE_NULL, &teseShader);
291 }
292
293 vk::VkShaderCreateInfoEXT geomShaderCreateInfo =
294 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, geom, tessellationSupported, geometrySupported);
295 geomShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
296
297 if (m_params.shaders.geometry == LINKED)
298 {
299 geomShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
300 shaderCreateInfos.push_back(geomShaderCreateInfo);
301 }
302 else if (m_params.shaders.geometry == UNLINKED)
303 {
304 vk.createShadersEXT(device, 1, &geomShaderCreateInfo, DE_NULL, &geomShader);
305 }
306
307 vk::VkShaderCreateInfoEXT fragShaderCreateInfo =
308 vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag, tessellationSupported, geometrySupported);
309 fragShaderCreateInfo.nextStage = getNextStage(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
310
311 if (m_params.shaders.fragment == LINKED)
312 {
313 fragShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
314 shaderCreateInfos.push_back(fragShaderCreateInfo);
315 }
316 else if (m_params.shaders.fragment == UNLINKED)
317 {
318 vk.createShadersEXT(device, 1, &fragShaderCreateInfo, DE_NULL, &fragShader);
319 }
320
321 vk::VkPrimitiveTopology primitiveTopology = m_params.shaders.tesellation_control != UNUSED ?
322 vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
323 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
324
325 if (!shaderCreateInfos.empty())
326 {
327 std::vector<vk::VkShaderEXT> shaders(shaderCreateInfos.size());
328 uint32_t i = 0u;
329 uint32_t j = 0u;
330 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
331 {
332 de::Random random(102030);
333 i = random.getUint32() % (uint32_t)shaders.size();
334 do
335 {
336 j = random.getUint32() % (uint32_t)shaders.size();
337 } while (i == j);
338 std::swap(shaderCreateInfos[i], shaderCreateInfos[j]);
339 }
340 if (m_params.separateLinked)
341 {
342 for (uint32_t k = 0; k < (uint32_t)shaders.size(); ++k)
343 vk.createShadersEXT(device, 1u, &shaderCreateInfos[k], DE_NULL, &shaders[k]);
344 }
345 else
346 {
347 vk.createShadersEXT(device, (uint32_t)shaders.size(), &shaderCreateInfos[0], DE_NULL, &shaders[0]);
348 }
349 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
350 {
351 std::swap(shaders[i], shaders[j]);
352 }
353 uint32_t n = 0;
354 if (m_params.shaders.vertex == LINKED)
355 {
356 vertShader = shaders[n++];
357 }
358 if (m_params.shaders.tesellation_control == LINKED)
359 {
360 tescShader = shaders[n++];
361 }
362 if (m_params.shaders.tesellation_evaluation == LINKED)
363 {
364 teseShader = shaders[n++];
365 }
366 if (m_params.shaders.geometry == LINKED)
367 {
368 geomShader = shaders[n++];
369 }
370 if (m_params.shaders.fragment == LINKED)
371 {
372 fragShader = shaders[n++];
373 }
374 }
375
376 const vk::VkCommandPoolCreateInfo cmdPoolInfo = {
377 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
378 DE_NULL, // pNext
379 vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
380 queueFamilyIndex, // queuefamilyindex
381 };
382
383 const vk::Move<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolInfo));
384 const vk::Move<vk::VkCommandBuffer> cmdBuffer(
385 allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
386
387 // Draw
388 vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
389
390 vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(
391 vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
392 vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
393 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
394 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u,
395 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
396 &preImageBarrier);
397
398 if (m_params.separateBind == SEPARATE)
399 {
400 vk::VkShaderStageFlagBits vertStage = vk::VK_SHADER_STAGE_VERTEX_BIT;
401 vk::VkShaderStageFlagBits tescStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
402 vk::VkShaderStageFlagBits teseStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
403 vk::VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
404 vk::VkShaderStageFlagBits fragStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
405 vk::VkShaderEXT bindVertShader = (m_params.shaders.vertex != UNUSED) ? vertShader : VK_NULL_HANDLE;
406 vk::VkShaderEXT bindTescShader = (m_params.shaders.tesellation_control != UNUSED) ? tescShader : VK_NULL_HANDLE;
407 vk::VkShaderEXT bindTeseShader =
408 (m_params.shaders.tesellation_evaluation != UNUSED) ? teseShader : VK_NULL_HANDLE;
409 vk::VkShaderEXT bindGeomShader = (m_params.shaders.geometry != UNUSED) ? geomShader : VK_NULL_HANDLE;
410 vk::VkShaderEXT bindFragShader = (m_params.shaders.fragment != UNUSED) ? fragShader : VK_NULL_HANDLE;
411 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &vertStage, &bindVertShader);
412 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &tescStage, &bindTescShader);
413 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &teseStage, &bindTeseShader);
414 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &geomStage, &bindGeomShader);
415 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &fragStage, &bindFragShader);
416 }
417 else if (m_params.separateBind == ONE_LINKED_UNLINKED)
418 {
419 std::vector<vk::VkShaderStageFlagBits> separateStages;
420 std::vector<vk::VkShaderStageFlagBits> togetherStages;
421 std::vector<vk::VkShaderEXT> separateShaders;
422 std::vector<vk::VkShaderEXT> togetherShaders;
423
424 bool linkedAdded = false;
425 if ((!linkedAdded && m_params.shaders.vertex == LINKED) || m_params.shaders.vertex == UNLINKED)
426 {
427 togetherStages.push_back(vk::VK_SHADER_STAGE_VERTEX_BIT);
428 togetherShaders.push_back(vertShader);
429 linkedAdded = true;
430 }
431 else if (m_params.shaders.vertex == LINKED)
432 {
433 separateStages.push_back(vk::VK_SHADER_STAGE_VERTEX_BIT);
434 togetherShaders.push_back(vertShader);
435 }
436
437 if ((!linkedAdded && m_params.shaders.tesellation_control == LINKED) ||
438 m_params.shaders.tesellation_control == UNLINKED)
439 {
440 togetherStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
441 togetherShaders.push_back(tescShader);
442 linkedAdded = true;
443 }
444 else if (m_params.shaders.tesellation_control == LINKED)
445 {
446 separateStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
447 separateShaders.push_back(tescShader);
448 }
449
450 if ((!linkedAdded && m_params.shaders.tesellation_evaluation == LINKED) ||
451 m_params.shaders.tesellation_evaluation == UNLINKED)
452 {
453 togetherStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
454 togetherShaders.push_back(teseShader);
455 linkedAdded = true;
456 }
457 else if (m_params.shaders.tesellation_evaluation == LINKED)
458 {
459 separateStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
460 separateShaders.push_back(teseShader);
461 }
462
463 if ((!linkedAdded && m_params.shaders.geometry == LINKED) || m_params.shaders.geometry == UNLINKED)
464 {
465 togetherStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
466 togetherShaders.push_back(geomShader);
467 linkedAdded = true;
468 }
469 else if (m_params.shaders.geometry == LINKED)
470 {
471 separateStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
472 separateShaders.push_back(geomShader);
473 }
474
475 if ((!linkedAdded && m_params.shaders.fragment == LINKED) || m_params.shaders.fragment == UNLINKED)
476 {
477 togetherStages.push_back(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
478 togetherShaders.push_back(fragShader);
479 linkedAdded = true;
480 }
481 else if (m_params.shaders.fragment == LINKED)
482 {
483 separateStages.push_back(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
484 separateShaders.push_back(fragShader);
485 }
486
487 vk::bindGraphicsShaders(vk, *cmdBuffer, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE,
488 VK_NULL_HANDLE, taskSupported, meshSupported);
489 if (!togetherShaders.empty())
490 vk.cmdBindShadersEXT(*cmdBuffer, (uint32_t)togetherShaders.size(), togetherStages.data(),
491 togetherShaders.data());
492 if (!separateShaders.empty())
493 vk.cmdBindShadersEXT(*cmdBuffer, (uint32_t)separateShaders.size(), separateStages.data(),
494 separateShaders.data());
495 }
496 else
497 {
498 vk::bindGraphicsShaders(vk, *cmdBuffer, m_params.shaders.vertex != UNUSED ? vertShader : VK_NULL_HANDLE,
499 m_params.shaders.tesellation_control != UNUSED ? tescShader : VK_NULL_HANDLE,
500 m_params.shaders.tesellation_evaluation != UNUSED ? teseShader : VK_NULL_HANDLE,
501 m_params.shaders.geometry != UNUSED ? geomShader : VK_NULL_HANDLE,
502 m_params.shaders.fragment != UNUSED ? fragShader : VK_NULL_HANDLE, taskSupported,
503 meshSupported);
504 }
505 vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, primitiveTopology, false);
506
507 bindNullTaskMeshShaders(vk, *cmdBuffer, m_context.getMeshShaderFeaturesEXT());
508
509 const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
510 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
511 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
512 vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
513 vk::endRendering(vk, *cmdBuffer);
514
515 vk::VkImageMemoryBarrier postImageBarrier =
516 vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
517 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
518 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
519 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
520 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
521 &postImageBarrier);
522
523 const vk::VkBufferImageCopy copyRegion = {
524 0u, // VkDeviceSize bufferOffset;
525 0u, // uint32_t bufferRowLength;
526 0u, // uint32_t bufferImageHeight;
527 {
528 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
529 0u, // uint32_t mipLevel;
530 0u, // uint32_t baseArrayLayer;
531 1u, // uint32_t layerCount;
532 }, // VkImageSubresourceLayers imageSubresource;
533 {0, 0, 0}, // VkOffset3D imageOffset;
534 {renderArea.extent.width, renderArea.extent.height, 1} // VkExtent3D imageExtent;
535 };
536 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, ©Region);
537
538 vk::endCommandBuffer(vk, *cmdBuffer);
539
540 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
541
542 // Cleanup
543 if (m_params.shaders.vertex != UNUSED)
544 vk.destroyShaderEXT(device, vertShader, DE_NULL);
545
546 if (m_params.shaders.tesellation_control != UNUSED)
547 vk.destroyShaderEXT(device, tescShader, DE_NULL);
548
549 if (m_params.shaders.tesellation_evaluation != UNUSED)
550 vk.destroyShaderEXT(device, teseShader, DE_NULL);
551
552 if (m_params.shaders.geometry != UNUSED)
553 vk.destroyShaderEXT(device, geomShader, DE_NULL);
554
555 if (m_params.shaders.fragment != UNUSED)
556 vk.destroyShaderEXT(device, fragShader, DE_NULL);
557
558 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
559 vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1,
560 (const void *)colorOutputBuffer->getAllocation().getHostPtr());
561
562 const tcu::Vec4 black = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
563 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
564 const int32_t width = resultBuffer.getWidth();
565 const int32_t height = resultBuffer.getHeight();
566 const int32_t xOffset = m_params.shaders.tesellation_control != UNUSED ? 4 : 8;
567 const int32_t yOffset = m_params.shaders.geometry != UNUSED ? 4 : 8;
568
569 for (int32_t j = 0; j < height; ++j)
570 {
571 for (int32_t i = 0; i < width; ++i)
572 {
573 const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
574 if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
575 {
576 if (color != white)
577 {
578 log << tcu::TestLog::Message << "Color at (" << i << ", " << j
579 << ") is expected to be (1.0, 1.0, 1.0, 1.0), but was (" << color << ")"
580 << tcu::TestLog::EndMessage;
581 return tcu::TestStatus::fail("Fail");
582 }
583 }
584 else
585 {
586 if (color != black)
587 {
588 log << tcu::TestLog::Message << "Color at (" << i << ", " << j
589 << ") is expected to be (0.0, 0.0, 0.0, 0.0), but was (" << color << ")"
590 << tcu::TestLog::EndMessage;
591 return tcu::TestStatus::fail("Fail");
592 }
593 }
594 }
595 }
596
597 return tcu::TestStatus::pass("Pass");
598 }
599
600 class ShaderObjectLinkCase : public vkt::TestCase
601 {
602 public:
ShaderObjectLinkCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)603 ShaderObjectLinkCase(tcu::TestContext &testCtx, const std::string &name, const TestParams ¶ms)
604 : vkt::TestCase(testCtx, name)
605 , m_params(params)
606 {
607 }
~ShaderObjectLinkCase(void)608 virtual ~ShaderObjectLinkCase(void)
609 {
610 }
611
612 void checkSupport(vkt::Context &context) const override;
613 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const614 TestInstance *createInstance(Context &context) const override
615 {
616 return new ShaderObjectLinkInstance(context, m_params);
617 }
618
619 private:
620 TestParams m_params;
621 };
622
checkSupport(Context & context) const623 void ShaderObjectLinkCase::checkSupport(Context &context) const
624 {
625 context.requireDeviceFunctionality("VK_EXT_shader_object");
626
627 if (m_params.shaders.tesellation_control != UNUSED || m_params.shaders.tesellation_evaluation != UNUSED ||
628 (m_params.nextStages.vertNextStage | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) > 0)
629 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
630
631 if (m_params.shaders.geometry != UNUSED ||
632 (m_params.nextStages.vertNextStage | vk::VK_SHADER_STAGE_GEOMETRY_BIT) > 0 ||
633 (m_params.nextStages.teseNextStage | vk::VK_SHADER_STAGE_GEOMETRY_BIT) > 0)
634 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
635 }
636
initPrograms(vk::SourceCollections & programCollection) const637 void ShaderObjectLinkCase::initPrograms(vk::SourceCollections &programCollection) const
638 {
639 vk::addBasicShaderObjectShaders(programCollection);
640 }
641
642 class MeshShaderObjectLinkInstance : public vkt::TestInstance
643 {
644 public:
MeshShaderObjectLinkInstance(Context & context,const MeshParams & params)645 MeshShaderObjectLinkInstance(Context &context, const MeshParams ¶ms)
646 : vkt::TestInstance(context)
647 , m_params(params)
648 {
649 }
~MeshShaderObjectLinkInstance(void)650 virtual ~MeshShaderObjectLinkInstance(void)
651 {
652 }
653
654 tcu::TestStatus iterate(void) override;
655
656 private:
657 vk::VkShaderStageFlags getNextStage(vk::VkShaderStageFlagBits currentStage);
658
659 MeshParams m_params;
660 };
661
getNextStage(vk::VkShaderStageFlagBits currentStage)662 vk::VkShaderStageFlags MeshShaderObjectLinkInstance::getNextStage(vk::VkShaderStageFlagBits currentStage)
663 {
664 if (currentStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
665 {
666 if (m_params.shaders.task == LINKED)
667 return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
668 return m_params.nextStages.taskNextStage;
669 }
670
671 if (currentStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
672 {
673 if (m_params.shaders.mesh == LINKED)
674 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
675 return m_params.nextStages.meshNextStage;
676 }
677
678 return 0;
679 }
680
iterate(void)681 tcu::TestStatus MeshShaderObjectLinkInstance::iterate(void)
682 {
683 const vk::VkInstance instance = m_context.getInstance();
684 const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
685 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
686 const vk::VkDevice device = m_context.getDevice();
687 const vk::VkQueue queue = m_context.getUniversalQueue();
688 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
689 auto &alloc = m_context.getDefaultAllocator();
690 tcu::TestLog &log = m_context.getTestContext().getLog();
691 const auto deviceExtensions = vk::removeUnsupportedShaderObjectExtensions(
692 m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
693
694 vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
695 const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
696
697 const vk::VkImageCreateInfo createInfo = {
698 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
699 DE_NULL, // const void* pNext
700 0u, // VkImageCreateFlags flags
701 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType
702 colorAttachmentFormat, // VkFormat format
703 {32, 32, 1}, // VkExtent3D extent
704 1u, // uint32_t mipLevels
705 1u, // uint32_t arrayLayers
706 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
707 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
708 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
709 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
710 0, // uint32_t queueFamilyIndexCount
711 DE_NULL, // const uint32_t* pQueueFamilyIndices
712 vk::VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
713 };
714
715 de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
716 new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
717 const auto imageView =
718 vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
719 const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
720
721 const vk::VkDeviceSize colorOutputBufferSize =
722 renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
723 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
724 vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
725 vk::MemoryRequirement::HostVisible));
726
727 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
728 vk::DescriptorSetLayoutBuilder()
729 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_MESH_BIT_EXT)
730 .build(vk, device));
731
732 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
733 vk::DescriptorPoolBuilder()
734 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
735 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
736
737 const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 4;
738 const vk::Unique<vk::VkDescriptorSet> descriptorSet(
739 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
740 const vk::BufferWithMemory outputBuffer(
741 vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
742 vk::MemoryRequirement::HostVisible);
743
744 const vk::VkDescriptorBufferInfo descriptorInfo =
745 vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
746 vk::DescriptorSetUpdateBuilder()
747 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
748 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
749 .update(vk, device);
750
751 const auto pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
752
753 const auto &binaries = m_context.getBinaryCollection();
754 const auto &task = binaries.get("task");
755 const auto &mesh = binaries.get("mesh");
756 const auto &frag = binaries.get("frag");
757
758 vk::VkShaderEXT taskShader;
759 vk::VkShaderEXT meshShader;
760 vk::VkShaderEXT fragShader;
761
762 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos;
763
764 vk::VkShaderCreateInfoEXT taskShaderCreateInfo = {
765 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
766 DE_NULL, // const void* pNext;
767 0u, // VkShaderCreateFlagsEXT flags;
768 vk::VK_SHADER_STAGE_TASK_BIT_EXT, // VkShaderStageFlagBits stage;
769 getNextStage(vk::VK_SHADER_STAGE_TASK_BIT_EXT), // VkShaderStageFlags nextStage;
770 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
771 task.getSize(), // size_t codeSize;
772 task.getBinary(), // const void* pCode;
773 "main", // const char* pName;
774 1u, // uint32_t setLayoutCount;
775 &*descriptorSetLayout, // VkDescriptorSetLayout* pSetLayouts;
776 0u, // uint32_t pushConstantRangeCount;
777 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
778 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
779 };
780
781 if (m_params.shaders.task == LINKED)
782 {
783 taskShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
784 shaderCreateInfos.push_back(taskShaderCreateInfo);
785 }
786 else if (m_params.shaders.task == UNLINKED)
787 {
788 vk.createShadersEXT(device, 1, &taskShaderCreateInfo, DE_NULL, &taskShader);
789 }
790
791 vk::VkShaderCreateInfoEXT meshShaderCreateInfo = {
792 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
793 DE_NULL, // const void* pNext;
794 (m_params.shaders.task == UNUSED) ? (vk::VkShaderCreateFlagsEXT)vk::VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT :
795 (vk::VkShaderCreateFlagsEXT)0u,
796 // VkShaderCreateFlagsEXT flags;
797 vk::VK_SHADER_STAGE_MESH_BIT_EXT, // VkShaderStageFlagBits stage;
798 getNextStage(vk::VK_SHADER_STAGE_MESH_BIT_EXT), // VkShaderStageFlags nextStage;
799 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
800 mesh.getSize(), // size_t codeSize;
801 mesh.getBinary(), // const void* pCode;
802 "main", // const char* pName;
803 1u, // uint32_t setLayoutCount;
804 &*descriptorSetLayout, // VkDescriptorSetLayout* pSetLayouts;
805 0u, // uint32_t pushConstantRangeCount;
806 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
807 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
808 };
809
810 if (m_params.shaders.mesh == LINKED)
811 {
812 meshShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
813 shaderCreateInfos.push_back(meshShaderCreateInfo);
814 }
815 else if (m_params.shaders.mesh == UNLINKED)
816 {
817 vk.createShadersEXT(device, 1, &meshShaderCreateInfo, DE_NULL, &meshShader);
818 }
819
820 vk::VkShaderCreateInfoEXT fragShaderCreateInfo = {
821 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
822 DE_NULL, // const void* pNext;
823 0u, // VkShaderCreateFlagsEXT flags;
824 vk::VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
825 getNextStage(vk::VK_SHADER_STAGE_FRAGMENT_BIT), // VkShaderStageFlags nextStage;
826 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType;
827 frag.getSize(), // size_t codeSize;
828 frag.getBinary(), // const void* pCode;
829 "main", // const char* pName;
830 1u, // uint32_t setLayoutCount;
831 &*descriptorSetLayout, // VkDescriptorSetLayout* pSetLayouts;
832 0u, // uint32_t pushConstantRangeCount;
833 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
834 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
835 };
836
837 if (m_params.shaders.fragment == LINKED)
838 {
839 fragShaderCreateInfo.flags = vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
840 shaderCreateInfos.push_back(fragShaderCreateInfo);
841 }
842 else if (m_params.shaders.fragment == UNLINKED)
843 {
844 vk.createShadersEXT(device, 1, &fragShaderCreateInfo, DE_NULL, &fragShader);
845 }
846
847 if (!shaderCreateInfos.empty())
848 {
849 std::vector<vk::VkShaderEXT> shaders(shaderCreateInfos.size());
850 uint32_t i = 0u;
851 uint32_t j = 0u;
852 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
853 {
854 de::Random random(102030);
855 i = random.getUint32() % (uint32_t)shaders.size();
856 do
857 {
858 j = random.getUint32() % (uint32_t)shaders.size();
859 } while (i == j);
860 std::swap(shaderCreateInfos[i], shaderCreateInfos[j]);
861 }
862 vk.createShadersEXT(device, (uint32_t)shaders.size(), &shaderCreateInfos[0], DE_NULL, &shaders[0]);
863 if (m_params.randomOrder && shaderCreateInfos.size() > 1)
864 {
865 std::swap(shaders[i], shaders[j]);
866 }
867 uint32_t n = 0;
868 if (m_params.shaders.task == LINKED)
869 {
870 taskShader = shaders[n++];
871 }
872 if (m_params.shaders.mesh == LINKED)
873 {
874 meshShader = shaders[n++];
875 }
876 if (m_params.shaders.fragment == LINKED)
877 {
878 fragShader = shaders[n++];
879 }
880 }
881
882 const vk::VkCommandPoolCreateInfo cmdPoolInfo = {
883 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
884 DE_NULL, // pNext
885 vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
886 queueFamilyIndex, // queuefamilyindex
887 };
888
889 const vk::Move<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolInfo));
890 const vk::Move<vk::VkCommandBuffer> cmdBuffer(
891 allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
892
893 // Draw
894 vk::beginCommandBuffer(vk, *cmdBuffer);
895
896 vk::VkImageMemoryBarrier preImageBarrier = {
897 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
898 DE_NULL, // const void* pNext
899 vk::VK_ACCESS_NONE, // VkAccessFlags srcAccessMask
900 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
901 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
902 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
903 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
904 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
905 **image, // VkImage image
906 {
907 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
908 0u, // uint32_t baseMipLevel
909 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
910 0u, // uint32_t baseArray
911 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
912 }};
913
914 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
915 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u,
916 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
917 &preImageBarrier);
918
919 const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
920 vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
921 vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
922 vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
923 true);
924 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1,
925 &descriptorSet.get(), 0, DE_NULL);
926
927 bindNullRasterizationShaders(vk, *cmdBuffer, m_context.getDeviceFeatures());
928 vk::VkShaderStageFlagBits stages[] = {
929 vk::VK_SHADER_STAGE_TASK_BIT_EXT,
930 vk::VK_SHADER_STAGE_MESH_BIT_EXT,
931 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
932 };
933 vk::VkShaderEXT shaders[] = {
934 m_params.shaders.task != UNUSED ? taskShader : VK_NULL_HANDLE,
935 m_params.shaders.mesh != UNUSED ? meshShader : VK_NULL_HANDLE,
936 m_params.shaders.fragment != UNUSED ? fragShader : VK_NULL_HANDLE,
937 };
938 vk.cmdBindShadersEXT(*cmdBuffer, 3, stages, shaders);
939
940 vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
941
942 vk::endRendering(vk, *cmdBuffer);
943
944 vk::VkImageMemoryBarrier postImageBarrier = {
945 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
946 DE_NULL, // const void* pNext
947 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
948 vk::VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
949 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
950 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
951 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
952 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
953 **image, // VkImage image
954 {
955 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
956 0u, // uint32_t baseMipLevel
957 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
958 0u, // uint32_t baseArray
959 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
960 }};
961
962 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
963 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
964 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
965 &postImageBarrier);
966
967 const vk::VkBufferImageCopy copyRegion = {
968 0u, // VkDeviceSize bufferOffset;
969 0u, // uint32_t bufferRowLength;
970 0u, // uint32_t bufferImageHeight;
971 {
972 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
973 0u, // uint32_t mipLevel;
974 0u, // uint32_t baseArrayLayer;
975 1u, // uint32_t layerCount;
976 }, // VkImageSubresourceLayers imageSubresource;
977 {0, 0, 0}, // VkOffset3D imageOffset;
978 {renderArea.extent.width, renderArea.extent.height, 1} // VkExtent3D imageExtent;
979 };
980 vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, ©Region);
981
982 vk::endCommandBuffer(vk, *cmdBuffer);
983
984 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
985
986 // Cleanup
987 if (m_params.shaders.task != UNUSED)
988 vk.destroyShaderEXT(device, taskShader, DE_NULL);
989
990 if (m_params.shaders.mesh != UNUSED)
991 vk.destroyShaderEXT(device, meshShader, DE_NULL);
992
993 if (m_params.shaders.fragment != UNUSED)
994 vk.destroyShaderEXT(device, fragShader, DE_NULL);
995
996 if (m_params.shaders.fragment != UNUSED)
997 {
998 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
999 vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1,
1000 (const void *)colorOutputBuffer->getAllocation().getHostPtr());
1001
1002 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1003 const int32_t width = resultBuffer.getWidth();
1004 const int32_t height = resultBuffer.getHeight();
1005
1006 for (int32_t j = 0; j < height; ++j)
1007 {
1008 for (int32_t i = 0; i < width; ++i)
1009 {
1010 const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
1011 if (color != white)
1012 {
1013 log << tcu::TestLog::Message << "Color at (" << i << ", " << j
1014 << ") is expected to be (1.0, 1.0, 1.0, 1.0), but was (" << color << ")"
1015 << tcu::TestLog::EndMessage;
1016 return tcu::TestStatus::fail("Fail");
1017 }
1018 }
1019 }
1020 }
1021 if (m_params.shaders.mesh != UNUSED)
1022 {
1023 const vk::Allocation &outputBufferAllocation = outputBuffer.getAllocation();
1024 invalidateAlloc(vk, device, outputBufferAllocation);
1025
1026 const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
1027
1028 if (bufferPtr[0] != 0u || bufferPtr[1] != 1u || bufferPtr[2] != 2u || bufferPtr[3] != 3u)
1029 {
1030 log << tcu::TestLog::Message << "Buffer values were expected to be [0, 1, 2, 3], but were[" << bufferPtr[0]
1031 << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", "
1032 << "]" << tcu::TestLog::EndMessage;
1033 return tcu::TestStatus::fail("Fail");
1034 }
1035 }
1036
1037 return tcu::TestStatus::pass("Pass");
1038 }
1039
1040 class MeshShaderObjectLinkCase : public vkt::TestCase
1041 {
1042 public:
MeshShaderObjectLinkCase(tcu::TestContext & testCtx,const std::string & name,const MeshParams & params)1043 MeshShaderObjectLinkCase(tcu::TestContext &testCtx, const std::string &name, const MeshParams ¶ms)
1044 : vkt::TestCase(testCtx, name)
1045 , m_params(params)
1046 {
1047 }
~MeshShaderObjectLinkCase(void)1048 virtual ~MeshShaderObjectLinkCase(void)
1049 {
1050 }
1051
1052 void checkSupport(vkt::Context &context) const override;
1053 virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1054 TestInstance *createInstance(Context &context) const override
1055 {
1056 return new MeshShaderObjectLinkInstance(context, m_params);
1057 }
1058
1059 private:
1060 MeshParams m_params;
1061 };
1062
initPrograms(vk::SourceCollections & programCollection) const1063 void MeshShaderObjectLinkCase::initPrograms(vk::SourceCollections &programCollection) const
1064 {
1065 std::stringstream task;
1066 std::stringstream mesh;
1067 std::stringstream frag;
1068
1069 task << "#version 450\n"
1070 << "#extension GL_EXT_mesh_shader : enable\n"
1071 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1072 << "void main ()\n"
1073 << "{\n"
1074 << " EmitMeshTasksEXT(1u, 1u, 1u);\n"
1075 << "}\n";
1076
1077 mesh << "#version 460\n"
1078 << "#extension GL_EXT_mesh_shader : require\n"
1079 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1080 << "layout(max_vertices = 3) out;\n"
1081 << "layout(max_primitives = 1) out;\n"
1082 << "layout(triangles) out;\n"
1083 << "layout(set = 0, binding = 0) buffer Output {\n"
1084 << " uint values[4];\n"
1085 << "} buffer_out;\n\n"
1086 << "void main() {\n"
1087 << " SetMeshOutputsEXT(3, 1);\n"
1088 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1089 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1090 << " gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0, 3.0, 0.0f, 1.0f);\n"
1091 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1092 << " buffer_out.values[0] = 0u;\n"
1093 << " buffer_out.values[1] = 1u;\n"
1094 << " buffer_out.values[2] = 2u;\n"
1095 << " buffer_out.values[3] = 3u;\n"
1096 << "}\n";
1097
1098 frag << "#version 450\n"
1099 << "layout (location=0) out vec4 outColor;\n"
1100 << "void main() {\n"
1101 << " outColor = vec4(1.0f);\n"
1102 << "}\n";
1103
1104 programCollection.glslSources.add("task")
1105 << glu::TaskSource(task.str())
1106 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1107 programCollection.glslSources.add("mesh")
1108 << glu::MeshSource(mesh.str())
1109 << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1110 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1111 }
1112
checkSupport(Context & context) const1113 void MeshShaderObjectLinkCase::checkSupport(Context &context) const
1114 {
1115 context.requireDeviceFunctionality("VK_EXT_shader_object");
1116
1117 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1118 const auto &features = context.getMeshShaderFeaturesEXT();
1119 if (!features.taskShader)
1120 TCU_THROW(NotSupportedError, "Task shaders not supported");
1121 if (!features.meshShader)
1122 TCU_THROW(NotSupportedError, "Mesh shaders not supported");
1123 }
1124
typeToString(ShaderType type)1125 std::string typeToString(ShaderType type)
1126 {
1127 if (type == UNUSED)
1128 return "unused";
1129
1130 if (type == LINKED)
1131 return "linked";
1132
1133 if (type == UNLINKED)
1134 return "unlinked";
1135
1136 return {};
1137 }
1138
1139 } // namespace
1140
createShaderObjectLinkTests(tcu::TestContext & testCtx)1141 tcu::TestCaseGroup *createShaderObjectLinkTests(tcu::TestContext &testCtx)
1142 {
1143 de::MovePtr<tcu::TestCaseGroup> linkGroup(new tcu::TestCaseGroup(testCtx, "link"));
1144
1145 const Shaders shaderTests[] = {
1146 {
1147 LINKED,
1148 LINKED,
1149 UNLINKED,
1150 UNUSED,
1151 UNLINKED,
1152 },
1153 {
1154 LINKED,
1155 LINKED,
1156 LINKED,
1157 UNUSED,
1158 UNLINKED,
1159 },
1160 {
1161 LINKED,
1162 LINKED,
1163 LINKED,
1164 LINKED,
1165 UNLINKED,
1166 },
1167 {
1168 LINKED,
1169 LINKED,
1170 LINKED,
1171 LINKED,
1172 LINKED,
1173 },
1174 {
1175 LINKED,
1176 UNUSED,
1177 UNUSED,
1178 LINKED,
1179 UNLINKED,
1180 },
1181 {
1182 LINKED,
1183 UNUSED,
1184 UNUSED,
1185 LINKED,
1186 LINKED,
1187 },
1188 {
1189 LINKED,
1190 UNUSED,
1191 UNUSED,
1192 UNUSED,
1193 LINKED,
1194 },
1195 {UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED},
1196 {UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED},
1197 {UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED},
1198 {UNLINKED, LINKED, LINKED, UNUSED, UNLINKED},
1199 {UNLINKED, LINKED, LINKED, LINKED, UNLINKED},
1200 {UNLINKED, LINKED, LINKED, UNUSED, LINKED},
1201 {UNLINKED, LINKED, LINKED, LINKED, LINKED},
1202 {UNLINKED, UNUSED, UNUSED, LINKED, LINKED},
1203 };
1204
1205 const bool randomOrderTests[] = {
1206 false,
1207 true,
1208 };
1209
1210 const struct
1211 {
1212 BindType bindType;
1213 const char *name;
1214 } bindTypeTests[] = {
1215 {SEPARATE, "separate"},
1216 {ONE_LINKED_UNLINKED, "one_linked_unlinked"},
1217 {ALL, "all"},
1218 };
1219
1220 for (const auto &shaders : shaderTests)
1221 {
1222 std::string shadersName = "";
1223 shadersName += typeToString(shaders.vertex) + "_";
1224 shadersName += typeToString(shaders.tesellation_control) + "_";
1225 shadersName += typeToString(shaders.tesellation_evaluation) + "_";
1226 shadersName += typeToString(shaders.geometry) + "_";
1227 shadersName += typeToString(shaders.fragment);
1228 de::MovePtr<tcu::TestCaseGroup> shadersGroup(new tcu::TestCaseGroup(testCtx, shadersName.c_str()));
1229
1230 for (const auto &bindType : bindTypeTests)
1231 {
1232 de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, bindType.name));
1233 for (const auto &randomOrder : randomOrderTests)
1234 {
1235 NextStages nextStages = {};
1236 if (shaders.tesellation_control != UNUSED)
1237 {
1238 nextStages.vertNextStage |= vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1239 nextStages.tescNextStage |= vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1240 }
1241 if (shaders.geometry != UNUSED)
1242 {
1243 nextStages.vertNextStage |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1244 nextStages.teseNextStage |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1245 }
1246 if (shaders.fragment != UNUSED)
1247 {
1248 nextStages.vertNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1249 nextStages.teseNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1250 nextStages.geomNextStage |= vk::VK_SHADER_STAGE_FRAGMENT_BIT;
1251 }
1252
1253 TestParams params = {
1254 shaders, // Shaders shaders;
1255 randomOrder, // bool randomOrder;
1256 nextStages, // NextStages nextStages;
1257 false, // bool separateLinked;
1258 bindType.bindType, // bool separateBind;
1259 };
1260
1261 std::string randomOrderName = randomOrder ? "random_order" : "default";
1262
1263 bindGroup->addChild(new ShaderObjectLinkCase(testCtx, randomOrderName, params));
1264 }
1265
1266 if (shaders.vertex == LINKED || shaders.tesellation_control == LINKED ||
1267 shaders.tesellation_evaluation == LINKED || shaders.geometry == LINKED || shaders.fragment == LINKED)
1268 {
1269 TestParams params = {
1270 shaders, // Shaders shaders;
1271 false, // bool randomOrder;
1272 {
1273 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT |
1274 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1275 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1276 vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1277 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1278 }, // NextStages nextStages;
1279 true, // bool separateLinked;
1280 ALL, // BindType separateBind
1281 };
1282
1283 bindGroup->addChild(new ShaderObjectLinkCase(testCtx, "separate_link", params));
1284 }
1285 shadersGroup->addChild(bindGroup.release());
1286 }
1287 linkGroup->addChild(shadersGroup.release());
1288 }
1289
1290 const struct
1291 {
1292 Shaders shaders;
1293 NextStages nextStages;
1294 const char *name;
1295 } nextStageTests[] = {
1296 {{UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED},
1297 {
1298 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1299 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1300 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1301 0u,
1302 },
1303 "vert_t"},
1304 {{UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED},
1305 {
1306 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1307 0u,
1308 0u,
1309 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1310 },
1311 "vert_g"},
1312 {{UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED},
1313 {
1314 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1315 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1316 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1317 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1318 },
1319 "vert_tg"},
1320 {{UNLINKED, UNUSED, UNUSED, UNUSED, UNLINKED},
1321 {
1322 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1323 0u,
1324 0u,
1325 0u,
1326 },
1327 "vert_f"},
1328 {{UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED},
1329 {
1330 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1331 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1332 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1333 0u,
1334 },
1335 "vert_tf"},
1336 {{UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED},
1337 {
1338 vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1339 0u,
1340 0u,
1341 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1342 },
1343 "vert_gf"},
1344 {{UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED},
1345 {
1346 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT |
1347 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1348 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1349 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1350 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1351 },
1352 "vert_tgf"},
1353 {{UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED},
1354 {
1355 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1356 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1357 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1358 0u,
1359 },
1360 "tesc_t"},
1361 {{UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED},
1362 {
1363 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1364 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1365 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1366 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1367 },
1368 "tese_g"},
1369 {{UNLINKED, UNLINKED, UNLINKED, UNUSED, UNLINKED},
1370 {
1371 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1372 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1373 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1374 0u,
1375 },
1376 "tese_f"},
1377 {{UNLINKED, UNLINKED, UNLINKED, UNLINKED, UNLINKED},
1378 {
1379 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1380 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1381 vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1382 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1383 },
1384 "tese_gf"},
1385 {{UNLINKED, UNUSED, UNUSED, UNLINKED, UNLINKED},
1386 {
1387 vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1388 0u,
1389 0u,
1390 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1391 },
1392 "geom_f"},
1393 };
1394
1395 de::MovePtr<tcu::TestCaseGroup> nextStageGroup(new tcu::TestCaseGroup(testCtx, "next_stage"));
1396 for (const auto &nextStage : nextStageTests)
1397 {
1398 TestParams params = {
1399 nextStage.shaders, false, nextStage.nextStages, false, ALL,
1400 };
1401 nextStageGroup->addChild(new ShaderObjectLinkCase(testCtx, nextStage.name, params));
1402 }
1403 linkGroup->addChild(nextStageGroup.release());
1404
1405 const MeshShaders meshShaderTests[] = {
1406 {
1407 UNLINKED,
1408 UNLINKED,
1409 UNLINKED,
1410 },
1411 {
1412 UNLINKED,
1413 UNLINKED,
1414 UNUSED,
1415 },
1416 {
1417 LINKED,
1418 LINKED,
1419 UNLINKED,
1420 },
1421 {
1422 UNLINKED,
1423 LINKED,
1424 LINKED,
1425 },
1426 {
1427 LINKED,
1428 LINKED,
1429 LINKED,
1430 },
1431 };
1432
1433 for (const auto &meshShaders : meshShaderTests)
1434 {
1435 std::string name = "mesh_";
1436 name += typeToString(meshShaders.task) + "_";
1437 name += typeToString(meshShaders.mesh) + "_";
1438 name += typeToString(meshShaders.fragment);
1439 de::MovePtr<tcu::TestCaseGroup> meshGroup(new tcu::TestCaseGroup(testCtx, name.c_str()));
1440
1441 for (const auto &randomOrder : randomOrderTests)
1442 {
1443 MeshParams params = {
1444 meshShaders,
1445 randomOrder,
1446 {
1447 0u,
1448 0u,
1449 },
1450 };
1451
1452 std::string randomOrderName = (randomOrder) ? "random_order" : "default";
1453
1454 meshGroup->addChild(new MeshShaderObjectLinkCase(testCtx, randomOrderName, params));
1455 }
1456 linkGroup->addChild(meshGroup.release());
1457 }
1458
1459 const struct
1460 {
1461 MeshNextStages nextStages;
1462 const char *name;
1463 } meshNextStageTests[] = {
1464 {{
1465 vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1466 0u,
1467 },
1468 "mesh"},
1469 {{
1470 0u,
1471 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1472 },
1473 "frag"},
1474 };
1475
1476 de::MovePtr<tcu::TestCaseGroup> meshNextStageGroup(new tcu::TestCaseGroup(testCtx, "meshnext_stage"));
1477 for (const auto &meshNextStage : meshNextStageTests)
1478 {
1479 MeshParams params = {
1480 {UNLINKED, UNLINKED, UNLINKED},
1481 false,
1482 meshNextStage.nextStages,
1483 };
1484 meshNextStageGroup->addChild(new MeshShaderObjectLinkCase(testCtx, meshNextStage.name, params));
1485 }
1486 linkGroup->addChild(meshNextStageGroup.release());
1487
1488 return linkGroup.release();
1489 }
1490
1491 } // namespace ShaderObject
1492 } // namespace vkt
1493