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 Binding Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectBindingTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkShaderObjectUtil.hpp"
30 #include "vktShaderObjectCreateUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkBufferWithMemory.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "deMath.h"
40 #include "vktCustomInstancesDevices.hpp"
41 #include "tcuCommandLine.hpp"
42 #include "vkBuilderUtil.hpp"
43 
44 namespace vkt
45 {
46 namespace ShaderObject
47 {
48 
49 namespace
50 {
51 
52 enum TestType
53 {
54     PASSTHROUGH_GEOM,
55     SWAP,
56     DISABLED,
57     UNBIND,
58     DRAW_DISPATCH_DRAW,
59     DISPATCH_DRAW_DISPATCH,
60 };
61 
62 struct BindingDrawParams
63 {
64     TestType testType;
65     vk::VkShaderStageFlagBits stage;
66     vk::VkShaderStageFlagBits unusedOutputs;
67     vk::VkShaderStageFlagBits binaryStage;
68     bool bindUnsupported;
69     bool setStateAfter;
70     bool unbindWithNullpShaders;
71 };
72 
73 struct MeshBindingDrawParams
74 {
75     vk::VkShaderStageFlagBits stage;
76 };
77 
78 struct BindingParams
79 {
80     bool useMeshShaders;
81 };
82 
83 class ShaderObjectBindingDrawInstance : public vkt::TestInstance
84 {
85 public:
ShaderObjectBindingDrawInstance(Context & context,const BindingDrawParams & params)86     ShaderObjectBindingDrawInstance(Context &context, const BindingDrawParams &params)
87         : vkt::TestInstance(context)
88         , m_params(params)
89     {
90     }
~ShaderObjectBindingDrawInstance(void)91     virtual ~ShaderObjectBindingDrawInstance(void)
92     {
93     }
94 
95     tcu::TestStatus iterate(void) override;
96 
97 private:
98     vk::Move<vk::VkShaderEXT> createShader(const vk::DeviceInterface &vk, const vk::VkDevice device,
99                                            vk::VkShaderStageFlagBits stage, const std::string &name,
100                                            const vk::VkDescriptorSetLayout *descriptorSetLayout = DE_NULL);
101     void createDevice(void);
getDevice(void)102     vk::VkDevice getDevice(void)
103     {
104         return (m_params.testType == DISABLED) ? m_customDevice.get() : m_context.getDevice();
105     }
106     void setDynamicStates(vk::VkCommandBuffer cmdBuffer, bool tessShader);
107 
108     BindingDrawParams m_params;
109     vk::Move<vk::VkDevice> m_customDevice;
110 };
111 
createDevice(void)112 void ShaderObjectBindingDrawInstance::createDevice(void)
113 {
114     if (m_params.testType != DISABLED)
115         return;
116 
117     const float queuePriority    = 1.0f;
118     const auto &deviceExtensions = m_context.getDeviceCreationExtensions();
119     auto features2               = m_context.getDeviceFeatures2();
120 
121     if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
122         features2.features.geometryShader = VK_FALSE;
123     else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
124         features2.features.tessellationShader = VK_FALSE;
125 
126     vk::VkDeviceQueueCreateInfo queueInfo = {
127         vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
128         DE_NULL,                                        // const void* pNext;
129         0u,                                             // VkDeviceQueueCreateFlags flags;
130         0u,                                             // uint32_t queueFamilyIndex;
131         1u,                                             // uint32_t queueCount;
132         &queuePriority                                  // const float* pQueuePriorities;
133     };
134 
135     const vk::VkDeviceCreateInfo deviceInfo = {
136         vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
137         &features2,                               // const void* pNext;
138         (vk::VkDeviceCreateFlags)0,               // VkDeviceCreateFlags flags;
139         1u,                                       // uint32_t queueCreateInfoCount;
140         &queueInfo,                               // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
141         0u,                                       // uint32_t enabledLayerCount;
142         DE_NULL,                                  // const char* const* ppEnabledLayerNames;
143         uint32_t(deviceExtensions.size()),        // uint32_t enabledExtensionCount;
144         (deviceExtensions.empty()) ? DE_NULL : deviceExtensions.data(), // const char* const* ppEnabledExtensionNames;
145         DE_NULL // const VkPhysicalDeviceFeatures* pEnabledFeatures;
146     };
147 
148     m_customDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
149                                         m_context.getPlatformInterface(), m_context.getInstance(),
150                                         m_context.getInstanceInterface(), m_context.getPhysicalDevice(), &deviceInfo);
151 }
152 
createShader(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::VkShaderStageFlagBits stage,const std::string & name,const vk::VkDescriptorSetLayout * descriptorSetLayout)153 vk::Move<vk::VkShaderEXT> ShaderObjectBindingDrawInstance::createShader(
154     const vk::DeviceInterface &vk, const vk::VkDevice device, vk::VkShaderStageFlagBits stage, const std::string &name,
155     const vk::VkDescriptorSetLayout *descriptorSetLayout)
156 {
157     const auto &binaries             = m_context.getBinaryCollection();
158     const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
159     const bool geometrySupported     = m_context.getDeviceFeatures().geometryShader;
160 
161     if (m_params.binaryStage == stage)
162     {
163         auto shaderCreateInfo = vk::makeShaderCreateInfo(stage, binaries.get(name), tessellationSupported,
164                                                          geometrySupported, descriptorSetLayout);
165         const auto shader     = vk::createShader(vk, device, shaderCreateInfo);
166 
167         size_t dataSize;
168         vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
169         std::vector<uint8_t> data(dataSize);
170         vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
171 
172         shaderCreateInfo.codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT;
173         shaderCreateInfo.codeSize = dataSize;
174         shaderCreateInfo.pCode    = data.data();
175 
176         return vk::createShader(vk, device, shaderCreateInfo);
177     }
178 
179     return vk::createShader(vk, device,
180                             vk::makeShaderCreateInfo(stage, binaries.get(name), tessellationSupported,
181                                                      geometrySupported, descriptorSetLayout));
182 }
183 
setDynamicStates(vk::VkCommandBuffer cmdBuffer,bool tessShader)184 void ShaderObjectBindingDrawInstance::setDynamicStates(vk::VkCommandBuffer cmdBuffer, bool tessShader)
185 {
186     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
187     const auto deviceExtensions   = vk::removeUnsupportedShaderObjectExtensions(
188         m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
189 
190     const vk::VkPrimitiveTopology topology =
191         tessShader ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
192 
193     vk::setDefaultShaderObjectDynamicStates(vk, cmdBuffer, deviceExtensions, topology, false);
194 
195     vk::VkBool32 colorBlendEnable = VK_TRUE;
196     vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0u, 1u, &colorBlendEnable);
197     vk::VkColorBlendEquationEXT colorBlendEquation = {
198         vk::VK_BLEND_FACTOR_ONE,                 // VkBlendFactor srcColorBlendFactor;
199         vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor;
200         vk::VK_BLEND_OP_ADD,                     // VkBlendOp colorBlendOp;
201         vk::VK_BLEND_FACTOR_ONE,                 // VkBlendFactor srcAlphaBlendFactor;
202         vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor;
203         vk::VK_BLEND_OP_ADD,                     // VkBlendOp alphaBlendOp;
204     };
205     vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0u, 1u, &colorBlendEquation);
206 }
207 
iterate(void)208 tcu::TestStatus ShaderObjectBindingDrawInstance::iterate(void)
209 {
210     const vk::VkInstance instance = m_context.getInstance();
211     const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
212     createDevice();
213     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
214     const vk::VkDevice device       = getDevice();
215     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
216     const vk::VkQueue queue         = getDeviceQueue(m_context.getDeviceInterface(), device, queueFamilyIndex, 0u);
217     auto alloctor                   = de::MovePtr<vk::Allocator>(new vk::SimpleAllocator(
218         vk, device, getPhysicalDeviceMemoryProperties(instanceDriver, m_context.getPhysicalDevice())));
219     auto &alloc                     = *alloctor;
220     tcu::TestLog &log               = m_context.getTestContext().getLog();
221 
222     const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
223     const bool geometrySupported     = m_context.getDeviceFeatures().geometryShader;
224     const bool taskSupported         = m_context.getMeshShaderFeaturesEXT().taskShader;
225     const bool meshSupported         = m_context.getMeshShaderFeaturesEXT().meshShader;
226 
227     vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
228     const auto subresourceRange        = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
229     const auto subresourceLayers       = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
230     const vk::VkRect2D renderArea      = vk::makeRect2D(0, 0, 32, 32);
231     vk::VkExtent3D extent              = {renderArea.extent.width, renderArea.extent.height, 1};
232 
233     const vk::VkImageCreateInfo createInfo = {
234         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
235         DE_NULL,                                 // const void*                pNext
236         0u,                                      // VkImageCreateFlags        flags
237         vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
238         colorAttachmentFormat,                   // VkFormat                    format
239         {32, 32, 1},                             // VkExtent3D                extent
240         1u,                                      // uint32_t                    mipLevels
241         1u,                                      // uint32_t                    arrayLayers
242         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
243         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
244         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
245         vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
246         0,                             // uint32_t                    queueFamilyIndexCount
247         DE_NULL,                       // const uint32_t*            pQueueFamilyIndices
248         vk::VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
249     };
250 
251     de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
252         new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
253     const auto imageView =
254         vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
255 
256     const vk::VkDeviceSize colorOutputBufferSize =
257         renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
258     de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
259         vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
260         vk::MemoryRequirement::HostVisible));
261 
262     const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 16;
263     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
264         vk::DescriptorSetLayoutBuilder()
265             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
266             .build(vk, device));
267 
268     const vk::Unique<vk::VkDescriptorPool> descriptorPool(
269         vk::DescriptorPoolBuilder()
270             .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
271             .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u));
272 
273     const vk::Move<vk::VkCommandPool> cmdPool(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
274     const vk::Move<vk::VkCommandBuffer> cmdBuffer(
275         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
276 
277     const vk::Unique<vk::VkDescriptorSet> descriptorSet1(
278         vk::makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
279     const vk::Unique<vk::VkDescriptorSet> descriptorSet2(
280         vk::makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
281     const vk::BufferWithMemory outputBuffer1(
282         vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
283         vk::MemoryRequirement::HostVisible);
284     const vk::BufferWithMemory outputBuffer2(
285         vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
286         vk::MemoryRequirement::HostVisible);
287 
288     const auto computePipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout.get());
289 
290     const vk::VkDescriptorBufferInfo descriptorInfo1 =
291         vk::makeDescriptorBufferInfo(*outputBuffer1, 0ull, bufferSizeBytes);
292     const vk::VkDescriptorBufferInfo descriptorInfo2 =
293         vk::makeDescriptorBufferInfo(*outputBuffer2, 0ull, bufferSizeBytes);
294     vk::DescriptorSetUpdateBuilder()
295         .writeSingle(*descriptorSet1, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
296                      vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo1)
297         .update(vk, device);
298     vk::DescriptorSetUpdateBuilder()
299         .writeSingle(*descriptorSet2, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
300                      vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo2)
301         .update(vk, device);
302 
303     vk::Move<vk::VkShaderEXT> vertShader;
304     vk::Move<vk::VkShaderEXT> tescShader;
305     vk::Move<vk::VkShaderEXT> teseShader;
306     vk::Move<vk::VkShaderEXT> geomShader;
307     vk::Move<vk::VkShaderEXT> fragShader;
308     vk::Move<vk::VkShaderEXT> compShader;
309     vk::Move<vk::VkShaderEXT> passThroughGeomShader;
310     vk::Move<vk::VkShaderEXT> vertAltShader;
311     vk::Move<vk::VkShaderEXT> tescAltShader;
312     vk::Move<vk::VkShaderEXT> teseAltShader;
313     vk::Move<vk::VkShaderEXT> geomAltShader;
314     vk::Move<vk::VkShaderEXT> fragAltShader;
315 
316     if (tessellationSupported && geometrySupported)
317     {
318         vertShader    = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vert");
319         vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAlt");
320     }
321     else if (tessellationSupported)
322     {
323         vertShader    = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoGeom");
324         vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoGeom");
325     }
326     else if (geometrySupported)
327     {
328         vertShader    = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoTess");
329         vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoTess");
330     }
331     else
332     {
333         vertShader    = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertNoTessGeom");
334         vertAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_VERTEX_BIT, "vertAltNoTessGeom");
335     }
336     if (tessellationSupported &&
337         (m_params.stage != vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_params.testType != DISABLED))
338     {
339         tescShader    = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc");
340         teseShader    = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tese");
341         tescAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tescAlt");
342         teseAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "teseAlt");
343     }
344     if (geometrySupported && (m_params.stage != vk::VK_SHADER_STAGE_GEOMETRY_BIT || m_params.testType != DISABLED))
345     {
346         geomShader            = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom");
347         geomAltShader         = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geomAlt");
348         passThroughGeomShader = createShader(vk, device, vk::VK_SHADER_STAGE_GEOMETRY_BIT, "passThroughGeom");
349     }
350     fragShader    = createShader(vk, device, vk::VK_SHADER_STAGE_FRAGMENT_BIT, "blendFrag");
351     compShader    = createShader(vk, device, vk::VK_SHADER_STAGE_COMPUTE_BIT, "comp", &*descriptorSetLayout);
352     fragAltShader = createShader(vk, device, vk::VK_SHADER_STAGE_FRAGMENT_BIT, "fragAlt");
353 
354     const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 0.0f});
355     vk::beginCommandBuffer(vk, *cmdBuffer);
356 
357     vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(
358         vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
359         vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
360     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
361                           vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u,
362                           (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
363                           &preImageBarrier);
364 
365     if (!m_params.setStateAfter)
366         setDynamicStates(*cmdBuffer, tessellationSupported);
367 
368     vk::VkBool32 colorBlendEnable = VK_TRUE;
369     vk.cmdSetColorBlendEnableEXT(*cmdBuffer, 0u, 1u, &colorBlendEnable);
370     vk::VkColorBlendEquationEXT colorBlendEquation = {
371         vk::VK_BLEND_FACTOR_ONE,                 // VkBlendFactor srcColorBlendFactor;
372         vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor;
373         vk::VK_BLEND_OP_ADD,                     // VkBlendOp colorBlendOp;
374         vk::VK_BLEND_FACTOR_ONE,                 // VkBlendFactor srcAlphaBlendFactor;
375         vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor;
376         vk::VK_BLEND_OP_ADD,                     // VkBlendOp alphaBlendOp;
377     };
378     vk.cmdSetColorBlendEquationEXT(*cmdBuffer, 0u, 1u, &colorBlendEquation);
379 
380     if (m_params.testType != DISPATCH_DRAW_DISPATCH)
381         vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
382                            vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
383 
384     vk::VkShaderEXT nullShader = VK_NULL_HANDLE;
385 
386     if (m_params.testType == PASSTHROUGH_GEOM)
387     {
388         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *passThroughGeomShader,
389                                 *fragShader, taskSupported, meshSupported);
390         if (m_params.setStateAfter)
391             setDynamicStates(*cmdBuffer, tessellationSupported);
392         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
393         vk::VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
394         vk.cmdBindShadersEXT(*cmdBuffer, 1u, &geomStage, &nullShader);
395         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
396     }
397     else if (m_params.testType == SWAP)
398     {
399         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
400                                 taskSupported, meshSupported);
401         if (m_params.setStateAfter)
402             setDynamicStates(*cmdBuffer, tessellationSupported);
403         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
404         vk::VkShaderEXT shader = VK_NULL_HANDLE;
405         if (m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
406             shader = *vertAltShader;
407         else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
408             shader = *tescAltShader;
409         else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
410             shader = *teseAltShader;
411         else if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
412             shader = *geomAltShader;
413         else if (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
414             shader = *fragAltShader;
415         vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &shader);
416         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
417     }
418     else if (m_params.testType == DISABLED)
419     {
420         if (taskSupported)
421         {
422             vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
423             vk::VkShaderEXT shader          = VK_NULL_HANDLE;
424             vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
425         }
426         if (meshSupported)
427         {
428             vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_MESH_BIT_EXT;
429             vk::VkShaderEXT shader          = VK_NULL_HANDLE;
430             vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
431         }
432         if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
433         {
434             vk::VkShaderStageFlagBits stages[] = {
435                 vk::VK_SHADER_STAGE_VERTEX_BIT, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
436                 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, vk::VK_SHADER_STAGE_FRAGMENT_BIT};
437             vk::VkShaderEXT shaders[] = {*vertShader, *tescShader, *teseShader, *fragShader};
438             vk.cmdBindShadersEXT(*cmdBuffer, 4u, stages, shaders);
439             if (m_params.bindUnsupported)
440                 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
441             if (m_params.setStateAfter)
442                 setDynamicStates(*cmdBuffer, tessellationSupported);
443             vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
444         }
445         else
446         {
447             vk.cmdSetPrimitiveTopology(*cmdBuffer, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
448             vk::VkShaderStageFlagBits stages[] = {vk::VK_SHADER_STAGE_VERTEX_BIT, vk::VK_SHADER_STAGE_GEOMETRY_BIT,
449                                                   vk::VK_SHADER_STAGE_FRAGMENT_BIT};
450             vk::VkShaderEXT shaders[]          = {*vertShader, *geomShader, *fragShader};
451             vk.cmdBindShadersEXT(*cmdBuffer, 3u, stages, shaders);
452             if (m_params.bindUnsupported)
453                 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
454             if (m_params.setStateAfter)
455                 setDynamicStates(*cmdBuffer, tessellationSupported);
456             vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
457         }
458     }
459     else if (m_params.testType == UNBIND)
460     {
461         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
462                                 taskSupported, meshSupported);
463         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
464         if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
465         {
466             if (m_params.unbindWithNullpShaders)
467                 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, DE_NULL);
468             else
469                 vk.cmdBindShadersEXT(*cmdBuffer, 1u, &m_params.stage, &nullShader);
470         }
471         else
472         {
473             vk::VkShaderStageFlagBits stages[] = {vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
474                                                   vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT};
475             vk::VkShaderEXT nullShaders[]      = {VK_NULL_HANDLE, VK_NULL_HANDLE};
476             vk.cmdSetPrimitiveTopology(*cmdBuffer, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
477             if (m_params.unbindWithNullpShaders)
478                 vk.cmdBindShadersEXT(*cmdBuffer, 2u, stages, DE_NULL);
479             else
480                 vk.cmdBindShadersEXT(*cmdBuffer, 2u, stages, nullShaders);
481         }
482         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
483     }
484     else if (m_params.testType == DRAW_DISPATCH_DRAW)
485     {
486         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
487                                 taskSupported, meshSupported);
488         if (m_params.setStateAfter)
489             setDynamicStates(*cmdBuffer, tessellationSupported);
490         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
491         vk::VkShaderStageFlagBits computeStage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
492         vk.cmdBindShadersEXT(*cmdBuffer, 1u, &computeStage, &*compShader);
493         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
494     }
495     else if (m_params.testType == DISPATCH_DRAW_DISPATCH)
496     {
497         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1,
498                                  &descriptorSet1.get(), 0, DE_NULL);
499         vk::VkShaderStageFlagBits computeStage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
500         vk.cmdBindShadersEXT(*cmdBuffer, 1u, &computeStage, &*compShader);
501         vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
502         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, *tescShader, *teseShader, *geomShader, *fragShader,
503                                 taskSupported, meshSupported);
504         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1,
505                                  &descriptorSet2.get(), 0, DE_NULL);
506         vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
507     }
508 
509     if (m_params.testType != DISPATCH_DRAW_DISPATCH)
510         vk::endRendering(vk, *cmdBuffer);
511 
512     vk::VkImageMemoryBarrier postImageBarrier =
513         vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
514                                    vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
515     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
516                           vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
517                           (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
518                           &postImageBarrier);
519 
520     const vk::VkBufferImageCopy copyRegion = vk::makeBufferImageCopy(extent, subresourceLayers);
521     vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, &copyRegion);
522 
523     vk::endCommandBuffer(vk, *cmdBuffer);
524 
525     vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
526 
527     tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
528         vk::mapVkFormat(colorAttachmentFormat), renderArea.extent.width, renderArea.extent.height, 1,
529         (const void *)colorOutputBuffer->getAllocation().getHostPtr());
530 
531     const int32_t width      = resultBuffer.getWidth();
532     const int32_t height     = resultBuffer.getHeight();
533     const float threshold    = 1.0f / 256.0f;
534     int32_t xOffset1         = width / 8;
535     int32_t yOffset1         = height / 8;
536     int32_t xOffset2         = width / 8;
537     int32_t yOffset2         = height / 8;
538     tcu::Vec4 expectedColor1 = tcu::Vec4(0.75f, 0.75f, 0.75f, 0.75f);
539     tcu::Vec4 expectedColor2 = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
540     tcu::Vec4 blackColor     = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
541 
542     if (m_params.testType == PASSTHROUGH_GEOM)
543     {
544         yOffset1 = height / 4;
545         xOffset2 = xOffset1;
546         yOffset2 = yOffset1;
547     }
548     else if (m_params.testType == SWAP)
549     {
550         if (m_params.stage == vk::VK_SHADER_STAGE_VERTEX_BIT)
551         {
552             xOffset2 = 0;
553             yOffset2 = 0;
554         }
555         else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
556         {
557             xOffset2 = 10;
558             yOffset2 = 10;
559         }
560         else if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
561         {
562             xOffset2 = 12;
563             yOffset2 = height / 8;
564         }
565         else if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
566         {
567             xOffset2 = width / 8;
568             yOffset2 = 12;
569         }
570         else if (m_params.stage == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
571         {
572             expectedColor1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
573         }
574     }
575     else if (m_params.testType == DISABLED)
576     {
577         if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
578         {
579             yOffset1 = height / 4;
580             xOffset2 = 16;
581             yOffset2 = 16;
582         }
583         else
584         {
585             xOffset1 = width / 4;
586             xOffset2 = 16;
587             yOffset2 = 16;
588         }
589     }
590     else if (m_params.testType == UNBIND)
591     {
592         if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
593         {
594             xOffset2 = xOffset1;
595             yOffset2 = yOffset1 * 2;
596         }
597         else
598         {
599             xOffset2 = xOffset1 * 2;
600             yOffset2 = yOffset1;
601         }
602     }
603     else if (m_params.testType == DRAW_DISPATCH_DRAW)
604     {
605         xOffset2 = xOffset1;
606         yOffset2 = yOffset1;
607     }
608 
609     if (m_params.testType == DISPATCH_DRAW_DISPATCH)
610     {
611         for (uint32_t i = 0; i < 2; ++i)
612         {
613             const vk::Allocation &outputBufferAllocation =
614                 i == 0 ? outputBuffer1.getAllocation() : outputBuffer2.getAllocation();
615             invalidateAlloc(vk, device, outputBufferAllocation);
616 
617             const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
618 
619             for (uint32_t j = 0; j < 16; ++j)
620             {
621                 if (bufferPtr[j] != j)
622                     return tcu::TestStatus::fail("Fail");
623             }
624         }
625         return tcu::TestStatus::pass("Pass");
626     }
627 
628     for (int32_t j = 0; j < height; ++j)
629     {
630         for (int32_t i = 0; i < width; ++i)
631         {
632             const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
633 
634             bool first              = i >= xOffset1 && i < width - xOffset1 && j >= yOffset1 && j < height - yOffset1;
635             bool second             = i >= xOffset2 && i < width - xOffset2 && j >= yOffset2 && j < height - yOffset2;
636             tcu::Vec4 expectedColor = blackColor;
637             if (first && second)
638                 expectedColor = expectedColor1;
639             else if (first || second)
640                 expectedColor = expectedColor2;
641 
642             if (deFloatAbs(color.x() - expectedColor.x()) > threshold ||
643                 deFloatAbs(color.y() - expectedColor.y()) > threshold ||
644                 deFloatAbs(color.z() - expectedColor.z()) > threshold ||
645                 deFloatAbs(color.w() - expectedColor.w()) > threshold)
646             {
647                 log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be ("
648                     << expectedColor << "), but was (" << color << ")" << tcu::TestLog::EndMessage;
649                 return tcu::TestStatus::fail("Fail");
650             }
651         }
652     }
653 
654     return tcu::TestStatus::pass("Pass");
655 }
656 
657 class ShaderObjectBindingDrawCase : public vkt::TestCase
658 {
659 public:
ShaderObjectBindingDrawCase(tcu::TestContext & testCtx,const std::string & name,const BindingDrawParams & params)660     ShaderObjectBindingDrawCase(tcu::TestContext &testCtx, const std::string &name, const BindingDrawParams &params)
661         : vkt::TestCase(testCtx, name)
662         , m_params(params)
663     {
664     }
~ShaderObjectBindingDrawCase(void)665     virtual ~ShaderObjectBindingDrawCase(void)
666     {
667     }
668 
669     void checkSupport(vkt::Context &context) const override;
670     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const671     TestInstance *createInstance(Context &context) const override
672     {
673         return new ShaderObjectBindingDrawInstance(context, m_params);
674     }
675 
676 private:
677     BindingDrawParams m_params;
678 };
679 
checkSupport(Context & context) const680 void ShaderObjectBindingDrawCase::checkSupport(Context &context) const
681 {
682     context.requireDeviceFunctionality("VK_EXT_shader_object");
683 
684     if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
685         m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ||
686         m_params.binaryStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
687         m_params.binaryStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
688         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
689 
690     if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT || m_params.binaryStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
691         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
692 }
693 
initPrograms(vk::SourceCollections & programCollection) const694 void ShaderObjectBindingDrawCase::initPrograms(vk::SourceCollections &programCollection) const
695 {
696     vk::addBasicShaderObjectShaders(programCollection);
697 
698     std::stringstream passThroughGeom;
699     std::stringstream blendFrag;
700     std::stringstream vertAlt;
701     std::stringstream geomAlt;
702     std::stringstream tescAlt;
703     std::stringstream teseAlt;
704     std::stringstream fragAlt;
705     std::stringstream vertNoTess;
706     std::stringstream vertNoGeom;
707     std::stringstream vertNoTessGeom;
708     std::stringstream vertAltNoTess;
709     std::stringstream vertAltNoGeom;
710     std::stringstream vertAltNoTessGeom;
711 
712     vertNoTess << "#version 450\n"
713                << "void main() {\n"
714                << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
715                << "    gl_Position = vec4((pos.x - 0.5f) * 1.5f, pos.y - 0.5f, 0.0f, 1.0f);\n"
716                << "}\n";
717 
718     vertNoGeom << "#version 450\n"
719                << "void main() {\n"
720                << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
721                << "    gl_Position = vec4(pos.x - 0.5f, (pos.y - 0.5f) * 1.5f, 0.0f, 1.0f);\n"
722                << "}\n";
723 
724     vertNoTessGeom << "#version 450\n"
725                    << "void main() {\n"
726                    << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
727                    << "    gl_Position = vec4((pos - 0.5f) * 1.5f, 0.0f, 1.0f);\n"
728                    << "}\n";
729 
730     passThroughGeom << "#version 450\n"
731                     << "layout(triangles) in;\n"
732                     << "layout(triangle_strip, max_vertices = 4) out;\n"
733                     << "\n"
734                     << "void main(void)\n"
735                     << "{\n"
736                     << "    gl_Position = gl_in[0].gl_Position;\n"
737                     << "    EmitVertex();\n"
738                     << "    gl_Position = gl_in[1].gl_Position;\n"
739                     << "    EmitVertex();\n"
740                     << "    gl_Position = gl_in[2].gl_Position;\n"
741                     << "    EmitVertex();\n"
742                     << "    EndPrimitive();\n"
743                     << "}\n";
744 
745     blendFrag << "#version 450\n"
746               << "layout (location=0) out vec4 outColor;\n"
747               << "void main() {\n"
748               << "    outColor = vec4(0.5f, 0.5f, 0.5f, 0.5f);\n"
749               << "}\n";
750 
751     vertAlt << "#version 450\n";
752     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
753         vertAlt << "layout (location = 0) out vec4 color;\n";
754     vertAlt << "void main() {\n"
755             << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
756             << "    gl_Position = vec4((pos - 0.5f) * 2, 0.0f, 1.0f);\n";
757     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
758         vertAlt << "color = vec4(1.0f);\n";
759     vertAlt << "}\n";
760 
761     vertAltNoTess << "#version 450\n";
762     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
763         vertAltNoTess << "layout (location = 0) out vec4 color;\n";
764     vertAltNoTess << "void main() {\n"
765                   << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
766                   << "    gl_Position = vec4((pos.x - 0.5f) * 2.0f * 1.5f, (pos.y - 0.5f) * 2.0f, 0.0f, 1.0f);\n";
767     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
768         vertAltNoTess << "    color = vec4(1.0f);\n";
769     vertAltNoTess << "}\n";
770 
771     vertAltNoGeom << "#version 450\n";
772     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
773         vertAltNoGeom << "layout (location = 0) out vec4 color;\n";
774     vertAltNoGeom << "void main() {\n"
775                   << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
776                   << "    gl_Position = vec4((pos.x - 0.5f) * 2.0f, (pos.y - 0.5f) * 2.0f * 1.5f, 0.0f, 1.0f);\n";
777     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
778         vertAltNoGeom << "    color = vec4(1.0f);\n";
779     vertAltNoGeom << "}\n";
780 
781     vertAltNoTessGeom << "#version 450\n";
782     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
783         vertAltNoTessGeom << "layout (location = 0) out vec4 color;\n";
784     vertAltNoTessGeom << "void main() {\n"
785                       << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
786                       << "    gl_Position = vec4((pos - 0.5f) * 2 * 1.5f, 0.0f, 1.0f);\n";
787     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_VERTEX_BIT)
788         vertAltNoTessGeom << "    color = vec4(1.0f);\n";
789     vertAltNoTessGeom << "}\n";
790 
791     tescAlt << "#version 450\n"
792             << "\n"
793             << "layout(vertices = 4) out;\n";
794     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
795         tescAlt << "layout (location = 0) out vec4 color[];\n";
796     tescAlt << "\n"
797             << "void main (void)\n"
798             << "{\n"
799             << "    if (gl_InvocationID == 0) {\n"
800             << "        gl_TessLevelInner[0] = 1.0;\n"
801             << "        gl_TessLevelInner[1] = 1.0;\n"
802             << "        gl_TessLevelOuter[0] = 1.0;\n"
803             << "        gl_TessLevelOuter[1] = 1.0;\n"
804             << "        gl_TessLevelOuter[2] = 1.0;\n"
805             << "        gl_TessLevelOuter[3] = 1.0;\n"
806             << "    }\n"
807             << "    vec4 pos = gl_in[gl_InvocationID].gl_Position;\n"
808             << "    pos.xy *= 0.5f;\n"
809             << "    gl_out[gl_InvocationID].gl_Position = pos;\n";
810     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
811         tescAlt << "    color[gl_InvocationID] = vec4(1.0f);\n";
812     tescAlt << "}\n";
813 
814     teseAlt << "#version 450\n"
815             << "\n"
816             << "layout(quads, equal_spacing) in;\n";
817     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
818         teseAlt << "layout (location = 0) out vec4 color;\n";
819     teseAlt << "\n"
820             << "void main (void)\n"
821             << "{\n"
822             << "    float u = gl_TessCoord.x;\n"
823             << "    float v = gl_TessCoord.y;\n"
824             << "    float omu = 1.0f - u;\n"
825             << "    float omv = 1.0f - v;\n"
826             << "    gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * "
827                "gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
828             << "    gl_Position.x *= 0.5f;\n";
829     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
830         teseAlt << "    color = vec4(1.0f);\n";
831     teseAlt << "}\n";
832 
833     geomAlt << "#version 450\n"
834             << "layout(triangles) in;\n"
835             << "layout(triangle_strip, max_vertices = 4) out;\n";
836     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
837         geomAlt << "layout (location = 0) out vec4 color;\n";
838     geomAlt << "\n"
839             << "void main(void)\n"
840             << "{\n"
841             << "    gl_Position = gl_in[0].gl_Position;\n"
842             << "    gl_Position.y *= 0.5f;\n"
843             << "    EmitVertex();\n"
844             << "    gl_Position = gl_in[1].gl_Position;\n"
845             << "    gl_Position.y *= 0.5f;\n"
846             << "    EmitVertex();\n"
847             << "    gl_Position = gl_in[2].gl_Position;\n"
848             << "    gl_Position.y *= 0.5f;\n"
849             << "    EmitVertex();\n"
850             << "    EndPrimitive();\n";
851     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
852         geomAlt << "    color = vec4(1.0f);\n";
853     geomAlt << "}\n";
854 
855     fragAlt << "#version 450\n"
856             << "layout (location=0) out vec4 outColor;\n";
857     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
858         fragAlt << "layout (location = 1) out vec4 color;\n";
859     fragAlt << "void main() {\n"
860             << "    outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
861     if (m_params.unusedOutputs == vk::VK_SHADER_STAGE_FRAGMENT_BIT)
862         fragAlt << "color = vec4(1.0f);\n";
863     fragAlt << "}\n";
864 
865     programCollection.glslSources.add("passThroughGeom") << glu::GeometrySource(passThroughGeom.str());
866     programCollection.glslSources.add("blendFrag") << glu::FragmentSource(blendFrag.str());
867     programCollection.glslSources.add("vertAlt") << glu::VertexSource(vertAlt.str());
868     programCollection.glslSources.add("tescAlt") << glu::TessellationControlSource(tescAlt.str());
869     programCollection.glslSources.add("teseAlt") << glu::TessellationEvaluationSource(teseAlt.str());
870     programCollection.glslSources.add("geomAlt") << glu::GeometrySource(geomAlt.str());
871     programCollection.glslSources.add("fragAlt") << glu::FragmentSource(fragAlt.str());
872 
873     programCollection.glslSources.add("vertNoTess") << glu::VertexSource(vertNoTess.str());
874     programCollection.glslSources.add("vertNoGeom") << glu::VertexSource(vertNoGeom.str());
875     programCollection.glslSources.add("vertNoTessGeom") << glu::VertexSource(vertNoTessGeom.str());
876     programCollection.glslSources.add("vertAltNoTess") << glu::VertexSource(vertAltNoTess.str());
877     programCollection.glslSources.add("vertAltNoGeom") << glu::VertexSource(vertAltNoGeom.str());
878     programCollection.glslSources.add("vertAltNoTessGeom") << glu::VertexSource(vertAltNoTessGeom.str());
879 }
880 
881 class ShaderObjectBindingInstance : public vkt::TestInstance
882 {
883 public:
ShaderObjectBindingInstance(Context & context,const BindingParams & params)884     ShaderObjectBindingInstance(Context &context, const BindingParams &params)
885         : vkt::TestInstance(context)
886         , m_params(params)
887     {
888     }
~ShaderObjectBindingInstance(void)889     virtual ~ShaderObjectBindingInstance(void)
890     {
891     }
892 
893     tcu::TestStatus iterate(void) override;
894 
895 private:
896     BindingParams m_params;
897 };
898 
iterate(void)899 tcu::TestStatus ShaderObjectBindingInstance::iterate(void)
900 {
901     const vk::VkInstance instance = m_context.getInstance();
902     const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
903     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
904     const vk::VkDevice device       = m_context.getDevice();
905     const vk::VkQueue queue         = m_context.getUniversalQueue();
906     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
907 
908     const auto meshShaderFeatures    = m_context.getMeshShaderFeaturesEXT();
909     const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
910     const bool geometrySupported     = m_context.getDeviceFeatures().geometryShader;
911     const auto &binaries             = m_context.getBinaryCollection();
912 
913     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
914         vk::DescriptorSetLayoutBuilder()
915             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
916                               vk::VK_SHADER_STAGE_COMPUTE_BIT |
917                                   ((m_params.useMeshShaders && meshShaderFeatures.meshShader) ?
918                                        vk::VkShaderStageFlags{vk::VK_SHADER_STAGE_MESH_BIT_EXT} :
919                                        vk::VkShaderStageFlags{0}))
920             .build(vk, device));
921 
922     vk::Move<vk::VkShaderEXT> vertShader =
923         vk::createShader(vk, device,
924                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vert"),
925                                                   tessellationSupported, geometrySupported));
926     vk::Move<vk::VkShaderEXT> tescShader;
927     vk::Move<vk::VkShaderEXT> teseShader;
928     vk::Move<vk::VkShaderEXT> geomShader;
929     vk::Move<vk::VkShaderEXT> fragShader =
930         vk::createShader(vk, device,
931                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"),
932                                                   tessellationSupported, geometrySupported));
933     vk::Move<vk::VkShaderEXT> compShader =
934         vk::createShader(vk, device,
935                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_COMPUTE_BIT, binaries.get("comp"),
936                                                   tessellationSupported, geometrySupported, &*descriptorSetLayout));
937     vk::Move<vk::VkShaderEXT> taskShader;
938     vk::Move<vk::VkShaderEXT> meshShader;
939     if (m_context.getDeviceFeatures().tessellationShader)
940     {
941         tescShader =
942             vk::createShader(vk, device,
943                              vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
944                                                       binaries.get("tesc"), tessellationSupported, geometrySupported));
945         teseShader =
946             vk::createShader(vk, device,
947                              vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
948                                                       binaries.get("tese"), tessellationSupported, geometrySupported));
949     }
950     if (m_context.getDeviceFeatures().geometryShader)
951     {
952         geomShader = vk::createShader(vk, device,
953                                       vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, binaries.get("geom"),
954                                                                tessellationSupported, geometrySupported));
955     }
956     if (m_params.useMeshShaders)
957     {
958         if (meshShaderFeatures.taskShader)
959             taskShader =
960                 vk::createShader(vk, device,
961                                  vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task"),
962                                                           tessellationSupported, geometrySupported));
963         if (meshShaderFeatures.meshShader)
964             meshShader = vk::createShader(vk, device,
965                                           vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT,
966                                                                    binaries.get("mesh"), tessellationSupported,
967                                                                    geometrySupported, &*descriptorSetLayout));
968     }
969 
970     const vk::Move<vk::VkCommandPool> cmdPool(
971         vk::createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
972     const vk::Move<vk::VkCommandBuffer> cmdBuffer(
973         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
974 
975     const bool bind[] = {true, false};
976     for (const auto bindVert : bind)
977     {
978         for (const auto bindTesc : bind)
979         {
980             for (const auto bindTese : bind)
981             {
982                 for (const auto bindGeom : bind)
983                 {
984                     for (const auto bindFrag : bind)
985                     {
986                         for (const auto bindComp : bind)
987                         {
988                             for (const auto bindTask : bind)
989                             {
990                                 if (bindVert && bindTask)
991                                     continue;
992                                 for (const auto bindMesh : bind)
993                                 {
994                                     if (bindVert && bindMesh)
995                                         continue;
996                                     std::vector<vk::VkShaderStageFlagBits> stages = {
997                                         vk::VK_SHADER_STAGE_VERTEX_BIT,
998                                         vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
999                                         vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1000                                         vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1001                                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1002                                         vk::VK_SHADER_STAGE_COMPUTE_BIT,
1003                                         vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1004                                         vk::VK_SHADER_STAGE_TASK_BIT_EXT,
1005                                     };
1006                                     std::vector<vk::VkShaderEXT> shaders = {
1007                                         bindVert ? *vertShader : VK_NULL_HANDLE,
1008                                         (bindTesc && m_context.getDeviceFeatures().tessellationShader) ? *tescShader :
1009                                                                                                          VK_NULL_HANDLE,
1010                                         (bindTese && m_context.getDeviceFeatures().tessellationShader) ? *teseShader :
1011                                                                                                          VK_NULL_HANDLE,
1012                                         (bindGeom && m_context.getDeviceFeatures().geometryShader) ? *geomShader :
1013                                                                                                      VK_NULL_HANDLE,
1014                                         bindFrag ? *fragShader : VK_NULL_HANDLE,
1015                                         bindComp ? *compShader : VK_NULL_HANDLE,
1016                                         bindMesh ? *meshShader : VK_NULL_HANDLE,
1017                                         bindTask ? *taskShader : VK_NULL_HANDLE,
1018                                     };
1019                                     uint32_t count = 6u;
1020                                     if (meshShaderFeatures.meshShader)
1021                                         ++count;
1022                                     if (meshShaderFeatures.taskShader)
1023                                         ++count;
1024                                     vk::beginCommandBuffer(vk, *cmdBuffer);
1025                                     vk.cmdBindShadersEXT(*cmdBuffer, count, stages.data(), shaders.data());
1026                                     vk::endCommandBuffer(vk, *cmdBuffer);
1027                                     vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1028                                 }
1029                             }
1030                         }
1031                     }
1032                 }
1033             }
1034         }
1035     }
1036 
1037     if (m_context.getDeviceFeatures().tessellationShader && m_context.getDeviceFeatures().geometryShader &&
1038         meshShaderFeatures.taskShader && meshShaderFeatures.meshShader)
1039     {
1040         std::vector<vk::VkShaderStageFlagBits> stages = {
1041             vk::VK_SHADER_STAGE_VERTEX_BIT,
1042             vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1043             vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1044             vk::VK_SHADER_STAGE_GEOMETRY_BIT,
1045             vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1046             vk::VK_SHADER_STAGE_COMPUTE_BIT,
1047             vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1048             vk::VK_SHADER_STAGE_TASK_BIT_EXT,
1049         };
1050         vk::beginCommandBuffer(vk, *cmdBuffer);
1051         vk.cmdBindShadersEXT(*cmdBuffer, (uint32_t)stages.size(), stages.data(), DE_NULL);
1052         vk::endCommandBuffer(vk, *cmdBuffer);
1053         vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1054     }
1055 
1056     return tcu::TestStatus::pass("pass");
1057 }
1058 
1059 class MeshShaderObjectBindingInstance : public vkt::TestInstance
1060 {
1061 public:
MeshShaderObjectBindingInstance(Context & context,const MeshBindingDrawParams & params)1062     MeshShaderObjectBindingInstance(Context &context, const MeshBindingDrawParams &params)
1063         : vkt::TestInstance(context)
1064         , m_params(params)
1065     {
1066     }
~MeshShaderObjectBindingInstance(void)1067     virtual ~MeshShaderObjectBindingInstance(void)
1068     {
1069     }
1070 
1071     tcu::TestStatus iterate(void) override;
1072 
1073 private:
1074     MeshBindingDrawParams m_params;
1075 };
1076 
iterate(void)1077 tcu::TestStatus MeshShaderObjectBindingInstance::iterate(void)
1078 {
1079     const vk::VkInstance instance = m_context.getInstance();
1080     const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
1081     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
1082     const vk::VkDevice device       = m_context.getDevice();
1083     const vk::VkQueue queue         = m_context.getUniversalQueue();
1084     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1085     auto &alloc                     = m_context.getDefaultAllocator();
1086     tcu::TestLog &log               = m_context.getTestContext().getLog();
1087     const auto deviceExtensions     = vk::removeUnsupportedShaderObjectExtensions(
1088         m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
1089 
1090     vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
1091     const auto subresourceRange        = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1092 
1093     const vk::VkImageCreateInfo createInfo = {
1094         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
1095         DE_NULL,                                 // const void*                pNext
1096         0u,                                      // VkImageCreateFlags        flags
1097         vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
1098         colorAttachmentFormat,                   // VkFormat                    format
1099         {32, 32, 1},                             // VkExtent3D                extent
1100         1u,                                      // uint32_t                    mipLevels
1101         1u,                                      // uint32_t                    arrayLayers
1102         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
1103         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
1104         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
1105         vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
1106         0,                             // uint32_t                    queueFamilyIndexCount
1107         DE_NULL,                       // const uint32_t*            pQueueFamilyIndices
1108         vk::VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
1109     };
1110 
1111     de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
1112         new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
1113     const auto imageView =
1114         vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
1115     const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, 32, 32);
1116 
1117     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
1118         vk::DescriptorSetLayoutBuilder()
1119             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
1120                               vk::VK_SHADER_STAGE_TASK_BIT_EXT | vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1121             .build(vk, device));
1122 
1123     const vk::Unique<vk::VkDescriptorPool> descriptorPool(
1124         vk::DescriptorPoolBuilder()
1125             .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1126             .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1127 
1128     const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 4;
1129     const vk::Unique<vk::VkDescriptorSet> descriptorSet(
1130         makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1131     const vk::BufferWithMemory outputBuffer(
1132         vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
1133         vk::MemoryRequirement::HostVisible);
1134 
1135     const vk::VkDescriptorBufferInfo descriptorInfo =
1136         vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
1137     vk::DescriptorSetUpdateBuilder()
1138         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
1139                      vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1140         .update(vk, device);
1141 
1142     const auto pipelineLayout = makePipelineLayout(vk, device, *descriptorSetLayout);
1143 
1144     const auto &binaries = m_context.getBinaryCollection();
1145     const auto taskShader1 =
1146         vk::createShader(vk, device,
1147                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task1"), false, false,
1148                                                   &*descriptorSetLayout));
1149     const auto taskShader2 =
1150         vk::createShader(vk, device,
1151                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, binaries.get("task2"), false, false,
1152                                                   &*descriptorSetLayout));
1153     const auto meshShader1 =
1154         vk::createShader(vk, device,
1155                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, binaries.get("mesh1"), false, false,
1156                                                   &*descriptorSetLayout));
1157     const auto meshShader2 =
1158         vk::createShader(vk, device,
1159                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, binaries.get("mesh2"), false, false,
1160                                                   &*descriptorSetLayout));
1161     const auto fragShader =
1162         vk::createShader(vk, device,
1163                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("frag"), false, false,
1164                                                   &*descriptorSetLayout));
1165 
1166     const vk::Move<vk::VkCommandPool> cmdPool(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
1167     const vk::Move<vk::VkCommandBuffer> cmdBuffer(
1168         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1169 
1170     const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
1171 
1172     vk::beginCommandBuffer(vk, *cmdBuffer);
1173 
1174     vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(
1175         vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
1176         vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1177     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1178                           vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u,
1179                           (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
1180                           &preImageBarrier);
1181 
1182     vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
1183                        vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
1184     vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1185                                             true);
1186     vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1,
1187                              &descriptorSet.get(), 0, DE_NULL);
1188 
1189     std::vector<vk::VkShaderStageFlagBits> nullStages = {
1190         vk::VK_SHADER_STAGE_VERTEX_BIT,
1191     };
1192     if (m_context.getDeviceFeatures().tessellationShader)
1193     {
1194         nullStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
1195         nullStages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
1196     }
1197     if (m_context.getDeviceFeatures().geometryShader)
1198     {
1199         nullStages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
1200     }
1201     for (const auto &stage : nullStages)
1202     {
1203         vk::VkShaderEXT shader = VK_NULL_HANDLE;
1204         vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stage, &shader);
1205     }
1206 
1207     const vk::VkShaderStageFlagBits stages[] = {
1208         vk::VK_SHADER_STAGE_TASK_BIT_EXT,
1209         vk::VK_SHADER_STAGE_MESH_BIT_EXT,
1210         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
1211     };
1212     vk::VkShaderEXT shaders[] = {
1213         *taskShader1,
1214         *meshShader1,
1215         *fragShader,
1216     };
1217     vk.cmdBindShadersEXT(*cmdBuffer, 3u, stages, shaders);
1218     vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
1219     vk::endRendering(vk, *cmdBuffer);
1220 
1221     vk::VkBufferMemoryBarrier shaderBufferBarrier = vk::makeBufferMemoryBarrier(
1222         vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, *outputBuffer, 0u, bufferSizeBytes);
1223     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1224                           (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier *)DE_NULL, 1u, &shaderBufferBarrier,
1225                           0u, (const vk::VkImageMemoryBarrier *)DE_NULL);
1226 
1227     vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
1228                        vk::VK_ATTACHMENT_LOAD_OP_LOAD);
1229     if (m_params.stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
1230         vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stages[0], &*taskShader2);
1231     else if (m_params.stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1232         vk.cmdBindShadersEXT(*cmdBuffer, 1u, &stages[1], &*meshShader2);
1233     vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1, 1, 1);
1234 
1235     vk::endRendering(vk, *cmdBuffer);
1236 
1237     vk::VkImageMemoryBarrier postImageBarrier =
1238         vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
1239                                    vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1240     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1241                           vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
1242                           (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
1243                           &postImageBarrier);
1244     vk::VkBufferMemoryBarrier bufferBarrier = vk::makeBufferMemoryBarrier(
1245         vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0u, bufferSizeBytes);
1246     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
1247                           (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier *)DE_NULL, 1u, &bufferBarrier, 0u,
1248                           (const vk::VkImageMemoryBarrier *)DE_NULL);
1249     vk::endCommandBuffer(vk, *cmdBuffer);
1250 
1251     submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1252 
1253     const vk::Allocation &outputBufferAllocation = outputBuffer.getAllocation();
1254     invalidateAlloc(vk, device, outputBufferAllocation);
1255 
1256     const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
1257 
1258     if (m_params.stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
1259     {
1260         if (bufferPtr[0] != 4u || bufferPtr[1] != 5u || bufferPtr[2] != 2u || bufferPtr[3] != 3u)
1261         {
1262             log << tcu::TestLog::Message << "Buffer values were expected to be [4, 5, 2, 3], but were[" << bufferPtr[0]
1263                 << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", "
1264                 << "]" << tcu::TestLog::EndMessage;
1265             return tcu::TestStatus::fail("Fail");
1266         }
1267     }
1268     else if (m_params.stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
1269     {
1270         if (bufferPtr[0] != 0u || bufferPtr[1] != 1u || bufferPtr[2] != 6u || bufferPtr[3] != 7u)
1271         {
1272             log << tcu::TestLog::Message << "Buffer values were expected to be [0, 1, 6, 7], but were[" << bufferPtr[0]
1273                 << ", " << bufferPtr[1] << ", " << bufferPtr[2] << ", " << bufferPtr[3] << ", "
1274                 << "]" << tcu::TestLog::EndMessage;
1275             return tcu::TestStatus::fail("Fail");
1276         }
1277     }
1278 
1279     return tcu::TestStatus::pass("pass");
1280 }
1281 
1282 class MeshShaderObjectBindingCase : public vkt::TestCase
1283 {
1284 public:
MeshShaderObjectBindingCase(tcu::TestContext & testCtx,const std::string & name,const MeshBindingDrawParams & params)1285     MeshShaderObjectBindingCase(tcu::TestContext &testCtx, const std::string &name, const MeshBindingDrawParams &params)
1286         : vkt::TestCase(testCtx, name)
1287         , m_params(params)
1288     {
1289     }
~MeshShaderObjectBindingCase(void)1290     virtual ~MeshShaderObjectBindingCase(void)
1291     {
1292     }
1293 
1294     void checkSupport(vkt::Context &context) const override;
1295     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1296     TestInstance *createInstance(Context &context) const override
1297     {
1298         return new MeshShaderObjectBindingInstance(context, m_params);
1299     }
1300 
1301 private:
1302     MeshBindingDrawParams m_params;
1303 };
1304 
checkSupport(vkt::Context & context) const1305 void MeshShaderObjectBindingCase::checkSupport(vkt::Context &context) const
1306 {
1307     context.requireDeviceFunctionality("VK_EXT_shader_object");
1308     context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1309     const auto &features = context.getMeshShaderFeaturesEXT();
1310     if (!features.taskShader)
1311         TCU_THROW(NotSupportedError, "Task shaders not supported");
1312     if (!features.meshShader)
1313         TCU_THROW(NotSupportedError, "Mesh shaders not supported");
1314 }
1315 
initPrograms(vk::SourceCollections & programCollection) const1316 void MeshShaderObjectBindingCase::initPrograms(vk::SourceCollections &programCollection) const
1317 {
1318     std::stringstream task1;
1319     std::stringstream task2;
1320     std::stringstream mesh1;
1321     std::stringstream mesh2;
1322     std::stringstream frag;
1323 
1324     task1 << "#version 450\n"
1325           << "#extension GL_EXT_mesh_shader : enable\n"
1326           << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1327           << "layout(set = 0, binding = 0) buffer Output {\n"
1328           << "    uint values[4];\n"
1329           << "} buffer_out;\n\n"
1330           << "void main ()\n"
1331           << "{\n"
1332           << "    buffer_out.values[0] = 0u;\n"
1333           << "    buffer_out.values[1] = 1u;\n"
1334           << "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
1335           << "}\n";
1336 
1337     task2 << "#version 450\n"
1338           << "#extension GL_EXT_mesh_shader : enable\n"
1339           << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1340           << "layout(set = 0, binding = 0) buffer Output {\n"
1341           << "    uint values[4];\n"
1342           << "} buffer_out;\n\n"
1343           << "void main ()\n"
1344           << "{\n"
1345           << "    buffer_out.values[0] = 4u;\n"
1346           << "    buffer_out.values[1] = 5u;\n"
1347           << "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
1348           << "}\n";
1349 
1350     mesh1 << "#version 460\n"
1351           << "#extension GL_EXT_mesh_shader : require\n"
1352           << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1353           << "layout(max_vertices = 3) out;\n"
1354           << "layout(max_primitives = 1) out;\n"
1355           << "layout(triangles) out;\n"
1356           << "layout(set = 0, binding = 0) buffer Output {\n"
1357           << "    uint values[4];\n"
1358           << "} buffer_out;\n\n"
1359           << "void main() {\n"
1360           << "      SetMeshOutputsEXT(3, 1);\n"
1361           << "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1362           << "      gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1363           << "      gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
1364           << "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1365           << "      buffer_out.values[2] = 2u;\n"
1366           << "      buffer_out.values[3] = 3u;\n"
1367           << "}\n";
1368 
1369     mesh2 << "#version 460\n"
1370           << "#extension GL_EXT_mesh_shader : require\n"
1371           << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1372           << "layout(max_vertices = 3) out;\n"
1373           << "layout(max_primitives = 1) out;\n"
1374           << "layout(triangles) out;\n"
1375           << "layout(set = 0, binding = 0) buffer Output {\n"
1376           << "    uint values[4];\n"
1377           << "} buffer_out;\n\n"
1378           << "void main() {\n"
1379           << "      SetMeshOutputsEXT(3, 1);\n"
1380           << "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1381           << "      gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1382           << "      gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
1383           << "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1384           << "      buffer_out.values[2] = 6u;\n"
1385           << "      buffer_out.values[3] = 7u;\n"
1386           << "}\n";
1387 
1388     frag << "#version 450\n"
1389          << "layout (location=0) out vec4 outColor;\n"
1390          << "void main() {\n"
1391          << "    outColor = vec4(1.0f);\n"
1392          << "}\n";
1393 
1394     programCollection.glslSources.add("task1")
1395         << glu::TaskSource(task1.str())
1396         << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1397     programCollection.glslSources.add("task2")
1398         << glu::TaskSource(task2.str())
1399         << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1400     programCollection.glslSources.add("mesh1")
1401         << glu::MeshSource(mesh1.str())
1402         << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1403     programCollection.glslSources.add("mesh2")
1404         << glu::MeshSource(mesh2.str())
1405         << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1406     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1407 }
1408 
1409 class ShaderObjectBindingCase : public vkt::TestCase
1410 {
1411 public:
ShaderObjectBindingCase(tcu::TestContext & testCtx,const std::string & name,const BindingParams & params)1412     ShaderObjectBindingCase(tcu::TestContext &testCtx, const std::string &name, const BindingParams &params)
1413         : vkt::TestCase(testCtx, name)
1414         , m_params(params)
1415     {
1416     }
~ShaderObjectBindingCase(void)1417     virtual ~ShaderObjectBindingCase(void)
1418     {
1419     }
1420 
1421     void checkSupport(vkt::Context &context) const override;
1422     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1423     TestInstance *createInstance(Context &context) const override
1424     {
1425         return new ShaderObjectBindingInstance(context, m_params);
1426     }
1427 
1428 private:
1429     BindingParams m_params;
1430 };
1431 
checkSupport(Context & context) const1432 void ShaderObjectBindingCase::checkSupport(Context &context) const
1433 {
1434     context.requireDeviceFunctionality("VK_EXT_shader_object");
1435     if (m_params.useMeshShaders)
1436         context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1437 }
1438 
initPrograms(vk::SourceCollections & programCollection) const1439 void ShaderObjectBindingCase::initPrograms(vk::SourceCollections &programCollection) const
1440 {
1441     vk::addBasicShaderObjectShaders(programCollection);
1442 
1443     if (m_params.useMeshShaders)
1444     {
1445         std::stringstream task;
1446         std::stringstream mesh;
1447 
1448         task << "#version 450\n"
1449              << "#extension GL_EXT_mesh_shader : enable\n"
1450              << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1451              << "void main ()\n"
1452              << "{\n"
1453              << "    EmitMeshTasksEXT(1u, 1u, 1u);\n"
1454              << "}\n";
1455 
1456         mesh << "#version 460\n"
1457              << "#extension GL_EXT_mesh_shader : require\n"
1458              << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1459              << "layout(max_vertices = 3) out;\n"
1460              << "layout(max_primitives = 1) out;\n"
1461              << "layout(triangles) out;\n"
1462              << "layout(set = 0, binding = 0) buffer Output {\n"
1463              << "    uint values[4];\n"
1464              << "} buffer_out;\n\n"
1465              << "void main() {\n"
1466              << "      SetMeshOutputsEXT(3, 1);\n"
1467              << "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0.0f, 1.0f);\n"
1468              << "      gl_MeshVerticesEXT[1].gl_Position = vec4( 3.0, -1.0, 0.0f, 1.0f);\n"
1469              << "      gl_MeshVerticesEXT[2].gl_Position = vec4(-1.0,  3.0, 0.0f, 1.0f);\n"
1470              << "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
1471              << "      buffer_out.values[0] = 0u;\n"
1472              << "      buffer_out.values[1] = 1u;\n"
1473              << "      buffer_out.values[2] = 2u;\n"
1474              << "      buffer_out.values[3] = 3u;\n"
1475              << "}\n";
1476 
1477         programCollection.glslSources.add("task")
1478             << glu::TaskSource(task.str())
1479             << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1480         programCollection.glslSources.add("mesh")
1481             << glu::MeshSource(mesh.str())
1482             << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
1483     }
1484 }
1485 
1486 } // namespace
1487 
createShaderObjectBindingTests(tcu::TestContext & testCtx)1488 tcu::TestCaseGroup *createShaderObjectBindingTests(tcu::TestContext &testCtx)
1489 {
1490     de::MovePtr<tcu::TestCaseGroup> bindingGroup(new tcu::TestCaseGroup(testCtx, "binding"));
1491 
1492     BindingDrawParams params;
1493     params.testType               = PASSTHROUGH_GEOM;
1494     params.stage                  = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1495     params.unusedOutputs          = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
1496     params.binaryStage            = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
1497     params.bindUnsupported        = false;
1498     params.setStateAfter          = false;
1499     params.unbindWithNullpShaders = false;
1500 
1501     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "unbind_passthrough_geom", params));
1502 
1503     const struct
1504     {
1505         vk::VkShaderStageFlagBits stage;
1506         const char *name;
1507     } stageTest[] = {
1508         {vk::VK_SHADER_STAGE_VERTEX_BIT, "vert"},
1509         {vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc"},
1510         {vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tese"},
1511         {vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom"},
1512         {vk::VK_SHADER_STAGE_FRAGMENT_BIT, "frag"},
1513     };
1514     params.testType = SWAP;
1515     for (const auto &stage : stageTest)
1516     {
1517         params.stage         = stage.stage;
1518         params.unusedOutputs = vk::VK_SHADER_STAGE_ALL; // Unused
1519         params.binaryStage   = vk::VK_SHADER_STAGE_ALL; // Unused
1520         params.setStateAfter = false;
1521         std::string name     = "swap_" + std::string(stage.name);
1522         bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name.c_str(), params));
1523         for (const auto &unusedOutputs : stageTest)
1524         {
1525             for (const auto &binaryStage : stageTest)
1526             {
1527                 for (uint32_t i = 0; i < 2; ++i)
1528                 {
1529                     params.stage         = stage.stage;
1530                     params.unusedOutputs = unusedOutputs.stage;
1531                     params.binaryStage   = binaryStage.stage;
1532                     params.setStateAfter = (bool)i;
1533                     std::string name2    = "swap_" + std::string(stage.name) + "_unused_output_" +
1534                                         std::string(unusedOutputs.name) + "_binary_" + std::string(binaryStage.name) +
1535                                         "_" + ((i == 0) ? "before" : "after");
1536                     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name2.c_str(), params));
1537                 }
1538             }
1539         }
1540     }
1541 
1542     params.unusedOutputs = vk::VK_SHADER_STAGE_ALL;
1543     params.binaryStage   = vk::VK_SHADER_STAGE_ALL;
1544 
1545     const struct
1546     {
1547         vk::VkShaderStageFlagBits stage;
1548         const char *name;
1549     } unbindStageTest[] = {
1550         {vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc"},
1551         {vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom"},
1552     };
1553     params.testType      = UNBIND;
1554     params.setStateAfter = false;
1555     for (const auto &stage : unbindStageTest)
1556     {
1557         for (uint32_t i = 0; i < 2; ++i)
1558         {
1559             params.stage                  = stage.stage;
1560             params.unbindWithNullpShaders = (bool)i;
1561             std::string name              = "unbind_" + std::string(stage.name) +
1562                                (params.unbindWithNullpShaders ? "_null_pshaders" : "_null_handle");
1563             bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, name.c_str(), params));
1564         }
1565     }
1566 
1567     const struct
1568     {
1569         vk::VkShaderStageFlagBits stage;
1570         const char *name;
1571     } meshStageTest[] = {
1572         {vk::VK_SHADER_STAGE_TASK_BIT_EXT, "task"},
1573         {vk::VK_SHADER_STAGE_MESH_BIT_EXT, "mesh"},
1574     };
1575 
1576     for (const auto &stage : meshStageTest)
1577     {
1578         MeshBindingDrawParams meshParams;
1579         meshParams.stage = stage.stage;
1580         std::string name = "mesh_swap_" + std::string(stage.name);
1581         bindingGroup->addChild(new MeshShaderObjectBindingCase(testCtx, name.c_str(), meshParams));
1582     }
1583 
1584     params.testType = DISABLED;
1585     params.stage    = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1586     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_geom", params));
1587     params.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1588     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_tess", params));
1589     params.stage           = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1590     params.bindUnsupported = true;
1591     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_geom_bind", params));
1592     params.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1593     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "disabled_tess_bind", params));
1594     params.testType = DRAW_DISPATCH_DRAW;
1595     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "draw_dispatch_draw", params));
1596     params.testType = DISPATCH_DRAW_DISPATCH;
1597     bindingGroup->addChild(new ShaderObjectBindingDrawCase(testCtx, "dispatch_draw_dispatch", params));
1598 
1599     BindingParams bindingParams;
1600     bindingParams.useMeshShaders = false;
1601     bindingGroup->addChild(new ShaderObjectBindingCase(testCtx, "bindings", bindingParams));
1602     bindingParams.useMeshShaders = true;
1603     bindingGroup->addChild(new ShaderObjectBindingCase(testCtx, "bindings_mesh_shaders", bindingParams));
1604 
1605     return bindingGroup.release();
1606 }
1607 
1608 } // namespace ShaderObject
1609 } // namespace vkt
1610