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 &params) : 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, &copyRegion);
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 &params)
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 &params)
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, &copyRegion);
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 &params)
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