• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2015 Google Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*--------------------------------------------------------------------*/
22 
23 #include "vkDefs.hpp"
24 #include "vktTestCaseUtil.hpp"
25 #include "vkBuilderUtil.hpp"
26 #include "vkPlatform.hpp"
27 #include "vkRefUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkDeviceUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkAllocationCallbackUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "vkBufferWithMemory.hpp"
40 #include "vkImageWithMemory.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuCommandLine.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "vktApiCommandBuffersTests.hpp"
45 #include "vktApiBufferComputeInstance.hpp"
46 #include "vktApiComputeInstanceResultBuffer.hpp"
47 #include "deSharedPtr.hpp"
48 #include "deRandom.hpp"
49 #include <sstream>
50 #include <limits>
51 
52 namespace vkt
53 {
54 namespace api
55 {
56 namespace
57 {
58 
59 using namespace vk;
60 
61 typedef de::SharedPtr<vk::Unique<vk::VkEvent>> VkEventSp;
62 
63 // Global variables
64 const uint64_t INFINITE_TIMEOUT = ~(uint64_t)0u;
65 
66 template <uint32_t NumBuffers>
67 class CommandBufferBareTestEnvironment
68 {
69 public:
70     CommandBufferBareTestEnvironment(Context &context, VkCommandPoolCreateFlags commandPoolCreateFlags);
71 
getCommandPool(void) const72     VkCommandPool getCommandPool(void) const
73     {
74         return *m_commandPool;
75     }
76     VkCommandBuffer getCommandBuffer(uint32_t bufferIndex) const;
77 
78 protected:
79     Context &m_context;
80     const VkDevice m_device;
81     const DeviceInterface &m_vkd;
82     const VkQueue m_queue;
83     const uint32_t m_queueFamilyIndex;
84     Allocator &m_allocator;
85 
86     Move<VkCommandPool> m_commandPool;
87     Move<VkCommandBuffer> m_primaryCommandBuffers[NumBuffers];
88 };
89 
90 template <uint32_t NumBuffers>
CommandBufferBareTestEnvironment(Context & context,VkCommandPoolCreateFlags commandPoolCreateFlags)91 CommandBufferBareTestEnvironment<NumBuffers>::CommandBufferBareTestEnvironment(
92     Context &context, VkCommandPoolCreateFlags commandPoolCreateFlags)
93     : m_context(context)
94     , m_device(context.getDevice())
95     , m_vkd(context.getDeviceInterface())
96     , m_queue(context.getUniversalQueue())
97     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
98     , m_allocator(context.getDefaultAllocator())
99 {
100     m_commandPool = createCommandPool(m_vkd, m_device, commandPoolCreateFlags, m_queueFamilyIndex);
101 
102     const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = {
103         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType             sType;
104         DE_NULL,                                        // const void*                 pNext;
105         *m_commandPool,                                 // VkCommandPool               commandPool;
106         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel        level;
107         NumBuffers                                      // uint32_t                    commandBufferCount;
108     };
109 
110     allocateCommandBuffers(m_vkd, m_device, &cmdBufferAllocateInfo, m_primaryCommandBuffers);
111 }
112 
113 template <uint32_t NumBuffers>
getCommandBuffer(uint32_t bufferIndex) const114 VkCommandBuffer CommandBufferBareTestEnvironment<NumBuffers>::getCommandBuffer(uint32_t bufferIndex) const
115 {
116     DE_ASSERT(bufferIndex < NumBuffers);
117     return m_primaryCommandBuffers[bufferIndex].get();
118 }
119 
120 class CommandBufferRenderPassTestEnvironment : public CommandBufferBareTestEnvironment<1>
121 {
122 public:
123     CommandBufferRenderPassTestEnvironment(Context &context, VkCommandPoolCreateFlags commandPoolCreateFlags);
124 
getRenderPass(void) const125     VkRenderPass getRenderPass(void) const
126     {
127         return *m_renderPass;
128     }
getFrameBuffer(void) const129     VkFramebuffer getFrameBuffer(void) const
130     {
131         return *m_frameBuffer;
132     }
getPrimaryCommandBuffer(void) const133     VkCommandBuffer getPrimaryCommandBuffer(void) const
134     {
135         return getCommandBuffer(0);
136     }
getSecondaryCommandBuffer(void) const137     VkCommandBuffer getSecondaryCommandBuffer(void) const
138     {
139         return *m_secondaryCommandBuffer;
140     }
getNestedCommandBuffer(void) const141     VkCommandBuffer getNestedCommandBuffer(void) const
142     {
143         return *m_nestedCommandBuffer;
144     }
145 
146     void beginPrimaryCommandBuffer(VkCommandBufferUsageFlags usageFlags);
147     void beginSecondaryCommandBuffer(VkCommandBufferUsageFlags usageFlags, bool framebufferHint);
148     void beginNestedCommandBuffer(VkCommandBufferUsageFlags usageFlags, bool framebufferHint);
149     void beginRenderPass(VkSubpassContents content);
150     void submitPrimaryCommandBuffer(void);
151     de::MovePtr<tcu::TextureLevel> readColorAttachment(void);
152 
153     static const VkImageType DEFAULT_IMAGE_TYPE;
154     static const VkFormat DEFAULT_IMAGE_FORMAT;
155     static const VkExtent3D DEFAULT_IMAGE_SIZE;
156     static const VkRect2D DEFAULT_IMAGE_AREA;
157 
158 protected:
159     Move<VkImage> m_colorImage;
160     Move<VkImageView> m_colorImageView;
161     Move<VkRenderPass> m_renderPass;
162     Move<VkFramebuffer> m_frameBuffer;
163     de::MovePtr<Allocation> m_colorImageMemory;
164     Move<VkCommandPool> m_secCommandPool;
165     Move<VkCommandBuffer> m_secondaryCommandBuffer;
166     Move<VkCommandBuffer> m_nestedCommandBuffer;
167 };
168 
169 const VkImageType CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_TYPE = VK_IMAGE_TYPE_2D;
170 const VkFormat CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_FORMAT  = VK_FORMAT_R8G8B8A8_UINT;
171 const VkExtent3D CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE  = {255, 255, 1};
172 const VkRect2D CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_AREA    = {
173     {
174         0u,
175         0u,
176     },                                                     // VkOffset2D offset;
177     {DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height}, // VkExtent2D extent;
178 };
179 
CommandBufferRenderPassTestEnvironment(Context & context,VkCommandPoolCreateFlags commandPoolCreateFlags)180 CommandBufferRenderPassTestEnvironment::CommandBufferRenderPassTestEnvironment(
181     Context &context, VkCommandPoolCreateFlags commandPoolCreateFlags)
182     : CommandBufferBareTestEnvironment<1>(context, commandPoolCreateFlags)
183 {
184     m_renderPass = makeRenderPass(m_vkd, m_device, DEFAULT_IMAGE_FORMAT);
185 
186     {
187         const VkImageCreateInfo imageCreateInfo = {
188             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
189             DE_NULL,                             // const void* pNext;
190             0u,                                  // VkImageCreateFlags flags;
191             DEFAULT_IMAGE_TYPE,                  // VkImageType imageType;
192             DEFAULT_IMAGE_FORMAT,                // VkFormat format;
193             DEFAULT_IMAGE_SIZE,                  // VkExtent3D extent;
194             1,                                   // uint32_t mipLevels;
195             1,                                   // uint32_t arrayLayers;
196             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
197             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
198             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
199                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
200             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
201             1,                                   // uint32_t queueFamilyIndexCount;
202             &m_queueFamilyIndex,                 // const uint32_t* pQueueFamilyIndices;
203             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
204         };
205 
206         m_colorImage = createImage(m_vkd, m_device, &imageCreateInfo, DE_NULL);
207     }
208 
209     m_colorImageMemory =
210         m_allocator.allocate(getImageMemoryRequirements(m_vkd, m_device, *m_colorImage), MemoryRequirement::Any);
211     VK_CHECK(m_vkd.bindImageMemory(m_device, *m_colorImage, m_colorImageMemory->getMemory(),
212                                    m_colorImageMemory->getOffset()));
213 
214     {
215         const VkImageViewCreateInfo imageViewCreateInfo = {
216             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
217             DE_NULL,                                  // const void* pNext;
218             0u,                                       // VkImageViewCreateFlags flags;
219             *m_colorImage,                            // VkImage image;
220             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
221             DEFAULT_IMAGE_FORMAT,                     // VkFormat format;
222             {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
223              VK_COMPONENT_SWIZZLE_A}, // VkComponentMapping components;
224             {
225                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
226                 0u,                        // uint32_t baseMipLevel;
227                 1u,                        // uint32_t mipLevels;
228                 0u,                        // uint32_t baseArrayLayer;
229                 1u,                        // uint32_t arraySize;
230             },                             // VkImageSubresourceRange subresourceRange;
231         };
232 
233         m_colorImageView = createImageView(m_vkd, m_device, &imageViewCreateInfo, DE_NULL);
234     }
235 
236     {
237         const VkImageView attachmentViews[1] = {*m_colorImageView};
238 
239         const VkFramebufferCreateInfo framebufferCreateInfo = {
240             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
241             DE_NULL,                                   // const void* pNext;
242             0u,                                        // VkFramebufferCreateFlags flags;
243             *m_renderPass,                             // VkRenderPass renderPass;
244             1,                                         // uint32_t attachmentCount;
245             attachmentViews,                           // const VkImageView* pAttachments;
246             DEFAULT_IMAGE_SIZE.width,                  // uint32_t width;
247             DEFAULT_IMAGE_SIZE.height,                 // uint32_t height;
248             1u,                                        // uint32_t layers;
249         };
250 
251         m_frameBuffer = createFramebuffer(m_vkd, m_device, &framebufferCreateInfo, DE_NULL);
252     }
253 
254     m_secCommandPool = createCommandPool(m_vkd, m_device, commandPoolCreateFlags, m_queueFamilyIndex);
255 
256     {
257         const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = {
258             VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType             sType;
259             DE_NULL,                                        // const void*                 pNext;
260             *m_secCommandPool,                              // VkCommandPool               commandPool;
261             VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel        level;
262             1u                                              // uint32_t                    commandBufferCount;
263         };
264 
265         m_secondaryCommandBuffer = allocateCommandBuffer(m_vkd, m_device, &cmdBufferAllocateInfo);
266         m_nestedCommandBuffer    = allocateCommandBuffer(m_vkd, m_device, &cmdBufferAllocateInfo);
267     }
268 }
269 
beginRenderPass(VkSubpassContents content)270 void CommandBufferRenderPassTestEnvironment::beginRenderPass(VkSubpassContents content)
271 {
272     vk::beginRenderPass(m_vkd, m_primaryCommandBuffers[0].get(), *m_renderPass, *m_frameBuffer, DEFAULT_IMAGE_AREA,
273                         tcu::UVec4(17, 59, 163, 251), content);
274 }
275 
beginPrimaryCommandBuffer(VkCommandBufferUsageFlags usageFlags)276 void CommandBufferRenderPassTestEnvironment::beginPrimaryCommandBuffer(VkCommandBufferUsageFlags usageFlags)
277 {
278     beginCommandBuffer(m_vkd, m_primaryCommandBuffers[0].get(), usageFlags);
279 }
280 
beginSecondaryCommandBuffer(VkCommandBufferUsageFlags usageFlags,bool framebufferHint)281 void CommandBufferRenderPassTestEnvironment::beginSecondaryCommandBuffer(VkCommandBufferUsageFlags usageFlags,
282                                                                          bool framebufferHint)
283 {
284     const VkCommandBufferInheritanceInfo commandBufferInheritanceInfo = {
285         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType                  sType;
286         DE_NULL,                                           // const void*                      pNext;
287         *m_renderPass,                                     // VkRenderPass                     renderPass;
288         0u,                                                // uint32_t                         subpass;
289         (framebufferHint ? *m_frameBuffer : DE_NULL),      // VkFramebuffer                    framebuffer;
290         VK_FALSE,                                          // VkBool32                         occlusionQueryEnable;
291         0u,                                                // VkQueryControlFlags              queryFlags;
292         0u                                                 // VkQueryPipelineStatisticFlags    pipelineStatistics;
293     };
294 
295     const VkCommandBufferBeginInfo commandBufferBeginInfo = {
296         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType                          sType;
297         DE_NULL,                                     // const void*                              pNext;
298         usageFlags,                                  // VkCommandBufferUsageFlags                flags;
299         &commandBufferInheritanceInfo                // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
300     };
301 
302     VK_CHECK(m_vkd.beginCommandBuffer(*m_secondaryCommandBuffer, &commandBufferBeginInfo));
303 }
304 
beginNestedCommandBuffer(VkCommandBufferUsageFlags usageFlags,bool framebufferHint)305 void CommandBufferRenderPassTestEnvironment::beginNestedCommandBuffer(VkCommandBufferUsageFlags usageFlags,
306                                                                       bool framebufferHint)
307 {
308     const VkCommandBufferInheritanceInfo commandBufferInheritanceInfo = {
309         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType                  sType;
310         DE_NULL,                                           // const void*                      pNext;
311         *m_renderPass,                                     // VkRenderPass                     renderPass;
312         0u,                                                // uint32_t                         subpass;
313         (framebufferHint ? *m_frameBuffer : DE_NULL),      // VkFramebuffer                    framebuffer;
314         VK_FALSE,                                          // VkBool32                         occlusionQueryEnable;
315         0u,                                                // VkQueryControlFlags              queryFlags;
316         0u                                                 // VkQueryPipelineStatisticFlags    pipelineStatistics;
317     };
318 
319     const VkCommandBufferBeginInfo commandBufferBeginInfo = {
320         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType                          sType;
321         DE_NULL,                                     // const void*                              pNext;
322         usageFlags,                                  // VkCommandBufferUsageFlags                flags;
323         &commandBufferInheritanceInfo                // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
324     };
325 
326     VK_CHECK(m_vkd.beginCommandBuffer(*m_nestedCommandBuffer, &commandBufferBeginInfo));
327 }
328 
submitPrimaryCommandBuffer(void)329 void CommandBufferRenderPassTestEnvironment::submitPrimaryCommandBuffer(void)
330 {
331     submitCommandsAndWait(m_vkd, m_device, m_queue, m_primaryCommandBuffers[0].get());
332 }
333 
readColorAttachment()334 de::MovePtr<tcu::TextureLevel> CommandBufferRenderPassTestEnvironment::readColorAttachment()
335 {
336     Move<VkBuffer> buffer;
337     de::MovePtr<Allocation> bufferAlloc;
338     const tcu::TextureFormat tcuFormat = mapVkFormat(DEFAULT_IMAGE_FORMAT);
339     const VkDeviceSize pixelDataSize = DEFAULT_IMAGE_SIZE.height * DEFAULT_IMAGE_SIZE.height * tcuFormat.getPixelSize();
340     de::MovePtr<tcu::TextureLevel> resultLevel(
341         new tcu::TextureLevel(tcuFormat, DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height));
342 
343     // Create destination buffer
344     {
345         const VkBufferCreateInfo bufferParams = {
346             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
347             DE_NULL,                              // const void* pNext;
348             0u,                                   // VkBufferCreateFlags flags;
349             pixelDataSize,                        // VkDeviceSize size;
350             VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
351             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
352             0u,                                   // uint32_t queueFamilyIndexCount;
353             DE_NULL                               // const uint32_t* pQueueFamilyIndices;
354         };
355 
356         buffer = createBuffer(m_vkd, m_device, &bufferParams);
357         bufferAlloc =
358             m_allocator.allocate(getBufferMemoryRequirements(m_vkd, m_device, *buffer), MemoryRequirement::HostVisible);
359         VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
360     }
361 
362     // Copy image to buffer
363     beginPrimaryCommandBuffer(0);
364     copyImageToBuffer(m_vkd, m_primaryCommandBuffers[0].get(), *m_colorImage, *buffer,
365                       tcu::IVec2(DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height));
366     endCommandBuffer(m_vkd, m_primaryCommandBuffers[0].get());
367 
368     submitPrimaryCommandBuffer();
369 
370     // Read buffer data
371     invalidateAlloc(m_vkd, m_device, *bufferAlloc);
372     tcu::copy(*resultLevel,
373               tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), bufferAlloc->getHostPtr()));
374 
375     return resultLevel;
376 }
377 
378 // Testcases
379 /********* 19.1. Command Pools (5.1 in VK 1.0 Spec) ***************************/
createPoolNullParamsTest(Context & context)380 tcu::TestStatus createPoolNullParamsTest(Context &context)
381 {
382     const VkDevice vkDevice         = context.getDevice();
383     const DeviceInterface &vk       = context.getDeviceInterface();
384     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
385 
386     createCommandPool(vk, vkDevice, 0u, queueFamilyIndex);
387 
388     return tcu::TestStatus::pass("Command Pool allocated correctly.");
389 }
390 
391 #ifndef CTS_USES_VULKANSC
createPoolNonNullAllocatorTest(Context & context)392 tcu::TestStatus createPoolNonNullAllocatorTest(Context &context)
393 {
394     const VkDevice vkDevice                          = context.getDevice();
395     const DeviceInterface &vk                        = context.getDeviceInterface();
396     const uint32_t queueFamilyIndex                  = context.getUniversalQueueFamilyIndex();
397     const VkAllocationCallbacks *allocationCallbacks = getSystemAllocator();
398 
399     const VkCommandPoolCreateInfo cmdPoolParams = {
400         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
401         DE_NULL,                                    // pNext;
402         0u,                                         // flags;
403         queueFamilyIndex,                           // queueFamilyIndex;
404     };
405 
406     createCommandPool(vk, vkDevice, &cmdPoolParams, allocationCallbacks);
407 
408     return tcu::TestStatus::pass("Command Pool allocated correctly.");
409 }
410 #endif // CTS_USES_VULKANSC
411 
createPoolTransientBitTest(Context & context)412 tcu::TestStatus createPoolTransientBitTest(Context &context)
413 {
414     const VkDevice vkDevice         = context.getDevice();
415     const DeviceInterface &vk       = context.getDeviceInterface();
416     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
417 
418     const VkCommandPoolCreateInfo cmdPoolParams = {
419         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
420         DE_NULL,                                    // pNext;
421         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // flags;
422         queueFamilyIndex,                           // queueFamilyIndex;
423     };
424 
425     createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL);
426 
427     return tcu::TestStatus::pass("Command Pool allocated correctly.");
428 }
429 
createPoolResetBitTest(Context & context)430 tcu::TestStatus createPoolResetBitTest(Context &context)
431 {
432     const VkDevice vkDevice         = context.getDevice();
433     const DeviceInterface &vk       = context.getDeviceInterface();
434     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
435 
436     const VkCommandPoolCreateInfo cmdPoolParams = {
437         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
438         DE_NULL,                                         // pNext;
439         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
440         queueFamilyIndex,                                // queueFamilyIndex;
441     };
442 
443     createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL);
444 
445     return tcu::TestStatus::pass("Command Pool allocated correctly.");
446 }
447 
448 #ifndef CTS_USES_VULKANSC
resetPoolReleaseResourcesBitTest(Context & context)449 tcu::TestStatus resetPoolReleaseResourcesBitTest(Context &context)
450 {
451     const VkDevice vkDevice         = context.getDevice();
452     const DeviceInterface &vk       = context.getDeviceInterface();
453     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
454 
455     const VkCommandPoolCreateInfo cmdPoolParams = {
456         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
457         DE_NULL,                                    // pNext;
458         0u,                                         // flags;
459         queueFamilyIndex,                           // queueFamilyIndex;
460     };
461 
462     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));
463 
464     VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT));
465 
466     return tcu::TestStatus::pass("Command Pool allocated correctly.");
467 }
468 #endif // CTS_USES_VULKANSC
469 
resetPoolNoFlagsTest(Context & context)470 tcu::TestStatus resetPoolNoFlagsTest(Context &context)
471 {
472     const VkDevice vkDevice         = context.getDevice();
473     const DeviceInterface &vk       = context.getDeviceInterface();
474     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
475 
476     const VkCommandPoolCreateInfo cmdPoolParams = {
477         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
478         DE_NULL,                                    // pNext;
479         0u,                                         // flags;
480         queueFamilyIndex,                           // queueFamilyIndex;
481     };
482 
483     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));
484 
485     VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, 0u));
486 
487     return tcu::TestStatus::pass("Command Pool allocated correctly.");
488 }
489 
490 #ifndef CTS_USES_VULKANSC
executeCommandBuffer(const VkDevice device,const DeviceInterface & vk,const VkQueue queue,const VkCommandBuffer commandBuffer,const bool exitBeforeEndCommandBuffer=false)491 bool executeCommandBuffer(const VkDevice device, const DeviceInterface &vk, const VkQueue queue,
492                           const VkCommandBuffer commandBuffer, const bool exitBeforeEndCommandBuffer = false)
493 {
494     const Unique<VkEvent> event(createEvent(vk, device));
495     beginCommandBuffer(vk, commandBuffer, 0u);
496     {
497         const VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
498         vk.cmdSetEvent(commandBuffer, *event, stageMask);
499         if (exitBeforeEndCommandBuffer)
500             return exitBeforeEndCommandBuffer;
501     }
502     endCommandBuffer(vk, commandBuffer);
503 
504     submitCommandsAndWait(vk, device, queue, commandBuffer);
505 
506     // check if buffer has been executed
507     const VkResult result = vk.getEventStatus(device, *event);
508     return result == VK_EVENT_SET;
509 }
510 
resetPoolReuseTest(Context & context)511 tcu::TestStatus resetPoolReuseTest(Context &context)
512 {
513     const VkDevice vkDevice         = context.getDevice();
514     const DeviceInterface &vk       = context.getDeviceInterface();
515     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
516     const VkQueue queue             = context.getUniversalQueue();
517 
518     const VkCommandPoolCreateInfo cmdPoolParams = {
519         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
520         DE_NULL,                                    // pNext;
521         0u,                                         // flags;
522         queueFamilyIndex                            // queueFamilyIndex;
523     };
524     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));
525     const VkCommandBufferAllocateInfo cmdBufParams = {
526         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
527         DE_NULL,                                        // pNext;
528         *cmdPool,                                       // commandPool;
529         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
530         1u                                              // bufferCount;
531     };
532     const Move<VkCommandBuffer> commandBuffers[] = {allocateCommandBuffer(vk, vkDevice, &cmdBufParams),
533                                                     allocateCommandBuffer(vk, vkDevice, &cmdBufParams)};
534 
535 #ifdef CTS_USES_VULKANSC
536     bool canFinishEarlier = context.getTestContext().getCommandLine().isSubProcess();
537 #else
538     bool canFinishEarlier           = true;
539 #endif // CTS_USES_VULKANSC
540 
541     if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[0])) && canFinishEarlier)
542         return tcu::TestStatus::fail("Failed");
543     if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[1]), true) && canFinishEarlier)
544         return tcu::TestStatus::fail("Failed");
545 
546     VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT));
547 
548     if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[0])) && canFinishEarlier)
549         return tcu::TestStatus::fail("Failed");
550     if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[1])) && canFinishEarlier)
551         return tcu::TestStatus::fail("Failed");
552 
553     {
554         const Unique<VkCommandBuffer> afterResetCommandBuffers(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
555         if (!executeCommandBuffer(vkDevice, vk, queue, *afterResetCommandBuffers) && canFinishEarlier)
556             return tcu::TestStatus::fail("Failed");
557     }
558 
559     return tcu::TestStatus::pass("Passed");
560 }
561 #endif // CTS_USES_VULKANSC
562 
563 /******** 19.2. Command Buffer Lifetime (5.2 in VK 1.0 Spec) ******************/
allocatePrimaryBufferTest(Context & context)564 tcu::TestStatus allocatePrimaryBufferTest(Context &context)
565 {
566     const VkDevice vkDevice         = context.getDevice();
567     const DeviceInterface &vk       = context.getDeviceInterface();
568     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
569 
570     const VkCommandPoolCreateInfo cmdPoolParams = {
571         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
572         DE_NULL,                                         // pNext;
573         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
574         queueFamilyIndex,                                // queueFamilyIndex;
575     };
576     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
577 
578     // Command buffer
579     const VkCommandBufferAllocateInfo cmdBufParams = {
580         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
581         DE_NULL,                                        // pNext;
582         *cmdPool,                                       // commandPool;
583         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
584         1u,                                             // bufferCount;
585     };
586     const Unique<VkCommandBuffer> cmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
587 
588     return tcu::TestStatus::pass("Buffer was created correctly.");
589 }
590 
allocateManyPrimaryBuffersTest(Context & context)591 tcu::TestStatus allocateManyPrimaryBuffersTest(Context &context)
592 {
593 
594     const VkDevice vkDevice         = context.getDevice();
595     const DeviceInterface &vk       = context.getDeviceInterface();
596     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
597 
598     const VkCommandPoolCreateInfo cmdPoolParams = {
599         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
600         DE_NULL,                                         // const void* pNext;
601         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
602         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
603     };
604     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
605 
606     // \todo Determining the minimum number of command buffers should be a function of available system memory and driver capabilities.
607 #ifndef CTS_USES_VULKANSC
608 #if (DE_PTR_SIZE == 4)
609     const unsigned minCommandBuffer = 1024;
610 #else
611     const unsigned minCommandBuffer = 10000;
612 #endif
613 #else
614     const unsigned minCommandBuffer  = 100;
615 #endif // CTS_USES_VULKANSC
616 
617     // Command buffer
618     const VkCommandBufferAllocateInfo cmdBufParams = {
619         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
620         DE_NULL,                                        // const void* pNext;
621         *cmdPool,                                       // VkCommandPool pool;
622         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
623         minCommandBuffer,                               // uint32_t bufferCount;
624     };
625 
626     // do not keep the handles to buffers, as they will be freed with command pool
627 
628     // allocate the minimum required amount of buffers
629     Move<VkCommandBuffer> cmdBuffers[minCommandBuffer];
630     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
631 
632     std::ostringstream out;
633     out << "allocateManyPrimaryBuffersTest succeded: created " << minCommandBuffer << " command buffers";
634 
635     return tcu::TestStatus::pass(out.str());
636 }
637 
allocateSecondaryBufferTest(Context & context)638 tcu::TestStatus allocateSecondaryBufferTest(Context &context)
639 {
640     const VkDevice vkDevice         = context.getDevice();
641     const DeviceInterface &vk       = context.getDeviceInterface();
642     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
643 
644     const VkCommandPoolCreateInfo cmdPoolParams = {
645         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
646         DE_NULL,                                         // pNext;
647         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
648         queueFamilyIndex,                                // queueFamilyIndex;
649     };
650     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
651 
652     // Command buffer
653     const VkCommandBufferAllocateInfo cmdBufParams = {
654         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
655         DE_NULL,                                        // pNext;
656         *cmdPool,                                       // commandPool;
657         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
658         1u,                                             // bufferCount;
659     };
660     const Unique<VkCommandBuffer> cmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
661 
662     return tcu::TestStatus::pass("Buffer was created correctly.");
663 }
664 
allocateManySecondaryBuffersTest(Context & context)665 tcu::TestStatus allocateManySecondaryBuffersTest(Context &context)
666 {
667 
668     const VkDevice vkDevice         = context.getDevice();
669     const DeviceInterface &vk       = context.getDeviceInterface();
670     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
671 
672     const VkCommandPoolCreateInfo cmdPoolParams = {
673         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
674         DE_NULL,                                         // const void* pNext;
675         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
676         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
677     };
678     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
679 
680     // \todo Determining the minimum number of command buffers should be a function of available system memory and driver capabilities.
681 #ifndef CTS_USES_VULKANSC
682 #if (DE_PTR_SIZE == 4)
683     const unsigned minCommandBuffer = 1024;
684 #else
685     const unsigned minCommandBuffer = 10000;
686 #endif
687 #else
688     const unsigned minCommandBuffer  = 100;
689 #endif // CTS_USES_VULKANSC
690 
691     // Command buffer
692     const VkCommandBufferAllocateInfo cmdBufParams = {
693         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
694         DE_NULL,                                        // const void* pNext;
695         *cmdPool,                                       // VkCommandPool pool;
696         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
697         minCommandBuffer,                               // uint32_t bufferCount;
698     };
699 
700     // do not keep the handles to buffers, as they will be freed with command pool
701 
702     // allocate the minimum required amount of buffers
703     Move<VkCommandBuffer> cmdBuffers[minCommandBuffer];
704     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
705 
706     std::ostringstream out;
707     out << "allocateManySecondaryBuffersTest succeded: created " << minCommandBuffer << " command buffers";
708 
709     return tcu::TestStatus::pass(out.str());
710 }
711 
executePrimaryBufferTest(Context & context)712 tcu::TestStatus executePrimaryBufferTest(Context &context)
713 {
714     const VkDevice vkDevice         = context.getDevice();
715     const DeviceInterface &vk       = context.getDeviceInterface();
716     const VkQueue queue             = context.getUniversalQueue();
717     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
718 
719     const VkCommandPoolCreateInfo cmdPoolParams = {
720         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
721         DE_NULL,                                         // const void* pNext;
722         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
723         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
724     };
725     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
726 
727     // Command buffer
728     const VkCommandBufferAllocateInfo cmdBufParams = {
729         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
730         DE_NULL,                                        // const void* pNext;
731         *cmdPool,                                       // VkCommandPool pool;
732         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
733         1u,                                             // uint32_t bufferCount;
734     };
735     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
736 
737     // create event that will be used to check if secondary command buffer has been executed
738     const Unique<VkEvent> event(createEvent(vk, vkDevice));
739 
740     // reset event
741     VK_CHECK(vk.resetEvent(vkDevice, *event));
742 
743     // record primary command buffer
744     beginCommandBuffer(vk, *primCmdBuf, 0u);
745     {
746         // allow execution of event during every stage of pipeline
747         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
748 
749         // record setting event
750         vk.cmdSetEvent(*primCmdBuf, *event, stageMask);
751     }
752     endCommandBuffer(vk, *primCmdBuf);
753 
754     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
755 
756     // check if buffer has been executed
757     VkResult result = vk.getEventStatus(vkDevice, *event);
758     if (result == VK_EVENT_SET)
759         return tcu::TestStatus::pass("Execute Primary Command Buffer succeeded");
760 
761     return tcu::TestStatus::fail("Execute Primary Command Buffer FAILED");
762 }
763 
executeLargePrimaryBufferTest(Context & context)764 tcu::TestStatus executeLargePrimaryBufferTest(Context &context)
765 {
766     const VkDevice vkDevice         = context.getDevice();
767     const DeviceInterface &vk       = context.getDeviceInterface();
768     const VkQueue queue             = context.getUniversalQueue();
769     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
770 #ifndef CTS_USES_VULKANSC
771     const uint32_t LARGE_BUFFER_SIZE = 10000;
772 #else
773     const uint32_t LARGE_BUFFER_SIZE = 100;
774 #endif // CTS_USES_VULKANSC
775 
776     const VkCommandPoolCreateInfo cmdPoolParams = {
777         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
778         DE_NULL,                                         // const void* pNext;
779         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
780         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
781     };
782     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
783 
784     // Command buffer
785     const VkCommandBufferAllocateInfo cmdBufParams = {
786         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
787         DE_NULL,                                        // const void* pNext;
788         *cmdPool,                                       // VkCommandPool pool;
789         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
790         1u,                                             // uint32_t bufferCount;
791     };
792     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
793 
794     std::vector<VkEventSp> events;
795     for (uint32_t ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
796         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
797 
798     // record primary command buffer
799     beginCommandBuffer(vk, *primCmdBuf, 0u);
800     {
801         // set all the events
802         for (uint32_t ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
803         {
804             vk.cmdSetEvent(*primCmdBuf, events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
805         }
806     }
807     endCommandBuffer(vk, *primCmdBuf);
808 
809     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
810 
811     // check if the buffer was executed correctly - all events had their status
812     // changed
813     tcu::TestStatus testResult = tcu::TestStatus::incomplete();
814 
815     for (uint32_t ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
816     {
817         if (vk.getEventStatus(vkDevice, events[ndx]->get()) != VK_EVENT_SET)
818         {
819             testResult = tcu::TestStatus::fail("An event was not set.");
820             break;
821         }
822     }
823 
824     if (!testResult.isComplete())
825         testResult = tcu::TestStatus::pass("All events set correctly.");
826 
827     return testResult;
828 }
829 
resetBufferImplicitlyTest(Context & context)830 tcu::TestStatus resetBufferImplicitlyTest(Context &context)
831 {
832     const VkDevice vkDevice         = context.getDevice();
833     const DeviceInterface &vk       = context.getDeviceInterface();
834     const VkQueue queue             = context.getUniversalQueue();
835     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
836 
837 #ifdef CTS_USES_VULKANSC
838     if (context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
839         TCU_THROW(NotSupportedError, "commandPoolResetCommandBuffer not supported by this implementation");
840 #endif // CTS_USES_VULKANSC
841 
842     const VkCommandPoolCreateInfo cmdPoolParams = {
843         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
844         DE_NULL,                                         // pNext;
845         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
846         queueFamilyIndex,                                // queueFamilyIndex;
847     };
848     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
849 
850     // Command buffer
851     const VkCommandBufferAllocateInfo cmdBufParams = {
852         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
853         DE_NULL,                                        // pNext;
854         *cmdPool,                                       // pool;
855         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
856         1u,                                             // bufferCount;
857     };
858     const Unique<VkCommandBuffer> cmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
859 
860     const Unique<VkEvent> event(createEvent(vk, vkDevice));
861 
862     // Put the command buffer in recording state.
863     beginCommandBuffer(vk, *cmdBuf, 0u);
864     {
865         // Set the event
866         vk.cmdSetEvent(*cmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
867     }
868     endCommandBuffer(vk, *cmdBuf);
869 
870     submitCommandsAndWait(vk, vkDevice, queue, cmdBuf.get());
871 
872     // Check if the buffer was executed
873     if (vk.getEventStatus(vkDevice, *event) != VK_EVENT_SET)
874         return tcu::TestStatus::fail("Failed to set the event.");
875 
876     // Reset the event
877     vk.resetEvent(vkDevice, *event);
878     if (vk.getEventStatus(vkDevice, *event) != VK_EVENT_RESET)
879         return tcu::TestStatus::fail("Failed to reset the event.");
880 
881     // Reset the command buffer by putting it in recording state again. This
882     // should empty the command buffer.
883     beginCommandBuffer(vk, *cmdBuf, 0u);
884     endCommandBuffer(vk, *cmdBuf);
885 
886     // Submit the command buffer after resetting. It should have no commands
887     // recorded, so the event should remain unsignaled.
888     submitCommandsAndWait(vk, vkDevice, queue, cmdBuf.get());
889 
890     // Check if the event remained unset.
891     if (vk.getEventStatus(vkDevice, *event) == VK_EVENT_RESET)
892         return tcu::TestStatus::pass("Buffer was reset correctly.");
893     else
894         return tcu::TestStatus::fail("Buffer was not reset correctly.");
895 }
896 
897 #ifndef CTS_USES_VULKANSC
898 
899 using de::SharedPtr;
900 typedef SharedPtr<Unique<VkEvent>> VkEventShared;
901 
902 template <typename T>
makeSharedPtr(Move<T> move)903 inline SharedPtr<Unique<T>> makeSharedPtr(Move<T> move)
904 {
905     return SharedPtr<Unique<T>>(new Unique<T>(move));
906 }
907 
submitAndCheck(Context & context,std::vector<VkCommandBuffer> & cmdBuffers,std::vector<VkEventShared> & events)908 bool submitAndCheck(Context &context, std::vector<VkCommandBuffer> &cmdBuffers, std::vector<VkEventShared> &events)
909 {
910     const VkDevice vkDevice   = context.getDevice();
911     const DeviceInterface &vk = context.getDeviceInterface();
912     const VkQueue queue       = context.getUniversalQueue();
913     const Unique<VkFence> fence(createFence(vk, vkDevice));
914 
915     const VkSubmitInfo submitInfo = {
916         VK_STRUCTURE_TYPE_SUBMIT_INFO,            // sType
917         DE_NULL,                                  // pNext
918         0u,                                       // waitSemaphoreCount
919         DE_NULL,                                  // pWaitSemaphores
920         (const VkPipelineStageFlags *)DE_NULL,    // pWaitDstStageMask
921         static_cast<uint32_t>(cmdBuffers.size()), // commandBufferCount
922         &cmdBuffers[0],                           // pCommandBuffers
923         0u,                                       // signalSemaphoreCount
924         DE_NULL,                                  // pSignalSemaphores
925     };
926 
927     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence.get()));
928     VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), 0u, INFINITE_TIMEOUT));
929 
930     for (int eventNdx = 0; eventNdx < static_cast<int>(events.size()); ++eventNdx)
931     {
932         if (vk.getEventStatus(vkDevice, **events[eventNdx]) != VK_EVENT_SET)
933             return false;
934         vk.resetEvent(vkDevice, **events[eventNdx]);
935     }
936 
937     return true;
938 }
939 
createCommadBuffers(const DeviceInterface & vk,const VkDevice vkDevice,uint32_t bufferCount,VkCommandPool pool,const VkCommandBufferLevel cmdBufferLevel,VkCommandBuffer * pCommandBuffers)940 void createCommadBuffers(const DeviceInterface &vk, const VkDevice vkDevice, uint32_t bufferCount, VkCommandPool pool,
941                          const VkCommandBufferLevel cmdBufferLevel, VkCommandBuffer *pCommandBuffers)
942 {
943     const VkCommandBufferAllocateInfo cmdBufParams = {
944         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
945         DE_NULL,                                        // const void* pNext;
946         pool,                                           // VkCommandPool pool;
947         cmdBufferLevel,                                 // VkCommandBufferLevel level;
948         bufferCount,                                    // uint32_t bufferCount;
949     };
950     VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, pCommandBuffers));
951 }
952 
addCommandsToBuffer(const DeviceInterface & vk,std::vector<VkCommandBuffer> & cmdBuffers,std::vector<VkEventShared> & events)953 void addCommandsToBuffer(const DeviceInterface &vk, std::vector<VkCommandBuffer> &cmdBuffers,
954                          std::vector<VkEventShared> &events)
955 {
956     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
957         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
958         DE_NULL,
959         (VkRenderPass)0u,                  // renderPass
960         0u,                                // subpass
961         (VkFramebuffer)0u,                 // framebuffer
962         VK_FALSE,                          // occlusionQueryEnable
963         (VkQueryControlFlags)0u,           // queryFlags
964         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
965     };
966 
967     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
968         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
969         DE_NULL,                                     // pNext
970         0u,                                          // flags
971         &secCmdBufInheritInfo,                       // pInheritanceInfo;
972     };
973 
974     for (int bufferNdx = 0; bufferNdx < static_cast<int>(cmdBuffers.size()); ++bufferNdx)
975     {
976         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[bufferNdx], &cmdBufBeginInfo));
977         vk.cmdSetEvent(cmdBuffers[bufferNdx], **events[bufferNdx % events.size()], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
978         endCommandBuffer(vk, cmdBuffers[bufferNdx]);
979     }
980 }
981 
executeSecondaryCmdBuffer(Context & context,VkCommandPool pool,std::vector<VkCommandBuffer> & cmdBuffersSecondary,std::vector<VkEventShared> & events)982 bool executeSecondaryCmdBuffer(Context &context, VkCommandPool pool, std::vector<VkCommandBuffer> &cmdBuffersSecondary,
983                                std::vector<VkEventShared> &events)
984 {
985     const VkDevice vkDevice   = context.getDevice();
986     const DeviceInterface &vk = context.getDeviceInterface();
987     std::vector<VkCommandBuffer> cmdBuffer(1);
988 
989     createCommadBuffers(vk, vkDevice, 1u, pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, &cmdBuffer[0]);
990     beginCommandBuffer(vk, cmdBuffer[0], 0u);
991     vk.cmdExecuteCommands(cmdBuffer[0], static_cast<uint32_t>(cmdBuffersSecondary.size()), &cmdBuffersSecondary[0]);
992     endCommandBuffer(vk, cmdBuffer[0]);
993 
994     bool returnValue = submitAndCheck(context, cmdBuffer, events);
995     vk.freeCommandBuffers(vkDevice, pool, 1u, &cmdBuffer[0]);
996     return returnValue;
997 }
998 
trimCommandPoolTest(Context & context,const VkCommandBufferLevel cmdBufferLevel)999 tcu::TestStatus trimCommandPoolTest(Context &context, const VkCommandBufferLevel cmdBufferLevel)
1000 {
1001     if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance1"))
1002         TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1003 
1004     const VkDevice vkDevice         = context.getDevice();
1005     const DeviceInterface &vk       = context.getDeviceInterface();
1006     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1007 
1008     //test parameters
1009     const uint32_t cmdBufferIterationCount = 300u;
1010     const uint32_t cmdBufferCount          = 10u;
1011 
1012     const VkCommandPoolCreateInfo cmdPoolParams = {
1013         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
1014         DE_NULL,                                         // pNext;
1015         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
1016         queueFamilyIndex,                                // queueFamilyIndex;
1017     };
1018     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1019 
1020     std::vector<VkEventShared> events;
1021     for (uint32_t ndx = 0u; ndx < cmdBufferCount; ++ndx)
1022         events.push_back(makeSharedPtr(createEvent(vk, vkDevice)));
1023 
1024     {
1025         std::vector<VkCommandBuffer> cmdBuffers(cmdBufferCount);
1026         createCommadBuffers(vk, vkDevice, cmdBufferCount, *cmdPool, cmdBufferLevel, &cmdBuffers[0]);
1027 
1028         for (uint32_t cmdBufferIterationrNdx = 0; cmdBufferIterationrNdx < cmdBufferIterationCount;
1029              ++cmdBufferIterationrNdx)
1030         {
1031             addCommandsToBuffer(vk, cmdBuffers, events);
1032 
1033             //Peak, situation when we use a lot more command buffers
1034             if (cmdBufferIterationrNdx % 10u == 0)
1035             {
1036                 std::vector<VkCommandBuffer> cmdBuffersPeak(cmdBufferCount * 10u);
1037                 createCommadBuffers(vk, vkDevice, static_cast<uint32_t>(cmdBuffersPeak.size()), *cmdPool,
1038                                     cmdBufferLevel, &cmdBuffersPeak[0]);
1039                 addCommandsToBuffer(vk, cmdBuffersPeak, events);
1040 
1041                 switch (cmdBufferLevel)
1042                 {
1043                 case VK_COMMAND_BUFFER_LEVEL_PRIMARY:
1044                     if (!submitAndCheck(context, cmdBuffersPeak, events))
1045                         return tcu::TestStatus::fail("Fail");
1046                     break;
1047                 case VK_COMMAND_BUFFER_LEVEL_SECONDARY:
1048                     if (!executeSecondaryCmdBuffer(context, *cmdPool, cmdBuffersPeak, events))
1049                         return tcu::TestStatus::fail("Fail");
1050                     break;
1051                 default:
1052                     DE_ASSERT(0);
1053                 }
1054                 vk.freeCommandBuffers(vkDevice, *cmdPool, static_cast<uint32_t>(cmdBuffersPeak.size()),
1055                                       &cmdBuffersPeak[0]);
1056             }
1057 
1058             vk.trimCommandPool(vkDevice, *cmdPool, (VkCommandPoolTrimFlags)0);
1059 
1060             switch (cmdBufferLevel)
1061             {
1062             case VK_COMMAND_BUFFER_LEVEL_PRIMARY:
1063                 if (!submitAndCheck(context, cmdBuffers, events))
1064                     return tcu::TestStatus::fail("Fail");
1065                 break;
1066             case VK_COMMAND_BUFFER_LEVEL_SECONDARY:
1067                 if (!executeSecondaryCmdBuffer(context, *cmdPool, cmdBuffers, events))
1068                     return tcu::TestStatus::fail("Fail");
1069                 break;
1070             default:
1071                 DE_ASSERT(0);
1072             }
1073 
1074             for (uint32_t bufferNdx = cmdBufferIterationrNdx % 3u; bufferNdx < cmdBufferCount; bufferNdx += 2u)
1075             {
1076                 vk.freeCommandBuffers(vkDevice, *cmdPool, 1u, &cmdBuffers[bufferNdx]);
1077                 createCommadBuffers(vk, vkDevice, 1u, *cmdPool, cmdBufferLevel, &cmdBuffers[bufferNdx]);
1078             }
1079         }
1080     }
1081 
1082     return tcu::TestStatus::pass("Pass");
1083 }
1084 
1085 #endif // CTS_USES_VULKANSC
1086 
1087 /******** 19.3. Command Buffer Recording (5.3 in VK 1.0 Spec) *****************/
recordSinglePrimaryBufferTest(Context & context)1088 tcu::TestStatus recordSinglePrimaryBufferTest(Context &context)
1089 {
1090     const VkDevice vkDevice         = context.getDevice();
1091     const DeviceInterface &vk       = context.getDeviceInterface();
1092     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1093 
1094     const VkCommandPoolCreateInfo cmdPoolParams = {
1095         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1096         DE_NULL,                                         // const void* pNext;
1097         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1098         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1099     };
1100     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1101 
1102     // Command buffer
1103     const VkCommandBufferAllocateInfo cmdBufParams = {
1104         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1105         DE_NULL,                                        // const void* pNext;
1106         *cmdPool,                                       // VkCommandPool pool;
1107         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1108         1u,                                             // uint32_t bufferCount;
1109     };
1110     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1111 
1112     // create event that will be used to check if secondary command buffer has been executed
1113     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1114 
1115     // record primary command buffer
1116     beginCommandBuffer(vk, *primCmdBuf, 0u);
1117     {
1118         // record setting event
1119         vk.cmdSetEvent(*primCmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
1120     }
1121     endCommandBuffer(vk, *primCmdBuf);
1122 
1123     return tcu::TestStatus::pass("Primary buffer recorded successfully.");
1124 }
1125 
recordLargePrimaryBufferTest(Context & context)1126 tcu::TestStatus recordLargePrimaryBufferTest(Context &context)
1127 {
1128     const VkDevice vkDevice         = context.getDevice();
1129     const DeviceInterface &vk       = context.getDeviceInterface();
1130     const VkQueue queue             = context.getUniversalQueue();
1131     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1132 
1133     const VkCommandPoolCreateInfo cmdPoolParams = {
1134         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1135         DE_NULL,                                         // const void* pNext;
1136         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1137         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1138     };
1139     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1140 
1141     // Command buffer
1142     const VkCommandBufferAllocateInfo cmdBufParams = {
1143         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1144         DE_NULL,                                        // const void* pNext;
1145         *cmdPool,                                       // VkCommandPool pool;
1146         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1147         1u,                                             // uint32_t bufferCount;
1148     };
1149     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1150 
1151     // create event that will be used to check if secondary command buffer has been executed
1152     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1153 
1154     // reset event
1155     VK_CHECK(vk.resetEvent(vkDevice, *event));
1156 
1157     // record primary command buffer
1158     beginCommandBuffer(vk, *primCmdBuf, 0u);
1159     {
1160         // allow execution of event during every stage of pipeline
1161         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1162 
1163         // define minimal amount of commands to accept
1164 #ifndef CTS_USES_VULKANSC
1165         const long long unsigned minNumCommands = 10000llu;
1166 #else
1167         const long long unsigned minNumCommands = 1000llu;
1168 #endif // CTS_USES_VULKANSC
1169 
1170         for (long long unsigned currentCommands = 0; currentCommands < minNumCommands / 2; ++currentCommands)
1171         {
1172             // record setting event
1173             vk.cmdSetEvent(*primCmdBuf, *event, stageMask);
1174 
1175             // record resetting event
1176             vk.cmdResetEvent(*primCmdBuf, *event, stageMask);
1177         }
1178     }
1179     endCommandBuffer(vk, *primCmdBuf);
1180 
1181     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1182 
1183     return tcu::TestStatus::pass("hugeTest succeeded");
1184 }
1185 
recordSingleSecondaryBufferTest(Context & context)1186 tcu::TestStatus recordSingleSecondaryBufferTest(Context &context)
1187 {
1188     const VkDevice vkDevice         = context.getDevice();
1189     const DeviceInterface &vk       = context.getDeviceInterface();
1190     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1191 
1192     const VkCommandPoolCreateInfo cmdPoolParams = {
1193         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1194         DE_NULL,                                         // const void* pNext;
1195         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1196         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1197     };
1198     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1199 
1200     // Command buffer
1201     const VkCommandBufferAllocateInfo cmdBufParams = {
1202         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1203         DE_NULL,                                        // const void* pNext;
1204         *cmdPool,                                       // VkCommandPool pool;
1205         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
1206         1u,                                             // uint32_t bufferCount;
1207     };
1208     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1209 
1210     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
1211         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1212         DE_NULL,
1213         (VkRenderPass)0u,                  // renderPass
1214         0u,                                // subpass
1215         (VkFramebuffer)0u,                 // framebuffer
1216         VK_FALSE,                          // occlusionQueryEnable
1217         (VkQueryControlFlags)0u,           // queryFlags
1218         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
1219     };
1220     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
1221         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1222         DE_NULL,
1223         0, // flags
1224         &secCmdBufInheritInfo,
1225     };
1226 
1227     // create event that will be used to check if secondary command buffer has been executed
1228     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1229 
1230     // record primary command buffer
1231     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
1232     {
1233         // record setting event
1234         vk.cmdSetEvent(*secCmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
1235     }
1236     endCommandBuffer(vk, *secCmdBuf);
1237 
1238     return tcu::TestStatus::pass("Secondary buffer recorded successfully.");
1239 }
1240 
recordLargeSecondaryBufferTest(Context & context)1241 tcu::TestStatus recordLargeSecondaryBufferTest(Context &context)
1242 {
1243     const VkDevice vkDevice         = context.getDevice();
1244     const DeviceInterface &vk       = context.getDeviceInterface();
1245     const VkQueue queue             = context.getUniversalQueue();
1246     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1247 
1248     const VkCommandPoolCreateInfo cmdPoolParams = {
1249         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1250         DE_NULL,                                         // const void* pNext;
1251         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1252         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1253     };
1254     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1255     const Unique<VkCommandPool> secCmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1256     // Command buffer
1257     const VkCommandBufferAllocateInfo cmdBufParams = {
1258         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1259         DE_NULL,                                        // const void* pNext;
1260         *cmdPool,                                       // VkCommandPool pool;
1261         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1262         1u,                                             // uint32_t bufferCount;
1263     };
1264     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1265 
1266     const VkCommandBufferAllocateInfo secCmdBufParams = {
1267         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1268         DE_NULL,                                        // const void* pNext;
1269         *secCmdPool,                                    // VkCommandPool pool;
1270         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
1271         1u,                                             // uint32_t bufferCount;
1272     };
1273     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
1274 
1275     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
1276         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1277         DE_NULL,
1278         (VkRenderPass)0u,                  // renderPass
1279         0u,                                // subpass
1280         (VkFramebuffer)0u,                 // framebuffer
1281         VK_FALSE,                          // occlusionQueryEnable
1282         (VkQueryControlFlags)0u,           // queryFlags
1283         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
1284     };
1285     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
1286         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1287         DE_NULL,
1288         0, // flags
1289         &secCmdBufInheritInfo,
1290     };
1291 
1292     // create event that will be used to check if secondary command buffer has been executed
1293     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1294 
1295     // reset event
1296     VK_CHECK(vk.resetEvent(vkDevice, *event));
1297 
1298     // record primary command buffer
1299     beginCommandBuffer(vk, *primCmdBuf, 0u);
1300     {
1301         // record secondary command buffer
1302         VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
1303         {
1304             // allow execution of event during every stage of pipeline
1305             VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1306 
1307             // define minimal amount of commands to accept
1308 #ifndef CTS_USES_VULKANSC
1309             const long long unsigned minNumCommands = 10000llu;
1310 #else
1311             const long long unsigned minNumCommands = 1000llu;
1312 #endif // CTS_USES_VULKANSC
1313 
1314             for (long long unsigned currentCommands = 0; currentCommands < minNumCommands / 2; ++currentCommands)
1315             {
1316                 // record setting event
1317                 vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
1318 
1319                 // record resetting event
1320                 vk.cmdResetEvent(*secCmdBuf, *event, stageMask);
1321             }
1322         }
1323 
1324         // end recording of secondary buffers
1325         endCommandBuffer(vk, *secCmdBuf);
1326 
1327         // execute secondary buffer
1328         vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
1329     }
1330     endCommandBuffer(vk, *primCmdBuf);
1331 
1332     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1333 
1334     return tcu::TestStatus::pass("hugeTest succeeded");
1335 }
1336 
submitPrimaryBufferTwiceTest(Context & context)1337 tcu::TestStatus submitPrimaryBufferTwiceTest(Context &context)
1338 {
1339     const VkDevice vkDevice         = context.getDevice();
1340     const DeviceInterface &vk       = context.getDeviceInterface();
1341     const VkQueue queue             = context.getUniversalQueue();
1342     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1343 
1344     const VkCommandPoolCreateInfo cmdPoolParams = {
1345         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1346         DE_NULL,                                         // const void* pNext;
1347         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1348         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1349     };
1350     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1351 
1352     // Command buffer
1353     const VkCommandBufferAllocateInfo cmdBufParams = {
1354         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1355         DE_NULL,                                        // const void* pNext;
1356         *cmdPool,                                       // VkCommandPool pool;
1357         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1358         1u,                                             // uint32_t bufferCount;
1359     };
1360     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1361 
1362     // create event that will be used to check if secondary command buffer has been executed
1363     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1364 
1365     // reset event
1366     VK_CHECK(vk.resetEvent(vkDevice, *event));
1367 
1368     // record primary command buffer
1369     beginCommandBuffer(vk, *primCmdBuf, 0u);
1370     {
1371         // allow execution of event during every stage of pipeline
1372         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1373 
1374         // record setting event
1375         vk.cmdSetEvent(*primCmdBuf, *event, stageMask);
1376     }
1377     endCommandBuffer(vk, *primCmdBuf);
1378 
1379     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1380 
1381     // check if buffer has been executed
1382     VkResult result = vk.getEventStatus(vkDevice, *event);
1383     if (result != VK_EVENT_SET)
1384         return tcu::TestStatus::fail("Submit Twice Test FAILED");
1385 
1386     // reset event
1387     VK_CHECK(vk.resetEvent(vkDevice, *event));
1388 
1389     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1390 
1391     // check if buffer has been executed
1392     result = vk.getEventStatus(vkDevice, *event);
1393     if (result != VK_EVENT_SET)
1394         return tcu::TestStatus::fail("Submit Twice Test FAILED");
1395     else
1396         return tcu::TestStatus::pass("Submit Twice Test succeeded");
1397 }
1398 
submitSecondaryBufferTwiceTest(Context & context)1399 tcu::TestStatus submitSecondaryBufferTwiceTest(Context &context)
1400 {
1401     const VkDevice vkDevice         = context.getDevice();
1402     const DeviceInterface &vk       = context.getDeviceInterface();
1403     const VkQueue queue             = context.getUniversalQueue();
1404     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1405 
1406 #ifdef CTS_USES_VULKANSC
1407     if (context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
1408         TCU_THROW(NotSupportedError, "commandPoolResetCommandBuffer not supported by this implementation");
1409 #endif // CTS_USES_VULKANSC
1410 
1411     const VkCommandPoolCreateInfo cmdPoolParams = {
1412         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1413         DE_NULL,                                         // const void* pNext;
1414         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1415         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1416     };
1417 
1418     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1419     const Unique<VkCommandPool> secCmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1420 
1421     // Command buffer
1422     const VkCommandBufferAllocateInfo cmdBufParams = {
1423         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1424         DE_NULL,                                        // const void* pNext;
1425         *cmdPool,                                       // VkCommandPool pool;
1426         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1427         1u,                                             // uint32_t bufferCount;
1428     };
1429 
1430     const Unique<VkCommandBuffer> primCmdBuf1(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1431     const Unique<VkCommandBuffer> primCmdBuf2(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1432 
1433     // Secondary Command buffer
1434     const VkCommandBufferAllocateInfo secCmdBufParams = {
1435         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1436         DE_NULL,                                        // const void* pNext;
1437         *secCmdPool,                                    // VkCommandPool pool;
1438         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
1439         1u,                                             // uint32_t bufferCount;
1440     };
1441     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
1442 
1443     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
1444         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1445         DE_NULL,
1446         (VkRenderPass)0u,                  // renderPass
1447         0u,                                // subpass
1448         (VkFramebuffer)0u,                 // framebuffer
1449         VK_FALSE,                          // occlusionQueryEnable
1450         (VkQueryControlFlags)0u,           // queryFlags
1451         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
1452     };
1453     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
1454         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1455         DE_NULL,
1456         0u, // flags
1457         &secCmdBufInheritInfo,
1458     };
1459 
1460     // create event that will be used to check if secondary command buffer has been executed
1461     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1462 
1463     // reset event
1464     VK_CHECK(vk.resetEvent(vkDevice, *event));
1465 
1466     // record first primary command buffer
1467     beginCommandBuffer(vk, *primCmdBuf1, 0u);
1468     {
1469         // record secondary command buffer
1470         VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
1471         {
1472             // allow execution of event during every stage of pipeline
1473             VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1474 
1475             // record setting event
1476             vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
1477         }
1478 
1479         // end recording of secondary buffers
1480         endCommandBuffer(vk, *secCmdBuf);
1481 
1482         // execute secondary buffer
1483         vk.cmdExecuteCommands(*primCmdBuf1, 1, &secCmdBuf.get());
1484     }
1485     endCommandBuffer(vk, *primCmdBuf1);
1486 
1487     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf1.get());
1488 
1489     // check if secondary buffer has been executed
1490     VkResult result = vk.getEventStatus(vkDevice, *event);
1491     if (result != VK_EVENT_SET)
1492         return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");
1493 
1494     // reset first primary buffer
1495     VK_CHECK(vk.resetCommandBuffer(*primCmdBuf1, 0u));
1496 
1497     // reset event to allow receiving it again
1498     VK_CHECK(vk.resetEvent(vkDevice, *event));
1499 
1500     // record second primary command buffer
1501     beginCommandBuffer(vk, *primCmdBuf2, 0u);
1502     {
1503         // execute secondary buffer
1504         vk.cmdExecuteCommands(*primCmdBuf2, 1, &secCmdBuf.get());
1505     }
1506     // end recording
1507     endCommandBuffer(vk, *primCmdBuf2);
1508 
1509     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf2.get());
1510 
1511     // check if secondary buffer has been executed
1512     result = vk.getEventStatus(vkDevice, *event);
1513     if (result != VK_EVENT_SET)
1514         return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");
1515     else
1516         return tcu::TestStatus::pass("Submit Twice Secondary Command Buffer succeeded");
1517 }
1518 
oneTimeSubmitFlagPrimaryBufferTest(Context & context)1519 tcu::TestStatus oneTimeSubmitFlagPrimaryBufferTest(Context &context)
1520 {
1521     const VkDevice vkDevice         = context.getDevice();
1522     const DeviceInterface &vk       = context.getDeviceInterface();
1523     const VkQueue queue             = context.getUniversalQueue();
1524     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1525 
1526 #ifdef CTS_USES_VULKANSC
1527     if (context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
1528         TCU_THROW(NotSupportedError, "commandPoolResetCommandBuffer not supported by this implementation");
1529 #endif // CTS_USES_VULKANSC
1530 
1531     const VkCommandPoolCreateInfo cmdPoolParams = {
1532         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1533         DE_NULL,                                         // const void* pNext;
1534         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1535         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1536     };
1537     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1538 
1539     // Command buffer
1540     const VkCommandBufferAllocateInfo cmdBufParams = {
1541         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1542         DE_NULL,                                        // const void* pNext;
1543         *cmdPool,                                       // VkCommandPool pool;
1544         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1545         1u,                                             // uint32_t bufferCount;
1546     };
1547     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1548 
1549     // create event that will be used to check if secondary command buffer has been executed
1550     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1551 
1552     // reset event
1553     VK_CHECK(vk.resetEvent(vkDevice, *event));
1554 
1555     // record primary command buffer
1556     beginCommandBuffer(vk, *primCmdBuf);
1557     {
1558         // allow execution of event during every stage of pipeline
1559         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1560 
1561         // record setting event
1562         vk.cmdSetEvent(*primCmdBuf, *event, stageMask);
1563     }
1564     endCommandBuffer(vk, *primCmdBuf);
1565 
1566     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1567 
1568     // check if buffer has been executed
1569     VkResult result = vk.getEventStatus(vkDevice, *event);
1570     if (result != VK_EVENT_SET)
1571         return tcu::TestStatus::fail("oneTimeSubmitFlagPrimaryBufferTest FAILED");
1572 
1573     // record primary command buffer again - implicit reset because of VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
1574     beginCommandBuffer(vk, *primCmdBuf);
1575     {
1576         // allow execution of event during every stage of pipeline
1577         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1578 
1579         // record setting event
1580         vk.cmdSetEvent(*primCmdBuf, *event, stageMask);
1581     }
1582     endCommandBuffer(vk, *primCmdBuf);
1583 
1584     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1585 
1586     // check if buffer has been executed
1587     result = vk.getEventStatus(vkDevice, *event);
1588     if (result != VK_EVENT_SET)
1589         return tcu::TestStatus::fail("oneTimeSubmitFlagPrimaryBufferTest FAILED");
1590     else
1591         return tcu::TestStatus::pass("oneTimeSubmitFlagPrimaryBufferTest succeeded");
1592 }
1593 
oneTimeSubmitFlagSecondaryBufferTest(Context & context)1594 tcu::TestStatus oneTimeSubmitFlagSecondaryBufferTest(Context &context)
1595 {
1596     const VkDevice vkDevice         = context.getDevice();
1597     const DeviceInterface &vk       = context.getDeviceInterface();
1598     const VkQueue queue             = context.getUniversalQueue();
1599     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1600 
1601 #ifdef CTS_USES_VULKANSC
1602     if (context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
1603         TCU_THROW(NotSupportedError, "commandPoolResetCommandBuffer not supported by this implementation");
1604 #endif // CTS_USES_VULKANSC
1605 
1606     const VkCommandPoolCreateInfo cmdPoolParams = {
1607         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1608         DE_NULL,                                         // const void* pNext;
1609         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1610         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1611     };
1612 
1613     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1614     const Unique<VkCommandPool> secCmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1615 
1616     // Command buffer
1617     const VkCommandBufferAllocateInfo cmdBufParams = {
1618         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1619         DE_NULL,                                        // const void* pNext;
1620         *cmdPool,                                       // VkCommandPool pool;
1621         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1622         1u,                                             // uint32_t bufferCount;
1623     };
1624 
1625     const Unique<VkCommandBuffer> primCmdBuf1(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1626     const Unique<VkCommandBuffer> primCmdBuf2(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1627 
1628     // Secondary Command buffer
1629     const VkCommandBufferAllocateInfo secCmdBufParams = {
1630         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1631         DE_NULL,                                        // const void* pNext;
1632         *secCmdPool,                                    // VkCommandPool pool;
1633         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
1634         1u,                                             // uint32_t bufferCount;
1635     };
1636     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
1637 
1638     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
1639         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1640         DE_NULL,
1641         (VkRenderPass)0u,                  // renderPass
1642         0u,                                // subpass
1643         (VkFramebuffer)0u,                 // framebuffer
1644         VK_FALSE,                          // occlusionQueryEnable
1645         (VkQueryControlFlags)0u,           // queryFlags
1646         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
1647     };
1648     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
1649         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1650         DE_NULL,
1651         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
1652         &secCmdBufInheritInfo,
1653     };
1654 
1655     // create event that will be used to check if secondary command buffer has been executed
1656     const Unique<VkEvent> event(createEvent(vk, vkDevice));
1657 
1658     // reset event
1659     VK_CHECK(vk.resetEvent(vkDevice, *event));
1660 
1661     // record first primary command buffer
1662     beginCommandBuffer(vk, *primCmdBuf1, 0u);
1663     {
1664         // record secondary command buffer
1665         VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
1666         {
1667             // allow execution of event during every stage of pipeline
1668             VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1669 
1670             // record setting event
1671             vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
1672         }
1673 
1674         // end recording of secondary buffers
1675         endCommandBuffer(vk, *secCmdBuf);
1676 
1677         // execute secondary buffer
1678         vk.cmdExecuteCommands(*primCmdBuf1, 1, &secCmdBuf.get());
1679     }
1680     endCommandBuffer(vk, *primCmdBuf1);
1681 
1682     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf1.get());
1683 
1684     // check if secondary buffer has been executed
1685     VkResult result = vk.getEventStatus(vkDevice, *event);
1686     if (result != VK_EVENT_SET)
1687         return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");
1688 
1689     // reset first primary buffer
1690     VK_CHECK(vk.resetCommandBuffer(*primCmdBuf1, 0u));
1691 
1692     // reset event to allow receiving it again
1693     VK_CHECK(vk.resetEvent(vkDevice, *event));
1694 
1695     // record secondary command buffer again
1696     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
1697     {
1698         // allow execution of event during every stage of pipeline
1699         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1700 
1701         // record setting event
1702         vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
1703     }
1704     // end recording of secondary buffers
1705     endCommandBuffer(vk, *secCmdBuf);
1706 
1707     // record second primary command buffer
1708     beginCommandBuffer(vk, *primCmdBuf2, 0u);
1709     {
1710         // execute secondary buffer
1711         vk.cmdExecuteCommands(*primCmdBuf2, 1, &secCmdBuf.get());
1712     }
1713     // end recording
1714     endCommandBuffer(vk, *primCmdBuf2);
1715 
1716     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf2.get());
1717 
1718     // check if secondary buffer has been executed
1719     result = vk.getEventStatus(vkDevice, *event);
1720     if (result != VK_EVENT_SET)
1721         return tcu::TestStatus::fail("oneTimeSubmitFlagSecondaryBufferTest FAILED");
1722     else
1723         return tcu::TestStatus::pass("oneTimeSubmitFlagSecondaryBufferTest succeeded");
1724 }
1725 
renderPassContinueTest(Context & context,bool framebufferHint)1726 tcu::TestStatus renderPassContinueTest(Context &context, bool framebufferHint)
1727 {
1728     const DeviceInterface &vkd = context.getDeviceInterface();
1729     CommandBufferRenderPassTestEnvironment env(context, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
1730 
1731     VkCommandBuffer primaryCommandBuffer   = env.getPrimaryCommandBuffer();
1732     VkCommandBuffer secondaryCommandBuffer = env.getSecondaryCommandBuffer();
1733     const uint32_t clearColor[4]           = {2, 47, 131, 211};
1734 
1735     const VkClearAttachment clearAttachment = {
1736         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1737         0,                         // uint32_t colorAttachment;
1738         makeClearValueColorU32(clearColor[0], clearColor[1], clearColor[2],
1739                                clearColor[3]) // VkClearValue clearValue;
1740     };
1741 
1742     const VkClearRect clearRect = {
1743         CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_AREA, // VkRect2D rect;
1744         0u,                                                         // uint32_t baseArrayLayer;
1745         1u                                                          // uint32_t layerCount;
1746     };
1747 
1748     env.beginSecondaryCommandBuffer(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, framebufferHint);
1749     vkd.cmdClearAttachments(secondaryCommandBuffer, 1, &clearAttachment, 1, &clearRect);
1750     endCommandBuffer(vkd, secondaryCommandBuffer);
1751 
1752     env.beginPrimaryCommandBuffer(0);
1753     env.beginRenderPass(VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1754     vkd.cmdExecuteCommands(primaryCommandBuffer, 1, &secondaryCommandBuffer);
1755     endRenderPass(vkd, primaryCommandBuffer);
1756 
1757     endCommandBuffer(vkd, primaryCommandBuffer);
1758 
1759     env.submitPrimaryCommandBuffer();
1760     context.resetCommandPoolForVKSC(context.getDevice(), env.getCommandPool());
1761 
1762     de::MovePtr<tcu::TextureLevel> result    = env.readColorAttachment();
1763     tcu::PixelBufferAccess pixelBufferAccess = result->getAccess();
1764 
1765     for (uint32_t i = 0; i < (CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.width *
1766                               CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.height);
1767          ++i)
1768     {
1769         uint8_t *colorData = reinterpret_cast<uint8_t *>(pixelBufferAccess.getDataPtr());
1770         for (int colorComponent = 0; colorComponent < 4; ++colorComponent)
1771             if (colorData[i * 4 + colorComponent] != clearColor[colorComponent])
1772                 return tcu::TestStatus::fail("clear value mismatch");
1773     }
1774 
1775     return tcu::TestStatus::pass("render pass continue test passed");
1776 }
1777 
simultaneousUseSecondaryBufferOnePrimaryBufferTest(Context & context)1778 tcu::TestStatus simultaneousUseSecondaryBufferOnePrimaryBufferTest(Context &context)
1779 {
1780     const VkDevice vkDevice         = context.getDevice();
1781     const DeviceInterface &vk       = context.getDeviceInterface();
1782     const VkQueue queue             = context.getUniversalQueue();
1783     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1784     Allocator &allocator            = context.getDefaultAllocator();
1785     const ComputeInstanceResultBuffer result(vk, vkDevice, allocator, 0.0f);
1786 
1787     const VkCommandPoolCreateInfo cmdPoolParams = {
1788         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1789         DE_NULL,                                         // const void* pNext;
1790         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
1791         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
1792     };
1793     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
1794 
1795     // Command buffer
1796     const VkCommandBufferAllocateInfo cmdBufParams = {
1797         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1798         DE_NULL,                                        // const void* pNext;
1799         *cmdPool,                                       // VkCommandPool pool;
1800         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
1801         1u,                                             // uint32_t bufferCount;
1802     };
1803     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
1804 
1805     // Secondary Command buffer params
1806     const VkCommandBufferAllocateInfo secCmdBufParams = {
1807         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1808         DE_NULL,                                        // const void* pNext;
1809         *cmdPool,                                       // VkCommandPool pool;
1810         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
1811         1u,                                             // uint32_t bufferCount;
1812     };
1813     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
1814 
1815     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
1816         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1817         DE_NULL,
1818         (VkRenderPass)0u,
1819         0u, // subpass
1820         (VkFramebuffer)0u,
1821         VK_FALSE, // occlusionQueryEnable
1822         (VkQueryControlFlags)0u,
1823         (VkQueryPipelineStatisticFlags)0u,
1824     };
1825     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
1826         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1827         DE_NULL,
1828         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
1829         &secCmdBufInheritInfo,
1830     };
1831 
1832     const uint32_t offset          = (0u);
1833     const uint32_t addressableSize = 256;
1834     const uint32_t dataSize        = 8;
1835     de::MovePtr<Allocation> bufferMem;
1836     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
1837     // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
1838     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
1839     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
1840     const Unique<VkDescriptorSet> descriptorSet(
1841         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
1842     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
1843     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
1844 
1845     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
1846         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1847         DE_NULL,                                       // pNext
1848         (VkPipelineLayoutCreateFlags)0,
1849         numDescriptorSets,          // setLayoutCount
1850         &descriptorSetLayout.get(), // pSetLayouts
1851         0u,                         // pushConstantRangeCount
1852         DE_NULL,                    // pPushConstantRanges
1853     };
1854     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
1855 
1856     const Unique<VkShaderModule> computeModule(createShaderModule(
1857         vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
1858 
1859     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
1860         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1861         DE_NULL,
1862         (VkPipelineShaderStageCreateFlags)0,
1863         VK_SHADER_STAGE_COMPUTE_BIT, // stage
1864         *computeModule,              // shader
1865         "main",
1866         DE_NULL, // pSpecializationInfo
1867     };
1868 
1869     const VkComputePipelineCreateInfo pipelineCreateInfo = {
1870         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1871         DE_NULL,
1872         0u,                // flags
1873         shaderCreateInfo,  // cs
1874         *pipelineLayout,   // layout
1875         (vk::VkPipeline)0, // basePipelineHandle
1876         0u,                // basePipelineIndex
1877     };
1878 
1879     const VkBufferMemoryBarrier bufferBarrier = {
1880         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
1881         DE_NULL,                                 // pNext
1882         VK_ACCESS_SHADER_WRITE_BIT,              // srcAccessMask
1883         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
1884         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
1885         VK_QUEUE_FAMILY_IGNORED,                 // destQueueFamilyIndex
1886         *buffer,                                 // buffer
1887         (VkDeviceSize)0u,                        // offset
1888         (VkDeviceSize)VK_WHOLE_SIZE,             // size
1889     };
1890 
1891     const Unique<VkPipeline> pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));
1892 
1893     // record secondary command buffer
1894     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
1895     {
1896         vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1897         vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
1898                                  descriptorSets, 0, 0);
1899         vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
1900         vk.cmdPipelineBarrier(*secCmdBuf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1901                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &bufferBarrier, 0,
1902                               (const VkImageMemoryBarrier *)DE_NULL);
1903     }
1904     // end recording of secondary buffer
1905     endCommandBuffer(vk, *secCmdBuf);
1906 
1907     // record primary command buffer
1908     beginCommandBuffer(vk, *primCmdBuf, 0u);
1909     {
1910         // execute secondary buffer twice in same primary
1911         vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
1912         vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
1913     }
1914     endCommandBuffer(vk, *primCmdBuf);
1915 
1916     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1917 
1918     uint32_t resultCount;
1919     result.readResultContentsTo(&resultCount);
1920     // check if secondary buffer has been executed
1921     if (resultCount == 2)
1922         return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
1923     else
1924         return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
1925 }
1926 
renderPassContinueNestedTest(Context & context,bool framebufferHint)1927 tcu::TestStatus renderPassContinueNestedTest(Context &context, bool framebufferHint)
1928 {
1929     context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
1930 #ifndef CTS_USES_VULKANSC
1931     const auto &features =
1932         *findStructure<VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
1933     if (!features.nestedCommandBuffer)
1934 #endif // CTS_USES_VULKANSC
1935         TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
1936 #ifndef CTS_USES_VULKANSC
1937     if (!features.nestedCommandBufferRendering)
1938 #endif // CTS_USES_VULKANSC
1939         TCU_THROW(NotSupportedError, "nestedCommandBufferRendering is not supported");
1940 
1941     const DeviceInterface &vkd = context.getDeviceInterface();
1942     CommandBufferRenderPassTestEnvironment env(context, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
1943 
1944     VkCommandBuffer primaryCommandBuffer   = env.getPrimaryCommandBuffer();
1945     VkCommandBuffer secondaryCommandBuffer = env.getSecondaryCommandBuffer();
1946     VkCommandBuffer nestedCommandBuffer    = env.getNestedCommandBuffer();
1947     const uint32_t clearColor[4]           = {2, 47, 131, 211};
1948 
1949     const VkClearAttachment clearAttachment = {
1950         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1951         0,                         // uint32_t colorAttachment;
1952         makeClearValueColorU32(clearColor[0], clearColor[1], clearColor[2],
1953                                clearColor[3]) // VkClearValue clearValue;
1954     };
1955 
1956     const uint32_t clearRectWidth  = CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.width / 2;
1957     const uint32_t clearRectHeight = CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.height / 2;
1958     const int32_t clearRectOffsetX = clearRectWidth;
1959     const int32_t clearRectOffsetY = clearRectHeight;
1960 
1961     const VkRect2D clearRectArea[4] = {{
1962                                            {0u, 0u},                          // VkOffset2D offset;
1963                                            {clearRectWidth, clearRectHeight}, // VkExtent2D extent;
1964                                        },
1965                                        {
1966                                            {0u, clearRectOffsetY},                // VkOffset2D offset;
1967                                            {clearRectWidth, clearRectHeight + 1}, // VkExtent2D extent;
1968                                        },
1969                                        {
1970                                            {clearRectOffsetX, 0u},                // VkOffset2D offset;
1971                                            {clearRectWidth + 1, clearRectHeight}, // VkExtent2D extent;
1972                                        },
1973                                        {
1974                                            {clearRectOffsetX, clearRectOffsetY},      // VkOffset2D offset;
1975                                            {clearRectWidth + 1, clearRectHeight + 1}, // VkExtent2D extent;
1976                                        }};
1977 
1978     const VkClearRect clearRect[4] = {{
1979                                           clearRectArea[0], // VkRect2D rect;
1980                                           0u,               // uint32_t baseArrayLayer;
1981                                           1u                // uint32_t layerCount;
1982                                       },
1983                                       {
1984                                           clearRectArea[1], // VkRect2D rect;
1985                                           0u,               // uint32_t baseArrayLayer;
1986                                           1u                // uint32_t layerCount;
1987                                       },
1988                                       {
1989                                           clearRectArea[2], // VkRect2D rect;
1990                                           0u,               // uint32_t baseArrayLayer;
1991                                           1u                // uint32_t layerCount;
1992                                       },
1993                                       {
1994                                           clearRectArea[3], // VkRect2D rect;
1995                                           0u,               // uint32_t baseArrayLayer;
1996                                           1u                // uint32_t layerCount;
1997                                       }};
1998 
1999     env.beginSecondaryCommandBuffer(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, framebufferHint);
2000     vkd.cmdClearAttachments(secondaryCommandBuffer, 1, &clearAttachment, 1, &clearRect[0]);
2001     endCommandBuffer(vkd, secondaryCommandBuffer);
2002 
2003     env.beginNestedCommandBuffer(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, framebufferHint);
2004     vkd.cmdExecuteCommands(nestedCommandBuffer, 1, &secondaryCommandBuffer);
2005     vkd.cmdClearAttachments(nestedCommandBuffer, 1, &clearAttachment, 1, &clearRect[1]);
2006     endCommandBuffer(vkd, nestedCommandBuffer);
2007 
2008     env.beginPrimaryCommandBuffer(0);
2009 #ifndef CTS_USES_VULKANSC
2010     env.beginRenderPass(VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT);
2011 #endif // CTS_USES_VULKANSC
2012     vkd.cmdClearAttachments(primaryCommandBuffer, 1, &clearAttachment, 1, &clearRect[2]);
2013     vkd.cmdExecuteCommands(primaryCommandBuffer, 1, &nestedCommandBuffer);
2014     vkd.cmdClearAttachments(primaryCommandBuffer, 1, &clearAttachment, 1, &clearRect[3]);
2015     endRenderPass(vkd, primaryCommandBuffer);
2016 
2017     endCommandBuffer(vkd, primaryCommandBuffer);
2018 
2019     env.submitPrimaryCommandBuffer();
2020     context.resetCommandPoolForVKSC(context.getDevice(), env.getCommandPool());
2021 
2022     de::MovePtr<tcu::TextureLevel> result    = env.readColorAttachment();
2023     tcu::PixelBufferAccess pixelBufferAccess = result->getAccess();
2024 
2025     for (uint32_t i = 0; i < (CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.width *
2026                               CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.height);
2027          ++i)
2028     {
2029         uint8_t *colorData = reinterpret_cast<uint8_t *>(pixelBufferAccess.getDataPtr());
2030         for (int colorComponent = 0; colorComponent < 4; ++colorComponent)
2031             if (colorData[i * 4 + colorComponent] != clearColor[colorComponent])
2032                 return tcu::TestStatus::fail("clear value mismatch");
2033     }
2034 
2035     return tcu::TestStatus::pass("render pass continue in nested command buffer test passed");
2036 }
2037 
simultaneousUseNestedSecondaryBufferTest(Context & context)2038 tcu::TestStatus simultaneousUseNestedSecondaryBufferTest(Context &context)
2039 {
2040     const VkDevice vkDevice         = context.getDevice();
2041     const DeviceInterface &vk       = context.getDeviceInterface();
2042     const VkQueue queue             = context.getUniversalQueue();
2043     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2044     Allocator &allocator            = context.getDefaultAllocator();
2045     const ComputeInstanceResultBuffer result(vk, vkDevice, allocator, 0.0f);
2046 
2047     const VkCommandPoolCreateInfo cmdPoolParams = {
2048         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
2049         DE_NULL,                                         // const void* pNext;
2050         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
2051         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
2052     };
2053     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2054 
2055     // Command buffer
2056     const VkCommandBufferAllocateInfo cmdBufParams = {
2057         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2058         DE_NULL,                                        // const void* pNext;
2059         *cmdPool,                                       // VkCommandPool pool;
2060         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
2061         1u,                                             // uint32_t bufferCount;
2062     };
2063     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2064 
2065     // Secondary Command buffer params
2066     const VkCommandBufferAllocateInfo secCmdBufParams = {
2067         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2068         DE_NULL,                                        // const void* pNext;
2069         *cmdPool,                                       // VkCommandPool pool;
2070         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
2071         1u,                                             // uint32_t bufferCount;
2072     };
2073     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2074     const Unique<VkCommandBuffer> nestedCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2075 
2076     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
2077         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2078         DE_NULL,
2079         (VkRenderPass)0u,
2080         0u, // subpass
2081         (VkFramebuffer)0u,
2082         VK_FALSE, // occlusionQueryEnable
2083         (VkQueryControlFlags)0u,
2084         (VkQueryPipelineStatisticFlags)0u,
2085     };
2086     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
2087         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2088         DE_NULL,
2089         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
2090         &secCmdBufInheritInfo,
2091     };
2092 
2093     const uint32_t offset          = (0u);
2094     const uint32_t addressableSize = 256;
2095     const uint32_t dataSize        = 8;
2096     de::MovePtr<Allocation> bufferMem;
2097     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2098     // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
2099     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2100     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2101     const Unique<VkDescriptorSet> descriptorSet(
2102         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2103     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2104     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2105 
2106     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
2107         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
2108         DE_NULL,                                       // pNext
2109         (VkPipelineLayoutCreateFlags)0,
2110         numDescriptorSets,          // setLayoutCount
2111         &descriptorSetLayout.get(), // pSetLayouts
2112         0u,                         // pushConstantRangeCount
2113         DE_NULL,                    // pPushConstantRanges
2114     };
2115     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
2116 
2117     const Unique<VkShaderModule> computeModule(createShaderModule(
2118         vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2119 
2120     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2121         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2122         DE_NULL,
2123         (VkPipelineShaderStageCreateFlags)0,
2124         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2125         *computeModule,              // shader
2126         "main",
2127         DE_NULL, // pSpecializationInfo
2128     };
2129 
2130     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2131         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2132         DE_NULL,
2133         0u,                // flags
2134         shaderCreateInfo,  // cs
2135         *pipelineLayout,   // layout
2136         (vk::VkPipeline)0, // basePipelineHandle
2137         0u,                // basePipelineIndex
2138     };
2139 
2140     const VkBufferMemoryBarrier bufferBarrier = {
2141         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
2142         DE_NULL,                                 // pNext
2143         VK_ACCESS_SHADER_WRITE_BIT,              // srcAccessMask
2144         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
2145         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
2146         VK_QUEUE_FAMILY_IGNORED,                 // destQueueFamilyIndex
2147         *buffer,                                 // buffer
2148         (VkDeviceSize)0u,                        // offset
2149         (VkDeviceSize)VK_WHOLE_SIZE,             // size
2150     };
2151 
2152     const Unique<VkPipeline> pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));
2153 
2154     // record secondary command buffer
2155     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
2156     {
2157         vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2158         vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2159                                  descriptorSets, 0, 0);
2160         vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
2161         vk.cmdPipelineBarrier(*secCmdBuf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2162                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &bufferBarrier, 0,
2163                               (const VkImageMemoryBarrier *)DE_NULL);
2164     }
2165     // end recording of secondary buffer
2166     endCommandBuffer(vk, *secCmdBuf);
2167 
2168     // record another secondary command buffer to nest the other into
2169     VK_CHECK(vk.beginCommandBuffer(*nestedCmdBuf, &secCmdBufBeginInfo));
2170     {
2171         // execute nested secondary buffer twice in same secondary buffer
2172         vk.cmdExecuteCommands(*nestedCmdBuf, 1, &secCmdBuf.get());
2173         vk.cmdExecuteCommands(*nestedCmdBuf, 1, &secCmdBuf.get());
2174     }
2175     endCommandBuffer(vk, *nestedCmdBuf);
2176 
2177     // record primary command buffer
2178     beginCommandBuffer(vk, *primCmdBuf, 0u);
2179     {
2180         // execute nested buffer
2181         vk.cmdExecuteCommands(*primCmdBuf, 1, &nestedCmdBuf.get());
2182     }
2183     endCommandBuffer(vk, *primCmdBuf);
2184 
2185     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
2186 
2187     uint32_t resultCount;
2188     result.readResultContentsTo(&resultCount);
2189     // check if secondary buffer has been executed
2190     if (resultCount == 2)
2191         return tcu::TestStatus::pass("Simultaneous Nested Command Buffer Execution succeeded");
2192     else
2193         return tcu::TestStatus::fail("Simultaneous Nested Command Buffer Execution FAILED");
2194 }
2195 
simultaneousUseNestedSecondaryBufferTwiceTest(Context & context)2196 tcu::TestStatus simultaneousUseNestedSecondaryBufferTwiceTest(Context &context)
2197 {
2198     const VkDevice vkDevice         = context.getDevice();
2199     const DeviceInterface &vk       = context.getDeviceInterface();
2200     const VkQueue queue             = context.getUniversalQueue();
2201     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2202     Allocator &allocator            = context.getDefaultAllocator();
2203     const ComputeInstanceResultBuffer result(vk, vkDevice, allocator, 0.0f);
2204 
2205     const VkCommandPoolCreateInfo cmdPoolParams = {
2206         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
2207         DE_NULL,                                         // const void* pNext;
2208         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
2209         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
2210     };
2211     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2212 
2213     // Command buffer
2214     const VkCommandBufferAllocateInfo cmdBufParams = {
2215         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2216         DE_NULL,                                        // const void* pNext;
2217         *cmdPool,                                       // VkCommandPool pool;
2218         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
2219         1u,                                             // uint32_t bufferCount;
2220     };
2221     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2222 
2223     // Secondary Command buffer params
2224     const VkCommandBufferAllocateInfo secCmdBufParams = {
2225         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2226         DE_NULL,                                        // const void* pNext;
2227         *cmdPool,                                       // VkCommandPool pool;
2228         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
2229         1u,                                             // uint32_t bufferCount;
2230     };
2231     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2232     const Unique<VkCommandBuffer> nestedCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2233 
2234     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
2235         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2236         DE_NULL,
2237         (VkRenderPass)0u,
2238         0u, // subpass
2239         (VkFramebuffer)0u,
2240         VK_FALSE, // occlusionQueryEnable
2241         (VkQueryControlFlags)0u,
2242         (VkQueryPipelineStatisticFlags)0u,
2243     };
2244     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
2245         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2246         DE_NULL,
2247         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
2248         &secCmdBufInheritInfo,
2249     };
2250 
2251     const uint32_t offset          = (0u);
2252     const uint32_t addressableSize = 256;
2253     const uint32_t dataSize        = 8;
2254     de::MovePtr<Allocation> bufferMem;
2255     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2256     // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
2257     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2258     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2259     const Unique<VkDescriptorSet> descriptorSet(
2260         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2261     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2262     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2263 
2264     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
2265         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
2266         DE_NULL,                                       // pNext
2267         (VkPipelineLayoutCreateFlags)0,
2268         numDescriptorSets,          // setLayoutCount
2269         &descriptorSetLayout.get(), // pSetLayouts
2270         0u,                         // pushConstantRangeCount
2271         DE_NULL,                    // pPushConstantRanges
2272     };
2273     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
2274 
2275     const Unique<VkShaderModule> computeModule(createShaderModule(
2276         vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2277 
2278     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2279         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2280         DE_NULL,
2281         (VkPipelineShaderStageCreateFlags)0,
2282         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2283         *computeModule,              // shader
2284         "main",
2285         DE_NULL, // pSpecializationInfo
2286     };
2287 
2288     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2289         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2290         DE_NULL,
2291         0u,                // flags
2292         shaderCreateInfo,  // cs
2293         *pipelineLayout,   // layout
2294         (vk::VkPipeline)0, // basePipelineHandle
2295         0u,                // basePipelineIndex
2296     };
2297 
2298     const VkBufferMemoryBarrier bufferBarrier = {
2299         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
2300         DE_NULL,                                 // pNext
2301         VK_ACCESS_SHADER_WRITE_BIT,              // srcAccessMask
2302         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
2303         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
2304         VK_QUEUE_FAMILY_IGNORED,                 // destQueueFamilyIndex
2305         *buffer,                                 // buffer
2306         (VkDeviceSize)0u,                        // offset
2307         (VkDeviceSize)VK_WHOLE_SIZE,             // size
2308     };
2309 
2310     const Unique<VkPipeline> pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));
2311 
2312     // record secondary command buffer
2313     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
2314     {
2315         vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2316         vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2317                                  descriptorSets, 0, 0);
2318         vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
2319         vk.cmdPipelineBarrier(*secCmdBuf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2320                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &bufferBarrier, 0,
2321                               (const VkImageMemoryBarrier *)DE_NULL);
2322     }
2323     // end recording of secondary buffer
2324     endCommandBuffer(vk, *secCmdBuf);
2325 
2326     // record another secondary command buffer to nest the other into
2327     VK_CHECK(vk.beginCommandBuffer(*nestedCmdBuf, &secCmdBufBeginInfo));
2328     {
2329         // execute nested secondary buffer
2330         vk.cmdExecuteCommands(*nestedCmdBuf, 1, &secCmdBuf.get());
2331     }
2332     endCommandBuffer(vk, *nestedCmdBuf);
2333 
2334     // record primary command buffer
2335     beginCommandBuffer(vk, *primCmdBuf, 0u);
2336     {
2337         // execute nested secondary buffers twice in same primary buffer
2338         vk.cmdExecuteCommands(*primCmdBuf, 1, &nestedCmdBuf.get());
2339         vk.cmdExecuteCommands(*primCmdBuf, 1, &nestedCmdBuf.get());
2340     }
2341     endCommandBuffer(vk, *primCmdBuf);
2342 
2343     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
2344 
2345     uint32_t resultCount;
2346     result.readResultContentsTo(&resultCount);
2347     // check if secondary buffer has been executed
2348     if (resultCount == 2)
2349         return tcu::TestStatus::pass("Simultaneous Nested Command Buffer Execution succeeded");
2350     else
2351         return tcu::TestStatus::fail("Simultaneous Nested Command Buffer Execution FAILED");
2352 }
2353 
2354 enum class BadInheritanceInfoCase
2355 {
2356     RANDOM_PTR = 0,
2357     RANDOM_PTR_CONTINUATION,
2358     RANDOM_DATA_PTR,
2359     INVALID_STRUCTURE_TYPE,
2360     VALID_NONSENSE_TYPE,
2361 };
2362 
badInheritanceInfoTest(Context & context,BadInheritanceInfoCase testCase)2363 tcu::TestStatus badInheritanceInfoTest(Context &context, BadInheritanceInfoCase testCase)
2364 {
2365     const auto &vkd             = context.getDeviceInterface();
2366     const auto device           = context.getDevice();
2367     const auto queue            = context.getUniversalQueue();
2368     const auto queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2369     auto &allocator             = context.getDefaultAllocator();
2370     const ComputeInstanceResultBuffer result(vkd, device, allocator, 0.0f);
2371 
2372     // Command pool and command buffer.
2373     const auto cmdPool      = makeCommandPool(vkd, device, queueFamilyIndex);
2374     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2375     const auto cmdBuffer    = cmdBufferPtr.get();
2376 
2377     // Buffers, descriptor set layouts and descriptor sets.
2378     const uint32_t offset          = 0u;
2379     const uint32_t addressableSize = 256u;
2380     const uint32_t dataSize        = 8u;
2381 
2382     // The uniform buffer will not be used by the shader but is needed by auxiliar functions here.
2383     de::MovePtr<Allocation> bufferMem;
2384     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2385 
2386     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2387     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2388     const Unique<VkDescriptorSet> descriptorSet(
2389         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2390     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2391     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2392 
2393     // Pipeline layout.
2394     const auto pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
2395 
2396     // Compute shader module.
2397     const Unique<VkShaderModule> computeModule(createShaderModule(
2398         vkd, device, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2399 
2400     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2401         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2402         DE_NULL,
2403         (VkPipelineShaderStageCreateFlags)0,
2404         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2405         *computeModule,              // shader
2406         "main",
2407         DE_NULL, // pSpecializationInfo
2408     };
2409 
2410     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2411         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2412         DE_NULL,
2413         0u,                // flags
2414         shaderCreateInfo,  // cs
2415         *pipelineLayout,   // layout
2416         (vk::VkPipeline)0, // basePipelineHandle
2417         0u,                // basePipelineIndex
2418     };
2419 
2420     const Unique<VkPipeline> pipeline(createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo));
2421 
2422     // Compute to host barrier to read result.
2423     const VkBufferMemoryBarrier bufferBarrier = {
2424         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
2425         DE_NULL,                                 // pNext
2426         VK_ACCESS_SHADER_WRITE_BIT,              // srcAccessMask
2427         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
2428         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
2429         VK_QUEUE_FAMILY_IGNORED,                 // destQueueFamilyIndex
2430         *buffer,                                 // buffer
2431         (VkDeviceSize)0u,                        // offset
2432         (VkDeviceSize)VK_WHOLE_SIZE,             // size
2433     };
2434 
2435     // Record command buffer and submit it.
2436     VkCommandBufferBeginInfo beginInfo = {
2437         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
2438         nullptr,                                     // const void* pNext;
2439         0u,                                          // VkCommandBufferUsageFlags flags;
2440         nullptr,                                     // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
2441     };
2442 
2443     // Structures used in different test types.
2444     VkCommandBufferInheritanceInfo inheritanceInfo;
2445     VkBufferCreateInfo validNonsenseStructure;
2446     struct
2447     {
2448         VkStructureType sType;
2449         void *pNext;
2450     } invalidStructure;
2451 
2452     if (testCase == BadInheritanceInfoCase::RANDOM_PTR || testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
2453     {
2454         de::Random rnd(1602600778u);
2455         VkCommandBufferInheritanceInfo *info;
2456         auto ptrData = reinterpret_cast<uint8_t *>(&info);
2457 
2458         // Fill pointer value with pseudorandom garbage.
2459         for (size_t i = 0; i < sizeof(info); ++i)
2460             *ptrData++ = rnd.getUint8();
2461 
2462         beginInfo.pInheritanceInfo = info;
2463 
2464         // Try to trick the implementation into reading pInheritanceInfo one more way.
2465         if (testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
2466             beginInfo.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
2467     }
2468     else if (testCase == BadInheritanceInfoCase::RANDOM_DATA_PTR)
2469     {
2470         de::Random rnd(1602601141u);
2471         auto itr = reinterpret_cast<uint8_t *>(&inheritanceInfo);
2472 
2473         // Fill inheritance info data structure with random data.
2474         for (size_t i = 0; i < sizeof(inheritanceInfo); ++i)
2475             *itr++ = rnd.getUint8();
2476 
2477         beginInfo.pInheritanceInfo = &inheritanceInfo;
2478     }
2479     else if (testCase == BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE)
2480     {
2481         de::Random rnd(1602658515u);
2482         auto ptrData           = reinterpret_cast<uint8_t *>(&(invalidStructure.pNext));
2483         invalidStructure.sType = VK_STRUCTURE_TYPE_MAX_ENUM;
2484 
2485         // Fill pNext pointer with random data.
2486         for (size_t i = 0; i < sizeof(invalidStructure.pNext); ++i)
2487             *ptrData++ = rnd.getUint8();
2488 
2489         beginInfo.pInheritanceInfo = reinterpret_cast<VkCommandBufferInheritanceInfo *>(&invalidStructure);
2490     }
2491     else if (testCase == BadInheritanceInfoCase::VALID_NONSENSE_TYPE)
2492     {
2493         validNonsenseStructure.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
2494         validNonsenseStructure.pNext                 = nullptr;
2495         validNonsenseStructure.flags                 = 0u;
2496         validNonsenseStructure.size                  = 1024u;
2497         validNonsenseStructure.usage                 = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2498         validNonsenseStructure.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
2499         validNonsenseStructure.queueFamilyIndexCount = 0u;
2500         validNonsenseStructure.pQueueFamilyIndices   = nullptr;
2501 
2502         beginInfo.pInheritanceInfo = reinterpret_cast<VkCommandBufferInheritanceInfo *>(&validNonsenseStructure);
2503     }
2504     else
2505     {
2506         DE_ASSERT(false);
2507     }
2508 
2509     VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &beginInfo));
2510     {
2511         vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2512         vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2513                                   descriptorSets, 0, 0);
2514         vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
2515         vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2516                                (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &bufferBarrier, 0,
2517                                (const VkImageMemoryBarrier *)DE_NULL);
2518     }
2519     endCommandBuffer(vkd, cmdBuffer);
2520     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2521 
2522     uint32_t resultCount;
2523     result.readResultContentsTo(&resultCount);
2524 
2525     // Make sure the command buffer was run.
2526     if (resultCount != 1u)
2527     {
2528         std::ostringstream msg;
2529         msg << "Invalid value found in results buffer (expected value 1u but found " << resultCount << ")";
2530         return tcu::TestStatus::fail(msg.str());
2531     }
2532 
2533     return tcu::TestStatus::pass("Pass");
2534 }
2535 
simultaneousUseSecondaryBufferTwoPrimaryBuffersTest(Context & context)2536 tcu::TestStatus simultaneousUseSecondaryBufferTwoPrimaryBuffersTest(Context &context)
2537 {
2538     const VkDevice vkDevice         = context.getDevice();
2539     const DeviceInterface &vk       = context.getDeviceInterface();
2540     const VkQueue queue             = context.getUniversalQueue();
2541     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2542     Allocator &allocator            = context.getDefaultAllocator();
2543     const ComputeInstanceResultBuffer result(vk, vkDevice, allocator, 0.0f);
2544 
2545     const VkCommandPoolCreateInfo cmdPoolParams = {
2546         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
2547         DE_NULL,                                         // const void* pNext;
2548         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
2549         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
2550     };
2551     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2552 
2553     // Command buffer
2554     const VkCommandBufferAllocateInfo cmdBufParams = {
2555         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2556         DE_NULL,                                        // const void* pNext;
2557         *cmdPool,                                       // VkCommandPool pool;
2558         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
2559         1u,                                             // uint32_t bufferCount;
2560     };
2561     // Two separate primary cmd buffers that will be executed with the same secondary cmd buffer
2562     const uint32_t numPrimCmdBufs = 2;
2563     const Unique<VkCommandBuffer> primCmdBufOne(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2564     const Unique<VkCommandBuffer> primCmdBufTwo(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2565     VkCommandBuffer primCmdBufs[numPrimCmdBufs];
2566     primCmdBufs[0] = primCmdBufOne.get();
2567     primCmdBufs[1] = primCmdBufTwo.get();
2568 
2569     // Secondary Command buffer params
2570     const VkCommandBufferAllocateInfo secCmdBufParams = {
2571         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2572         DE_NULL,                                        // const void* pNext;
2573         *cmdPool,                                       // VkCommandPool pool;
2574         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
2575         1u,                                             // uint32_t bufferCount;
2576     };
2577     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2578 
2579     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
2580         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2581         DE_NULL,
2582         0, // flags
2583         (const VkCommandBufferInheritanceInfo *)DE_NULL,
2584     };
2585 
2586     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
2587         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2588         DE_NULL,
2589         (VkRenderPass)0u,                  // renderPass
2590         0u,                                // subpass
2591         (VkFramebuffer)0u,                 // framebuffer
2592         VK_FALSE,                          // occlusionQueryEnable
2593         (VkQueryControlFlags)0u,           // queryFlags
2594         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2595     };
2596     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
2597         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2598         DE_NULL,
2599         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
2600         &secCmdBufInheritInfo,
2601     };
2602 
2603     const uint32_t offset          = (0u);
2604     const uint32_t addressableSize = 256;
2605     const uint32_t dataSize        = 8;
2606     de::MovePtr<Allocation> bufferMem;
2607     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2608     // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
2609     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2610     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2611     const Unique<VkDescriptorSet> descriptorSet(
2612         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2613     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2614     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2615 
2616     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
2617         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
2618         DE_NULL,                                       // pNext
2619         (VkPipelineLayoutCreateFlags)0,
2620         numDescriptorSets,          // setLayoutCount
2621         &descriptorSetLayout.get(), // pSetLayouts
2622         0u,                         // pushConstantRangeCount
2623         DE_NULL,                    // pPushConstantRanges
2624     };
2625     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
2626 
2627     const Unique<VkShaderModule> computeModule(createShaderModule(
2628         vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2629 
2630     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2631         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2632         DE_NULL,
2633         (VkPipelineShaderStageCreateFlags)0,
2634         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2635         *computeModule,              // shader
2636         "main",
2637         DE_NULL, // pSpecializationInfo
2638     };
2639 
2640     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2641         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2642         DE_NULL,
2643         0u,                // flags
2644         shaderCreateInfo,  // cs
2645         *pipelineLayout,   // layout
2646         (vk::VkPipeline)0, // basePipelineHandle
2647         0u,                // basePipelineIndex
2648     };
2649 
2650     const Unique<VkPipeline> pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));
2651 
2652     // record secondary command buffer
2653     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
2654     {
2655         vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2656         vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2657                                  descriptorSets, 0, 0);
2658         vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
2659     }
2660     // end recording of secondary buffer
2661     endCommandBuffer(vk, *secCmdBuf);
2662 
2663     // record primary command buffers
2664     // Insert one instance of same secondary command buffer into two separate primary command buffers
2665     VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
2666     {
2667         vk.cmdExecuteCommands(*primCmdBufOne, 1, &secCmdBuf.get());
2668     }
2669     endCommandBuffer(vk, *primCmdBufOne);
2670 
2671     VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
2672     {
2673         vk.cmdExecuteCommands(*primCmdBufTwo, 1, &secCmdBuf.get());
2674     }
2675     endCommandBuffer(vk, *primCmdBufTwo);
2676 
2677     // create fence to wait for execution of queue
2678     const Unique<VkFence> fence(createFence(vk, vkDevice));
2679 
2680     const VkSubmitInfo submitInfo = {
2681         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
2682         DE_NULL,                               // pNext
2683         0u,                                    // waitSemaphoreCount
2684         DE_NULL,                               // pWaitSemaphores
2685         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
2686         numPrimCmdBufs,                        // commandBufferCount
2687         primCmdBufs,                           // pCommandBuffers
2688         0u,                                    // signalSemaphoreCount
2689         DE_NULL,                               // pSignalSemaphores
2690     };
2691 
2692     // submit primary buffers, the secondary should be executed too
2693     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
2694 
2695     // wait for end of execution of queue
2696     VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
2697 
2698     uint32_t resultCount;
2699     result.readResultContentsTo(&resultCount);
2700     // check if secondary buffer has been executed
2701     if (resultCount == 2)
2702         return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
2703     else
2704         return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
2705 }
2706 
recordBufferQueryPreciseWithFlagTest(Context & context)2707 tcu::TestStatus recordBufferQueryPreciseWithFlagTest(Context &context)
2708 {
2709     const VkDevice vkDevice         = context.getDevice();
2710     const DeviceInterface &vk       = context.getDeviceInterface();
2711     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2712 
2713     if (!context.getDeviceFeatures().inheritedQueries)
2714         TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
2715 
2716     const VkCommandPoolCreateInfo cmdPoolParams = {
2717         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
2718         DE_NULL,                                         // pNext;
2719         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
2720         queueFamilyIndex,                                // queueFamilyIndex;
2721     };
2722     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2723 
2724     // Command buffer
2725     const VkCommandBufferAllocateInfo primCmdBufParams = {
2726         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2727         DE_NULL,                                        // pNext;
2728         *cmdPool,                                       // pool;
2729         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
2730         1u,                                             // flags;
2731     };
2732     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
2733 
2734     // Secondary Command buffer params
2735     const VkCommandBufferAllocateInfo secCmdBufParams = {
2736         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2737         DE_NULL,                                        // pNext;
2738         *cmdPool,                                       // pool;
2739         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
2740         1u,                                             // flags;
2741     };
2742     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2743 
2744     const VkCommandBufferBeginInfo primBufferBeginInfo = {
2745         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2746         DE_NULL,                                     // pNext
2747         0u,                                          // flags
2748         (const VkCommandBufferInheritanceInfo *)DE_NULL,
2749     };
2750 
2751     const VkCommandBufferInheritanceInfo secBufferInheritInfo = {
2752         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2753         DE_NULL,
2754         0u,                                // renderPass
2755         0u,                                // subpass
2756         0u,                                // framebuffer
2757         VK_TRUE,                           // occlusionQueryEnable
2758         VK_QUERY_CONTROL_PRECISE_BIT,      // queryFlags
2759         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2760     };
2761     const VkCommandBufferBeginInfo secBufferBeginInfo = {
2762         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2763         DE_NULL,                                     // pNext
2764         0u,                                          // flags
2765         &secBufferInheritInfo,
2766     };
2767 
2768     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
2769         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
2770         DE_NULL,                                  // pNext
2771         (VkQueryPoolCreateFlags)0,                // flags
2772         VK_QUERY_TYPE_OCCLUSION,                  // queryType
2773         1u,                                       // entryCount
2774         0u,                                       // pipelineStatistics
2775     };
2776     Unique<VkQueryPool> queryPool(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
2777 
2778     VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
2779     endCommandBuffer(vk, secCmdBuf.get());
2780 
2781     VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
2782     {
2783         vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
2784         vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, VK_QUERY_CONTROL_PRECISE_BIT);
2785         {
2786             vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
2787         }
2788         vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
2789     }
2790     endCommandBuffer(vk, primCmdBuf.get());
2791 
2792     return tcu::TestStatus::pass(
2793         "Successfully recorded a secondary command buffer allowing a precise occlusion query.");
2794 }
2795 
recordBufferQueryImpreciseWithFlagTest(Context & context)2796 tcu::TestStatus recordBufferQueryImpreciseWithFlagTest(Context &context)
2797 {
2798     const VkDevice vkDevice         = context.getDevice();
2799     const DeviceInterface &vk       = context.getDeviceInterface();
2800     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2801 
2802     if (!context.getDeviceFeatures().inheritedQueries)
2803         TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
2804 
2805     const VkCommandPoolCreateInfo cmdPoolParams = {
2806         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
2807         DE_NULL,                                         // pNext;
2808         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
2809         queueFamilyIndex,                                // queueFamilyIndex;
2810     };
2811     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2812 
2813     // Command buffer
2814     const VkCommandBufferAllocateInfo primCmdBufParams = {
2815         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2816         DE_NULL,                                        // pNext;
2817         *cmdPool,                                       // pool;
2818         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
2819         1u,                                             // flags;
2820     };
2821     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
2822 
2823     // Secondary Command buffer params
2824     const VkCommandBufferAllocateInfo secCmdBufParams = {
2825         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2826         DE_NULL,                                        // pNext;
2827         *cmdPool,                                       // pool;
2828         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
2829         1u,                                             // flags;
2830     };
2831     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2832 
2833     const VkCommandBufferBeginInfo primBufferBeginInfo = {
2834         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2835         DE_NULL,                                     // pNext
2836         0u,                                          // flags
2837         (const VkCommandBufferInheritanceInfo *)DE_NULL,
2838     };
2839 
2840     const VkCommandBufferInheritanceInfo secBufferInheritInfo = {
2841         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2842         DE_NULL,
2843         0u,                                // renderPass
2844         0u,                                // subpass
2845         0u,                                // framebuffer
2846         VK_TRUE,                           // occlusionQueryEnable
2847         VK_QUERY_CONTROL_PRECISE_BIT,      // queryFlags
2848         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2849     };
2850     const VkCommandBufferBeginInfo secBufferBeginInfo = {
2851         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2852         DE_NULL,                                     // pNext
2853         0u,                                          // flags
2854         &secBufferInheritInfo,
2855     };
2856 
2857     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
2858         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
2859         DE_NULL,                                  // pNext
2860         0u,                                       // flags
2861         VK_QUERY_TYPE_OCCLUSION,                  // queryType
2862         1u,                                       // entryCount
2863         0u,                                       // pipelineStatistics
2864     };
2865     Unique<VkQueryPool> queryPool(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
2866 
2867     VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
2868     endCommandBuffer(vk, secCmdBuf.get());
2869 
2870     VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
2871     {
2872         vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
2873         vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, 0u);
2874         {
2875             vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
2876         }
2877         vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
2878     }
2879     endCommandBuffer(vk, primCmdBuf.get());
2880 
2881     return tcu::TestStatus::pass(
2882         "Successfully recorded an imprecise query with a secondary command buffer allowing a precise occlusion query.");
2883 }
2884 
recordBufferQueryImpreciseWithoutFlagTest(Context & context)2885 tcu::TestStatus recordBufferQueryImpreciseWithoutFlagTest(Context &context)
2886 {
2887     const VkDevice vkDevice         = context.getDevice();
2888     const DeviceInterface &vk       = context.getDeviceInterface();
2889     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2890 
2891     if (!context.getDeviceFeatures().inheritedQueries)
2892         TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
2893 
2894     const VkCommandPoolCreateInfo cmdPoolParams = {
2895         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
2896         DE_NULL,                                         // pNext;
2897         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
2898         queueFamilyIndex,                                // queueFamilyIndex;
2899     };
2900     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2901 
2902     // Command buffer
2903     const VkCommandBufferAllocateInfo primCmdBufParams = {
2904         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2905         DE_NULL,                                        // pNext;
2906         *cmdPool,                                       // pool;
2907         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
2908         1u,                                             // flags;
2909     };
2910     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
2911 
2912     // Secondary Command buffer params
2913     const VkCommandBufferAllocateInfo secCmdBufParams = {
2914         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2915         DE_NULL,                                        // pNext;
2916         *cmdPool,                                       // pool;
2917         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
2918         1u,                                             // flags;
2919     };
2920     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2921 
2922     const VkCommandBufferBeginInfo primBufferBeginInfo = {
2923         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2924         DE_NULL,                                     // pNext
2925         0u,                                          // flags
2926         (const VkCommandBufferInheritanceInfo *)DE_NULL,
2927     };
2928 
2929     const VkCommandBufferInheritanceInfo secBufferInheritInfo = {
2930         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2931         DE_NULL,
2932         0u,                                // renderPass
2933         0u,                                // subpass
2934         0u,                                // framebuffer
2935         VK_TRUE,                           // occlusionQueryEnable
2936         0u,                                // queryFlags
2937         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2938     };
2939     const VkCommandBufferBeginInfo secBufferBeginInfo = {
2940         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2941         DE_NULL,                                     // pNext
2942         0u,                                          // flags
2943         &secBufferInheritInfo,
2944     };
2945 
2946     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
2947         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
2948         DE_NULL,                                  // pNext
2949         (VkQueryPoolCreateFlags)0,
2950         VK_QUERY_TYPE_OCCLUSION,
2951         1u,
2952         0u,
2953     };
2954     Unique<VkQueryPool> queryPool(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
2955 
2956     VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
2957     endCommandBuffer(vk, secCmdBuf.get());
2958 
2959     VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
2960     {
2961         vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
2962         vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, 0u);
2963         {
2964             vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
2965         }
2966         vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
2967     }
2968     endCommandBuffer(vk, primCmdBuf.get());
2969 
2970     return tcu::TestStatus::pass("Successfully recorded an imprecise query with a secondary command buffer not "
2971                                  "allowing a precise occlusion query.");
2972 }
2973 
2974 /******** 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) ****************/
submitBufferCountNonZero(Context & context)2975 tcu::TestStatus submitBufferCountNonZero(Context &context)
2976 {
2977     const VkDevice vkDevice         = context.getDevice();
2978     const DeviceInterface &vk       = context.getDeviceInterface();
2979     const VkQueue queue             = context.getUniversalQueue();
2980     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2981 
2982     const uint32_t BUFFER_COUNT = 5u;
2983 
2984     const VkCommandPoolCreateInfo cmdPoolParams = {
2985         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
2986         DE_NULL,                                    // pNext;
2987         0u,                                         // flags;
2988         queueFamilyIndex,                           // queueFamilyIndex;
2989     };
2990     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2991 
2992     // Command buffer
2993     const VkCommandBufferAllocateInfo cmdBufParams = {
2994         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2995         DE_NULL,                                        // pNext;
2996         *cmdPool,                                       // pool;
2997         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
2998         BUFFER_COUNT,                                   // bufferCount;
2999     };
3000     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3001     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3002 
3003     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3004         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3005         DE_NULL,                                     // pNext
3006         0u,                                          // flags
3007         (const VkCommandBufferInheritanceInfo *)DE_NULL,
3008     };
3009 
3010     std::vector<VkEventSp> events;
3011     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3012     {
3013         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3014     }
3015 
3016     VkCommandBuffer cmdBufferHandles[BUFFER_COUNT];
3017 
3018     // Record the command buffers
3019     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3020     {
3021         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3022         {
3023             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3024         }
3025         endCommandBuffer(vk, cmdBuffers[ndx].get());
3026         cmdBufferHandles[ndx] = cmdBuffers[ndx].get();
3027     }
3028 
3029     // We'll use a fence to wait for the execution of the queue
3030     const Unique<VkFence> fence(createFence(vk, vkDevice));
3031 
3032     const VkSubmitInfo submitInfo = {
3033         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
3034         DE_NULL,                               // pNext
3035         0u,                                    // waitSemaphoreCount
3036         DE_NULL,                               // pWaitSemaphores
3037         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
3038         BUFFER_COUNT,                          // commandBufferCount
3039         cmdBufferHandles,                      // pCommandBuffers
3040         0u,                                    // signalSemaphoreCount
3041         DE_NULL,                               // pSignalSemaphores
3042     };
3043 
3044     // Submit the alpha command buffer to the queue
3045     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence.get()));
3046     // Wait for the queue
3047     VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
3048 
3049     // Check if the buffers were executed
3050     tcu::TestStatus testResult = tcu::TestStatus::incomplete();
3051 
3052     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3053     {
3054         if (vk.getEventStatus(vkDevice, events[ndx]->get()) != VK_EVENT_SET)
3055         {
3056             testResult = tcu::TestStatus::fail("Failed to set the event.");
3057             break;
3058         }
3059     }
3060 
3061     if (!testResult.isComplete())
3062         testResult = tcu::TestStatus::pass("All buffers were submitted and executed correctly.");
3063 
3064     return testResult;
3065 }
3066 
submitBufferCountEqualZero(Context & context)3067 tcu::TestStatus submitBufferCountEqualZero(Context &context)
3068 {
3069     const VkDevice vkDevice         = context.getDevice();
3070     const DeviceInterface &vk       = context.getDeviceInterface();
3071     const VkQueue queue             = context.getUniversalQueue();
3072     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3073 
3074     const uint32_t BUFFER_COUNT = 2u;
3075 
3076     const VkCommandPoolCreateInfo cmdPoolParams = {
3077         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
3078         DE_NULL,                                    // pNext;
3079         0u,                                         // flags;
3080         queueFamilyIndex,                           // queueFamilyIndex;
3081     };
3082     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3083 
3084     // Command buffer
3085     const VkCommandBufferAllocateInfo cmdBufParams = {
3086         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3087         DE_NULL,                                        // pNext;
3088         *cmdPool,                                       // pool;
3089         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3090         BUFFER_COUNT,                                   // bufferCount;
3091     };
3092     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3093     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3094 
3095     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3096         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3097         DE_NULL,                                     // pNext
3098         0u,                                          // flags
3099         (const VkCommandBufferInheritanceInfo *)DE_NULL,
3100     };
3101 
3102     std::vector<VkEventSp> events;
3103     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3104         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3105 
3106     // Record the command buffers
3107     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3108     {
3109         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3110         {
3111             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3112         }
3113         endCommandBuffer(vk, cmdBuffers[ndx].get());
3114     }
3115 
3116     // We'll use a fence to wait for the execution of the queue
3117     const Unique<VkFence> fenceZero(createFence(vk, vkDevice));
3118     const Unique<VkFence> fenceOne(createFence(vk, vkDevice));
3119 
3120     VkCommandBuffer cmdBuf0                = cmdBuffers[0].get();
3121     const VkSubmitInfo submitInfoCountZero = {
3122         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
3123         DE_NULL,                               // pNext
3124         0u,                                    // waitSemaphoreCount
3125         DE_NULL,                               // pWaitSemaphores
3126         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
3127         1u,                                    // commandBufferCount
3128         &cmdBuf0,                              // pCommandBuffers
3129         0u,                                    // signalSemaphoreCount
3130         DE_NULL,                               // pSignalSemaphores
3131     };
3132 
3133     VkCommandBuffer cmdBuf1               = cmdBuffers[1].get();
3134     const VkSubmitInfo submitInfoCountOne = {
3135         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
3136         DE_NULL,                               // pNext
3137         0u,                                    // waitSemaphoreCount
3138         DE_NULL,                               // pWaitSemaphores
3139         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
3140         1u,                                    // commandBufferCount
3141         &cmdBuf1,                              // pCommandBuffers
3142         0u,                                    // signalSemaphoreCount
3143         DE_NULL,                               // pSignalSemaphores
3144     };
3145 
3146     // Submit the command buffers to the queue
3147     // We're performing two submits to make sure that the first one has
3148     // a chance to be processed before we check the event's status
3149     VK_CHECK(vk.queueSubmit(queue, 0, &submitInfoCountZero, fenceZero.get()));
3150     VK_CHECK(vk.queueSubmit(queue, 1, &submitInfoCountOne, fenceOne.get()));
3151 
3152     const VkFence fences[] = {
3153         fenceZero.get(),
3154         fenceOne.get(),
3155     };
3156 
3157     // Wait for the queue
3158     VK_CHECK(vk.waitForFences(vkDevice, (uint32_t)DE_LENGTH_OF_ARRAY(fences), fences, VK_TRUE, INFINITE_TIMEOUT));
3159 
3160     // Check if the first buffer was executed
3161     tcu::TestStatus testResult = tcu::TestStatus::incomplete();
3162 
3163     if (vk.getEventStatus(vkDevice, events[0]->get()) == VK_EVENT_SET)
3164         testResult = tcu::TestStatus::fail("The first event was signaled.");
3165     else
3166         testResult = tcu::TestStatus::pass("The first submission was ignored.");
3167 
3168     return testResult;
3169 }
3170 
submitBufferWaitSingleSemaphore(Context & context)3171 tcu::TestStatus submitBufferWaitSingleSemaphore(Context &context)
3172 {
3173     const VkDevice vkDevice         = context.getDevice();
3174     const DeviceInterface &vk       = context.getDeviceInterface();
3175     const VkQueue queue             = context.getUniversalQueue();
3176     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3177 
3178     const VkCommandPoolCreateInfo cmdPoolParams = {
3179         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
3180         DE_NULL,                                         // const void* pNext;
3181         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
3182         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
3183     };
3184     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3185 
3186     // Command buffer
3187     const VkCommandBufferAllocateInfo cmdBufParams = {
3188         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3189         DE_NULL,                                        // const void* pNext;
3190         *cmdPool,                                       // VkCommandPool pool;
3191         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
3192         1u,                                             // uint32_t bufferCount;
3193     };
3194 
3195     // Create two command buffers
3196     const Unique<VkCommandBuffer> primCmdBuf1(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3197     const Unique<VkCommandBuffer> primCmdBuf2(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3198 
3199     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3200         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3201         DE_NULL,                                     // pNext
3202         0,                                           // flags
3203         DE_NULL                                      // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
3204     };
3205 
3206     // create two events that will be used to check if command buffers has been executed
3207     const Unique<VkEvent> event1(createEvent(vk, vkDevice));
3208     const Unique<VkEvent> event2(createEvent(vk, vkDevice));
3209 
3210     // reset events
3211     VK_CHECK(vk.resetEvent(vkDevice, *event1));
3212     VK_CHECK(vk.resetEvent(vkDevice, *event2));
3213 
3214     // record first command buffer
3215     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf1, &primCmdBufBeginInfo));
3216     {
3217         // allow execution of event during every stage of pipeline
3218         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3219 
3220         // record setting event
3221         vk.cmdSetEvent(*primCmdBuf1, *event1, stageMask);
3222     }
3223     endCommandBuffer(vk, *primCmdBuf1);
3224 
3225     // record second command buffer
3226     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf2, &primCmdBufBeginInfo));
3227     {
3228         // allow execution of event during every stage of pipeline
3229         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3230 
3231         // record setting event
3232         vk.cmdSetEvent(*primCmdBuf2, *event2, stageMask);
3233     }
3234     endCommandBuffer(vk, *primCmdBuf2);
3235 
3236     // create fence to wait for execution of queue
3237     const Unique<VkFence> fence(createFence(vk, vkDevice));
3238 
3239     // create semaphore for use in this test
3240     const Unique<VkSemaphore> semaphore(createSemaphore(vk, vkDevice));
3241 
3242     // create submit info for first buffer - signalling semaphore
3243     const VkSubmitInfo submitInfo1 = {
3244         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3245         DE_NULL,                       // pNext
3246         0u,                            // waitSemaphoreCount
3247         DE_NULL,                       // pWaitSemaphores
3248         DE_NULL,                       // pWaitDstStageMask
3249         1,                             // commandBufferCount
3250         &primCmdBuf1.get(),            // pCommandBuffers
3251         1u,                            // signalSemaphoreCount
3252         &semaphore.get(),              // pSignalSemaphores
3253     };
3254 
3255     // Submit the command buffer to the queue
3256     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));
3257 
3258     // wait for end of execution of queue
3259     VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
3260 
3261     // check if buffer has been executed
3262     VkResult result = vk.getEventStatus(vkDevice, *event1);
3263     if (result != VK_EVENT_SET)
3264         return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");
3265 
3266     const VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
3267 
3268     // create submit info for second buffer - waiting for semaphore
3269     const VkSubmitInfo submitInfo2 = {
3270         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3271         DE_NULL,                       // pNext
3272         1u,                            // waitSemaphoreCount
3273         &semaphore.get(),              // pWaitSemaphores
3274         &waitDstStageFlags,            // pWaitDstStageMask
3275         1,                             // commandBufferCount
3276         &primCmdBuf2.get(),            // pCommandBuffers
3277         0u,                            // signalSemaphoreCount
3278         DE_NULL,                       // pSignalSemaphores
3279     };
3280 
3281     // reset fence, so it can be used again
3282     VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
3283 
3284     // Submit the second command buffer to the queue
3285     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));
3286 
3287     // wait for end of execution of queue
3288     VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
3289 
3290     // check if second buffer has been executed
3291     // if it has been executed, it means that the semaphore was signalled - so test if passed
3292     result = vk.getEventStatus(vkDevice, *event1);
3293     if (result != VK_EVENT_SET)
3294         return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");
3295 
3296     return tcu::TestStatus::pass("Submit Buffer and Wait for Single Semaphore Test succeeded");
3297 }
3298 
submitBufferWaitManySemaphores(Context & context)3299 tcu::TestStatus submitBufferWaitManySemaphores(Context &context)
3300 {
3301     // This test will create numSemaphores semaphores, and signal them in NUM_SEMAPHORES submits to queue
3302     // After that the numSubmissions queue submissions will wait for each semaphore
3303 
3304     const uint32_t numSemaphores    = 10u; // it must be multiply of numSubmission
3305     const uint32_t numSubmissions   = 2u;
3306     const VkDevice vkDevice         = context.getDevice();
3307     const DeviceInterface &vk       = context.getDeviceInterface();
3308     const VkQueue queue             = context.getUniversalQueue();
3309     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3310 
3311     const VkCommandPoolCreateInfo cmdPoolParams = {
3312         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
3313         DE_NULL,                                         // const void* pNext;
3314         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
3315         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
3316     };
3317     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3318 
3319     // Command buffer
3320     const VkCommandBufferAllocateInfo cmdBufParams = {
3321         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3322         DE_NULL,                                        // const void* pNext;
3323         *cmdPool,                                       // VkCommandPool pool;
3324         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
3325         1u,                                             // uint32_t bufferCount;
3326     };
3327 
3328     // Create command buffer
3329     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3330 
3331     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3332         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3333         DE_NULL,                                     // pNext
3334         0,                                           // flags
3335         DE_NULL                                      // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
3336     };
3337 
3338     // create event that will be used to check if command buffers has been executed
3339     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3340 
3341     // reset event - at creation state is undefined
3342     VK_CHECK(vk.resetEvent(vkDevice, *event));
3343 
3344     // record command buffer
3345     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3346     {
3347         // allow execution of event during every stage of pipeline
3348         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3349 
3350         // record setting event
3351         vk.cmdSetEvent(*primCmdBuf, *event, stageMask);
3352     }
3353     endCommandBuffer(vk, *primCmdBuf);
3354 
3355     // create fence to wait for execution of queue
3356     const Unique<VkFence> fence(createFence(vk, vkDevice));
3357 
3358     // numSemaphores is declared const, so this array can be static
3359     // the semaphores will be destroyed automatically at end of scope
3360     Move<VkSemaphore> semaphoreArray[numSemaphores];
3361     VkSemaphore semaphores[numSemaphores];
3362 
3363     for (uint32_t idx = 0; idx < numSemaphores; ++idx)
3364     {
3365         // create semaphores for use in this test
3366         semaphoreArray[idx] = createSemaphore(vk, vkDevice);
3367         semaphores[idx]     = semaphoreArray[idx].get();
3368     }
3369 
3370     {
3371         // create submit info for buffer - signal semaphores
3372         const VkSubmitInfo submitInfo1 = {
3373             VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3374             DE_NULL,                       // pNext
3375             0u,                            // waitSemaphoreCount
3376             DE_NULL,                       // pWaitSemaphores
3377             DE_NULL,                       // pWaitDstStageMask
3378             1,                             // commandBufferCount
3379             &primCmdBuf.get(),             // pCommandBuffers
3380             numSemaphores,                 // signalSemaphoreCount
3381             semaphores                     // pSignalSemaphores
3382         };
3383         // Submit the command buffer to the queue
3384         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));
3385 
3386         // wait for end of execution of queue
3387         VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
3388 
3389         // check if buffer has been executed
3390         VkResult result = vk.getEventStatus(vkDevice, *event);
3391         if (result != VK_EVENT_SET)
3392             return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");
3393 
3394         // reset event, so next buffers can set it again
3395         VK_CHECK(vk.resetEvent(vkDevice, *event));
3396 
3397         // reset fence, so it can be used again
3398         VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
3399     }
3400 
3401     const uint32_t numberOfSemaphoresToBeWaitedByOneSubmission = numSemaphores / numSubmissions;
3402     const std::vector<VkPipelineStageFlags> waitDstStageFlags(numberOfSemaphoresToBeWaitedByOneSubmission,
3403                                                               VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
3404 
3405     // the following code waits for the semaphores set above - numSubmissions queues will wait for each semaphore from above
3406     for (uint32_t idxSubmission = 0; idxSubmission < numSubmissions; ++idxSubmission)
3407     {
3408 
3409         // create submit info for buffer - waiting for semaphore
3410         const VkSubmitInfo submitInfo2 = {
3411             VK_STRUCTURE_TYPE_SUBMIT_INFO,                                              // sType
3412             DE_NULL,                                                                    // pNext
3413             numberOfSemaphoresToBeWaitedByOneSubmission,                                // waitSemaphoreCount
3414             semaphores + (numberOfSemaphoresToBeWaitedByOneSubmission * idxSubmission), // pWaitSemaphores
3415             waitDstStageFlags.data(),                                                   // pWaitDstStageMask
3416             1,                                                                          // commandBufferCount
3417             &primCmdBuf.get(),                                                          // pCommandBuffers
3418             0u,                                                                         // signalSemaphoreCount
3419             DE_NULL,                                                                    // pSignalSemaphores
3420         };
3421 
3422         // Submit the second command buffer to the queue
3423         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));
3424 
3425         // wait for 1 second.
3426         VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, 1000 * 1000 * 1000));
3427 
3428         // check if second buffer has been executed
3429         // if it has been executed, it means that the semaphore was signalled - so test if passed
3430         VkResult result = vk.getEventStatus(vkDevice, *event);
3431         if (result != VK_EVENT_SET)
3432             return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");
3433 
3434         // reset fence, so it can be used again
3435         VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
3436 
3437         // reset event, so next buffers can set it again
3438         VK_CHECK(vk.resetEvent(vkDevice, *event));
3439     }
3440 
3441     return tcu::TestStatus::pass("Submit Buffer and Wait for Many Semaphores Test succeeded");
3442 }
3443 
submitBufferNullFence(Context & context)3444 tcu::TestStatus submitBufferNullFence(Context &context)
3445 {
3446     const VkDevice vkDevice         = context.getDevice();
3447     const DeviceInterface &vk       = context.getDeviceInterface();
3448     const VkQueue queue             = context.getUniversalQueue();
3449     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3450 
3451     const short BUFFER_COUNT = 2;
3452 
3453     const VkCommandPoolCreateInfo cmdPoolParams = {
3454         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
3455         DE_NULL,                                    // pNext;
3456         0u,                                         // flags;
3457         queueFamilyIndex,                           // queueFamilyIndex;
3458     };
3459     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3460 
3461     // Command buffer
3462     const VkCommandBufferAllocateInfo cmdBufParams = {
3463         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3464         DE_NULL,                                        // pNext;
3465         *cmdPool,                                       // pool;
3466         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3467         BUFFER_COUNT,                                   // bufferCount;
3468     };
3469     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3470     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3471 
3472     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3473         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3474         DE_NULL,                                     // pNext
3475         0u,                                          // flags
3476         (const VkCommandBufferInheritanceInfo *)DE_NULL,
3477     };
3478 
3479     std::vector<VkEventSp> events;
3480     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3481         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3482 
3483     // Record the command buffers
3484     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3485     {
3486         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3487         {
3488             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3489         }
3490         endCommandBuffer(vk, cmdBuffers[ndx].get());
3491     }
3492 
3493     // We'll use a fence to wait for the execution of the queue
3494     const Unique<VkFence> fence(createFence(vk, vkDevice));
3495 
3496     VkCommandBuffer cmdBuf0                = cmdBuffers[0].get();
3497     const VkSubmitInfo submitInfoNullFence = {
3498         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
3499         DE_NULL,                               // pNext
3500         0u,                                    // waitSemaphoreCount
3501         DE_NULL,                               // pWaitSemaphores
3502         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
3503         1u,                                    // commandBufferCount
3504         &cmdBuf0,                              // pCommandBuffers
3505         0u,                                    // signalSemaphoreCount
3506         DE_NULL,                               // pSignalSemaphores
3507     };
3508 
3509     VkCommandBuffer cmdBuf1                   = cmdBuffers[1].get();
3510     const VkSubmitInfo submitInfoNonNullFence = {
3511         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
3512         DE_NULL,                               // pNext
3513         0u,                                    // waitSemaphoreCount
3514         DE_NULL,                               // pWaitSemaphores
3515         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
3516         1u,                                    // commandBufferCount
3517         &cmdBuf1,                              // pCommandBuffers
3518         0u,                                    // signalSemaphoreCount
3519         DE_NULL,                               // pSignalSemaphores
3520     };
3521 
3522     // Perform two submissions - one with no fence, the other one with a valid
3523     // fence Hoping submitting the other buffer will give the first one time to
3524     // execute
3525     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNullFence, DE_NULL));
3526     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullFence, fence.get()));
3527 
3528     // Wait for the queue
3529     VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
3530 
3531     tcu::TestStatus testResult = tcu::TestStatus::incomplete();
3532 
3533     //Fence guaranteed that all buffers submited before fence were executed
3534     if (vk.getEventStatus(vkDevice, events[0]->get()) != VK_EVENT_SET ||
3535         vk.getEventStatus(vkDevice, events[1]->get()) != VK_EVENT_SET)
3536     {
3537         testResult = tcu::TestStatus::fail("One of the buffers was not executed.");
3538     }
3539     else
3540     {
3541         testResult = tcu::TestStatus::pass("Buffers have been submitted and executed correctly.");
3542     }
3543 
3544     vk.queueWaitIdle(queue);
3545     return testResult;
3546 }
3547 
submitTwoBuffersOneBufferNullWithFence(Context & context)3548 tcu::TestStatus submitTwoBuffersOneBufferNullWithFence(Context &context)
3549 {
3550     const VkDevice vkDevice         = context.getDevice();
3551     const DeviceInterface &vk       = context.getDeviceInterface();
3552     const VkQueue queue             = context.getUniversalQueue();
3553     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3554     const uint32_t BUFFER_COUNT     = 2u;
3555 
3556     const VkCommandPoolCreateInfo cmdPoolParams = {
3557         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3558         DE_NULL,                                         // pNext;
3559         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3560         queueFamilyIndex,                                // queueFamilyIndex;
3561     };
3562     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3563 
3564     const VkCommandBufferAllocateInfo cmdBufParams = {
3565         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3566         DE_NULL,                                        // pNext;
3567         *cmdPool,                                       // pool;
3568         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3569         BUFFER_COUNT,                                   // bufferCount;
3570     };
3571 
3572     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3573     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3574 
3575     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3576         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,     // sType
3577         DE_NULL,                                         // pNext
3578         0u,                                              // flags
3579         (const VkCommandBufferInheritanceInfo *)DE_NULL, // pInheritanceInfo
3580     };
3581 
3582     std::vector<VkEventSp> events;
3583     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3584         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3585 
3586     // Record the command buffers
3587     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3588     {
3589         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3590         {
3591             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3592         }
3593         VK_CHECK(vk.endCommandBuffer(cmdBuffers[ndx].get()));
3594     }
3595 
3596     // First command buffer
3597     VkCommandBuffer cmdBuf0                   = cmdBuffers[0].get();
3598     const VkSubmitInfo submitInfoNonNullFirst = {
3599         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
3600         DE_NULL,                               // pNext
3601         0u,                                    // waitSemaphoreCount
3602         DE_NULL,                               // pWaitSemaphores
3603         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
3604         1u,                                    // commandBufferCount
3605         &cmdBuf0,                              // pCommandBuffers
3606         0u,                                    // signalSemaphoreCount
3607         DE_NULL,                               // pSignalSemaphores
3608     };
3609 
3610     // Second command buffer
3611     VkCommandBuffer cmdBuf1                    = cmdBuffers[1].get();
3612     const VkSubmitInfo submitInfoNonNullSecond = {
3613         VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
3614         DE_NULL,                               // pNext
3615         0u,                                    // waitSemaphoreCount
3616         DE_NULL,                               // pWaitSemaphores
3617         (const VkPipelineStageFlags *)DE_NULL, // pWaitDstStageMask
3618         1u,                                    // commandBufferCount
3619         &cmdBuf1,                              // pCommandBuffers
3620         0u,                                    // signalSemaphoreCount
3621         DE_NULL,                               // pSignalSemaphores
3622     };
3623 
3624     // Fence will be submitted with the null queue
3625     const Unique<VkFence> fence(createFence(vk, vkDevice));
3626 
3627     // Perform two separate queueSubmit calls on the same queue followed
3628     // by a third call with no submitInfos and with a valid fence
3629     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullFirst, DE_NULL));
3630     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullSecond, DE_NULL));
3631     VK_CHECK(vk.queueSubmit(queue, 0u, DE_NULL, fence.get()));
3632 
3633     // Wait for the queue
3634     VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
3635 
3636     return tcu::TestStatus::pass("Buffers have been submitted correctly");
3637 }
3638 
3639 /******** 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) *******/
executeSecondaryBufferTest(Context & context)3640 tcu::TestStatus executeSecondaryBufferTest(Context &context)
3641 {
3642     const VkDevice vkDevice         = context.getDevice();
3643     const DeviceInterface &vk       = context.getDeviceInterface();
3644     const VkQueue queue             = context.getUniversalQueue();
3645     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3646 
3647     const VkCommandPoolCreateInfo cmdPoolParams = {
3648         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3649         DE_NULL,                                         // pNext;
3650         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3651         queueFamilyIndex,                                // queueFamilyIndex;
3652     };
3653     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3654 
3655     // Command buffer
3656     const VkCommandBufferAllocateInfo cmdBufParams = {
3657         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3658         DE_NULL,                                        // pNext;
3659         *cmdPool,                                       // commandPool;
3660         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3661         1u,                                             // bufferCount;
3662     };
3663     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3664 
3665     // Secondary Command buffer
3666     const VkCommandBufferAllocateInfo secCmdBufParams = {
3667         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3668         DE_NULL,                                        // pNext;
3669         *cmdPool,                                       // commandPool;
3670         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
3671         1u,                                             // bufferCount;
3672     };
3673     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
3674 
3675     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3676         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3677         DE_NULL,                                     // pNext
3678         0u,                                          // flags
3679         (const VkCommandBufferInheritanceInfo *)DE_NULL,
3680     };
3681 
3682     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
3683         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3684         DE_NULL,
3685         DE_NULL,                           // renderPass
3686         0u,                                // subpass
3687         DE_NULL,                           // framebuffer
3688         VK_FALSE,                          // occlusionQueryEnable
3689         (VkQueryControlFlags)0u,           // queryFlags
3690         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3691     };
3692     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
3693         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3694         DE_NULL,                                     // pNext
3695         0u,                                          // flags
3696         &secCmdBufInheritInfo,
3697     };
3698 
3699     // create event that will be used to check if secondary command buffer has been executed
3700     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3701 
3702     // reset event
3703     VK_CHECK(vk.resetEvent(vkDevice, *event));
3704 
3705     // record secondary command buffer
3706     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
3707     {
3708         // allow execution of event during every stage of pipeline
3709         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3710         // record setting event
3711         vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
3712     }
3713     // end recording of the secondary buffer
3714     endCommandBuffer(vk, *secCmdBuf);
3715 
3716     // record primary command buffer
3717     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3718     {
3719         // execute secondary buffer
3720         vk.cmdExecuteCommands(*primCmdBuf, 1u, &secCmdBuf.get());
3721     }
3722     endCommandBuffer(vk, *primCmdBuf);
3723 
3724     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
3725 
3726     // check if secondary buffer has been executed
3727     VkResult result = vk.getEventStatus(vkDevice, *event);
3728     if (result == VK_EVENT_SET)
3729         return tcu::TestStatus::pass("executeSecondaryBufferTest succeeded");
3730 
3731     return tcu::TestStatus::fail("executeSecondaryBufferTest FAILED");
3732 }
3733 
executeNestedBufferTest(Context & context)3734 tcu::TestStatus executeNestedBufferTest(Context &context)
3735 {
3736     const VkDevice vkDevice         = context.getDevice();
3737     const DeviceInterface &vk       = context.getDeviceInterface();
3738     const VkQueue queue             = context.getUniversalQueue();
3739     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3740 
3741     const VkCommandPoolCreateInfo cmdPoolParams = {
3742         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3743         DE_NULL,                                         // pNext;
3744         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3745         queueFamilyIndex,                                // queueFamilyIndex;
3746     };
3747     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3748 
3749     // Command buffer
3750     const VkCommandBufferAllocateInfo cmdBufParams = {
3751         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3752         DE_NULL,                                        // pNext;
3753         *cmdPool,                                       // commandPool;
3754         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3755         1u,                                             // bufferCount;
3756     };
3757     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3758 
3759     // Secondary Command buffer
3760     const VkCommandBufferAllocateInfo secCmdBufParams = {
3761         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3762         DE_NULL,                                        // pNext;
3763         *cmdPool,                                       // commandPool;
3764         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
3765         1u,                                             // bufferCount;
3766     };
3767     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
3768 
3769     // Nested secondary Command buffer
3770     const VkCommandBufferAllocateInfo nestedCmdBufParams = {
3771         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3772         DE_NULL,                                        // pNext;
3773         *cmdPool,                                       // commandPool;
3774         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
3775         1u,                                             // bufferCount;
3776     };
3777     const Unique<VkCommandBuffer> nestedCmdBuf(allocateCommandBuffer(vk, vkDevice, &nestedCmdBufParams));
3778 
3779     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3780         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3781         DE_NULL,                                     // pNext
3782         0u,                                          // flags
3783         (const VkCommandBufferInheritanceInfo *)DE_NULL,
3784     };
3785 
3786     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
3787         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3788         DE_NULL,
3789         DE_NULL,                           // renderPass
3790         0u,                                // subpass
3791         DE_NULL,                           // framebuffer
3792         VK_FALSE,                          // occlusionQueryEnable
3793         (VkQueryControlFlags)0u,           // queryFlags
3794         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3795     };
3796     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
3797         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3798         DE_NULL,                                     // pNext
3799         0u,                                          // flags
3800         &secCmdBufInheritInfo,
3801     };
3802 
3803     const VkCommandBufferInheritanceInfo nestedCmdBufInheritInfo = {
3804         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3805         DE_NULL,
3806         DE_NULL,                           // renderPass
3807         0u,                                // subpass
3808         DE_NULL,                           // framebuffer
3809         VK_FALSE,                          // occlusionQueryEnable
3810         (VkQueryControlFlags)0u,           // queryFlags
3811         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3812     };
3813     const VkCommandBufferBeginInfo nestedCmdBufBeginInfo = {
3814         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3815         DE_NULL,                                     // pNext
3816         0u,                                          // flags
3817         &nestedCmdBufInheritInfo,
3818     };
3819 
3820     // create event that will be used to check if nested command buffer has been executed
3821     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3822 
3823     // reset event
3824     VK_CHECK(vk.resetEvent(vkDevice, *event));
3825 
3826     // record nested command buffer
3827     VK_CHECK(vk.beginCommandBuffer(*nestedCmdBuf, &nestedCmdBufBeginInfo));
3828     {
3829         // allow execution of event during every stage of pipeline
3830         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3831         // record setting event
3832         vk.cmdSetEvent(*nestedCmdBuf, *event, stageMask);
3833     }
3834     // end recording of the secondary buffer
3835     endCommandBuffer(vk, *nestedCmdBuf);
3836 
3837     // record secondary command buffer
3838     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
3839     {
3840         // execute nested buffer
3841         vk.cmdExecuteCommands(*secCmdBuf, 1u, &nestedCmdBuf.get());
3842     }
3843     // end recording of the secondary buffer
3844     endCommandBuffer(vk, *secCmdBuf);
3845 
3846     // record primary command buffer
3847     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3848     {
3849         // execute secondary buffer
3850         vk.cmdExecuteCommands(*primCmdBuf, 1u, &secCmdBuf.get());
3851     }
3852     endCommandBuffer(vk, *primCmdBuf);
3853 
3854     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
3855 
3856     // check if secondary buffer has been executed
3857     VkResult result = vk.getEventStatus(vkDevice, *event);
3858     if (result == VK_EVENT_SET)
3859         return tcu::TestStatus::pass("executeNestedBufferTest succeeded");
3860 
3861     return tcu::TestStatus::fail("executeNestedBufferTest FAILED");
3862 }
3863 
executeMultipleLevelsNestedBufferTest(Context & context)3864 tcu::TestStatus executeMultipleLevelsNestedBufferTest(Context &context)
3865 {
3866     const uint32_t BUFFER_COUNT     = 2u;
3867     const VkDevice vkDevice         = context.getDevice();
3868     const DeviceInterface &vk       = context.getDeviceInterface();
3869     const VkQueue queue             = context.getUniversalQueue();
3870     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3871 
3872     const VkCommandPoolCreateInfo cmdPoolParams = {
3873         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3874         DE_NULL,                                         // pNext;
3875         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3876         queueFamilyIndex,                                // queueFamilyIndex;
3877     };
3878     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3879 
3880     // Command buffer
3881     const VkCommandBufferAllocateInfo cmdBufParams = {
3882         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3883         DE_NULL,                                        // pNext;
3884         *cmdPool,                                       // commandPool;
3885         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3886         1u,                                             // bufferCount;
3887     };
3888     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3889 
3890     // Secondary Command buffers
3891     const VkCommandBufferAllocateInfo secCmdBufParams = {
3892         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3893         DE_NULL,                                        // const void* pNext;
3894         *cmdPool,                                       // VkCommandPool pool;
3895         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
3896         BUFFER_COUNT,                                   // uint32_t bufferCount;
3897     };
3898     Move<VkCommandBuffer> nestedBuffers[BUFFER_COUNT];
3899     allocateCommandBuffers(vk, vkDevice, &secCmdBufParams, nestedBuffers);
3900 
3901     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3902         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3903         DE_NULL,                                     // pNext
3904         0u,                                          // flags
3905         (const VkCommandBufferInheritanceInfo *)DE_NULL,
3906     };
3907 
3908     const VkCommandBufferInheritanceInfo nestedCmdBufInheritInfo = {
3909         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3910         DE_NULL,
3911         DE_NULL,                           // renderPass
3912         0u,                                // subpass
3913         DE_NULL,                           // framebuffer
3914         VK_FALSE,                          // occlusionQueryEnable
3915         (VkQueryControlFlags)0u,           // queryFlags
3916         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3917     };
3918     const VkCommandBufferBeginInfo nestedCmdBufBeginInfo = {
3919         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3920         DE_NULL,                                     // pNext
3921         0u,                                          // flags
3922         &nestedCmdBufInheritInfo,
3923     };
3924 
3925     // create event that will be used to check if secondary command buffer has been executed
3926     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3927 
3928     // reset event
3929     VK_CHECK(vk.resetEvent(vkDevice, *event));
3930 
3931     // record nested secondary command buffers
3932     VK_CHECK(vk.beginCommandBuffer(*(nestedBuffers[0]), &nestedCmdBufBeginInfo));
3933     {
3934         // allow execution of event during every stage of pipeline
3935         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3936         // record setting event
3937         vk.cmdSetEvent(*(nestedBuffers[0]), *event, stageMask);
3938     }
3939     // end recording of the secondary buffer
3940     endCommandBuffer(vk, *(nestedBuffers[0]));
3941 
3942     for (uint32_t ndx = 1; ndx < BUFFER_COUNT; ndx++)
3943     {
3944         VK_CHECK(vk.beginCommandBuffer(*(nestedBuffers[ndx]), &nestedCmdBufBeginInfo));
3945         {
3946             // execute nested buffer
3947             vk.cmdExecuteCommands(*(nestedBuffers[ndx]), 1u, &(nestedBuffers[ndx - 1]).get());
3948         }
3949         // end recording of the secondary buffer
3950         endCommandBuffer(vk, *(nestedBuffers[ndx]));
3951     }
3952 
3953     // record primary command buffer
3954     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3955     {
3956         // execute secondary buffer
3957         vk.cmdExecuteCommands(*primCmdBuf, 1u, &(nestedBuffers[BUFFER_COUNT - 1]).get());
3958     }
3959     endCommandBuffer(vk, *primCmdBuf);
3960 
3961     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
3962 
3963     // check if secondary buffer has been executed
3964     VkResult result = vk.getEventStatus(vkDevice, *event);
3965     if (result == VK_EVENT_SET)
3966         return tcu::TestStatus::pass("executeMultipleLevelsNestedBufferTest succeeded");
3967 
3968     return tcu::TestStatus::fail("executeMultipleLevelsNestedBufferTest FAILED");
3969 }
3970 
executeSecondaryBufferTwiceTest(Context & context)3971 tcu::TestStatus executeSecondaryBufferTwiceTest(Context &context)
3972 {
3973     const uint32_t BUFFER_COUNT     = 10u;
3974     const VkDevice vkDevice         = context.getDevice();
3975     const DeviceInterface &vk       = context.getDeviceInterface();
3976     const VkQueue queue             = context.getUniversalQueue();
3977     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3978 
3979     const VkCommandPoolCreateInfo cmdPoolParams = {
3980         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
3981         DE_NULL,                                         // const void* pNext;
3982         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
3983         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
3984     };
3985     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3986 
3987     // Command buffer
3988     const VkCommandBufferAllocateInfo cmdBufParams = {
3989         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3990         DE_NULL,                                        // const void* pNext;
3991         *cmdPool,                                       // VkCommandPool pool;
3992         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
3993         1u,                                             // uint32_t bufferCount;
3994     };
3995     const Unique<VkCommandBuffer> primCmdBufOne(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3996     const Unique<VkCommandBuffer> primCmdBufTwo(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3997 
3998     // Secondary Command buffers params
3999     const VkCommandBufferAllocateInfo secCmdBufParams = {
4000         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
4001         DE_NULL,                                        // const void* pNext;
4002         *cmdPool,                                       // VkCommandPool pool;
4003         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
4004         BUFFER_COUNT,                                   // uint32_t bufferCount;
4005     };
4006     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
4007     allocateCommandBuffers(vk, vkDevice, &secCmdBufParams, cmdBuffers);
4008 
4009     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
4010         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
4011         DE_NULL,
4012         0, // flags
4013         (const VkCommandBufferInheritanceInfo *)DE_NULL,
4014     };
4015 
4016     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
4017         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
4018         DE_NULL,
4019         (VkRenderPass)0u,                  // renderPass
4020         0u,                                // subpass
4021         (VkFramebuffer)0u,                 // framebuffer
4022         VK_FALSE,                          // occlusionQueryEnable
4023         (VkQueryControlFlags)0u,           // queryFlags
4024         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
4025     };
4026     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
4027         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
4028         DE_NULL,
4029         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
4030         &secCmdBufInheritInfo,
4031     };
4032 
4033     // create event that will be used to check if secondary command buffer has been executed
4034     const Unique<VkEvent> eventOne(createEvent(vk, vkDevice));
4035 
4036     // reset event
4037     VK_CHECK(vk.resetEvent(vkDevice, *eventOne));
4038 
4039     VkCommandBuffer cmdBufferHandles[BUFFER_COUNT];
4040 
4041     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
4042     {
4043         // record secondary command buffer
4044         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &secCmdBufBeginInfo));
4045         {
4046             // set event
4047             vk.cmdSetEvent(cmdBuffers[ndx].get(), *eventOne, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
4048         }
4049         // end recording of secondary buffers
4050         endCommandBuffer(vk, cmdBuffers[ndx].get());
4051         cmdBufferHandles[ndx] = cmdBuffers[ndx].get();
4052     }
4053 
4054     // record primary command buffer one
4055     VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
4056     {
4057         // execute one secondary buffer
4058         vk.cmdExecuteCommands(*primCmdBufOne, 1, cmdBufferHandles);
4059     }
4060     endCommandBuffer(vk, *primCmdBufOne);
4061 
4062     // record primary command buffer two
4063     VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
4064     {
4065         // execute one secondary buffer with all buffers
4066         vk.cmdExecuteCommands(*primCmdBufTwo, BUFFER_COUNT, cmdBufferHandles);
4067     }
4068     endCommandBuffer(vk, *primCmdBufTwo);
4069 
4070     // create fence to wait for execution of queue
4071     const Unique<VkFence> fenceOne(createFence(vk, vkDevice));
4072     const Unique<VkFence> fenceTwo(createFence(vk, vkDevice));
4073 
4074     const uint64_t semaphoreWaitValue             = 1ull;
4075     const VkPipelineStageFlags semaphoreWaitStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
4076     const auto semaphore                          = createSemaphoreType(vk, vkDevice, VK_SEMAPHORE_TYPE_TIMELINE);
4077 
4078     // Use timeline semaphore to wait for signal from the host.
4079     const VkTimelineSemaphoreSubmitInfo timelineWaitSubmitInfo = {
4080         VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, // VkStructureType sType;
4081         nullptr,                                          // const void* pNext;
4082         1u,                                               // uint32_t waitSemaphoreValueCount;
4083         &semaphoreWaitValue,                              // const uint64_t* pWaitSemaphoreValues;
4084         0u,                                               // uint32_t signalSemaphoreValueCount;
4085         nullptr,                                          // const uint64_t* pSignalSemaphoreValues;
4086     };
4087 
4088     const VkSubmitInfo submitInfo = {
4089         VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
4090         &timelineWaitSubmitInfo,       // const void* pNext;
4091         1u,                            // uint32_t waitSemaphoreCount;
4092         &semaphore.get(),              // const VkSemaphore* pWaitSemaphores;
4093         &semaphoreWaitStage,           // const VkPipelineStageFlags* pWaitDstStageMask;
4094         1u,                            // uint32_t commandBufferCount;
4095         &primCmdBufOne.get(),          // const VkCommandBuffer* pCommandBuffers;
4096         0u,                            // uint32_t signalSemaphoreCount;
4097         nullptr,                       // const VkSemaphore* pSignalSemaphores;
4098     };
4099     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fenceOne));
4100 
4101     const VkSubmitInfo submitInfo2 = {
4102         VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
4103         &timelineWaitSubmitInfo,       // const void* pNext;
4104         1u,                            // uint32_t waitSemaphoreCount;
4105         &semaphore.get(),              // const VkSemaphore* pWaitSemaphores;
4106         &semaphoreWaitStage,           // const VkPipelineStageFlags* pWaitDstStageMask;
4107         1u,                            // uint32_t commandBufferCount;
4108         &primCmdBufTwo.get(),          // const VkCommandBuffer* pCommandBuffers;
4109         0u,                            // uint32_t signalSemaphoreCount;
4110         nullptr,                       // const VkSemaphore* pSignalSemaphores;
4111     };
4112 
4113     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fenceTwo));
4114 
4115     // Signal from host
4116     const vk::VkSemaphoreSignalInfo signalInfo = {
4117         vk::VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType;
4118         nullptr,                                     // const void* pNext;
4119         semaphore.get(),                             // VkSemaphore semaphore;
4120         semaphoreWaitValue,                          // uint64_t value;
4121     };
4122 
4123     VK_CHECK(vk.signalSemaphore(vkDevice, &signalInfo));
4124 
4125     // wait for end of execution of fenceOne
4126     VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, INFINITE_TIMEOUT));
4127 
4128     // wait for end of execution of fenceTwo
4129     VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceTwo.get(), 0u, INFINITE_TIMEOUT));
4130 
4131     TCU_CHECK(vk.getEventStatus(vkDevice, *eventOne) == vk::VK_EVENT_SET);
4132 
4133     return tcu::TestStatus::pass("executeSecondaryBufferTwiceTest succeeded");
4134 }
4135 
4136 /******** 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) **/
orderBindPipelineTest(Context & context)4137 tcu::TestStatus orderBindPipelineTest(Context &context)
4138 {
4139     const DeviceInterface &vk       = context.getDeviceInterface();
4140     const VkDevice device           = context.getDevice();
4141     const VkQueue queue             = context.getUniversalQueue();
4142     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
4143     Allocator &allocator            = context.getDefaultAllocator();
4144     const ComputeInstanceResultBuffer result(vk, device, allocator);
4145 
4146     enum
4147     {
4148         ADDRESSABLE_SIZE = 256, // allocate a lot more than required
4149     };
4150 
4151     const tcu::Vec4 colorA1 = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
4152     const tcu::Vec4 colorA2 = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
4153     const tcu::Vec4 colorB1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
4154     const tcu::Vec4 colorB2 = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
4155 
4156     const uint32_t dataOffsetA = (0u);
4157     const uint32_t dataOffsetB = (0u);
4158     const uint32_t viewOffsetA = (0u);
4159     const uint32_t viewOffsetB = (0u);
4160     const uint32_t bufferSizeA = dataOffsetA + ADDRESSABLE_SIZE;
4161     const uint32_t bufferSizeB = dataOffsetB + ADDRESSABLE_SIZE;
4162 
4163     de::MovePtr<Allocation> bufferMemA;
4164     const Unique<VkBuffer> bufferA(
4165         createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA, context));
4166 
4167     de::MovePtr<Allocation> bufferMemB;
4168     const Unique<VkBuffer> bufferB(
4169         createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB, context));
4170 
4171     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
4172     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
4173     const Unique<VkDescriptorSet> descriptorSet(createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA,
4174                                                                     viewOffsetA, *bufferB, viewOffsetB,
4175                                                                     result.getBuffer(), context));
4176     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
4177     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
4178 
4179     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
4180         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
4181         DE_NULL,                                       // pNext
4182         (VkPipelineLayoutCreateFlags)0,
4183         numDescriptorSets,          // setLayoutCount
4184         &descriptorSetLayout.get(), // pSetLayouts
4185         0u,                         // pushConstantRangeCount
4186         DE_NULL,                    // pPushConstantRanges
4187     };
4188     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, device, &layoutCreateInfo));
4189 
4190     const Unique<VkShaderModule> computeModuleGood(createShaderModule(
4191         vk, device, context.getBinaryCollection().get("compute_good"), (VkShaderModuleCreateFlags)0u));
4192     const Unique<VkShaderModule> computeModuleBad(createShaderModule(
4193         vk, device, context.getBinaryCollection().get("compute_bad"), (VkShaderModuleCreateFlags)0u));
4194 
4195     const VkPipelineShaderStageCreateInfo shaderCreateInfoGood = {
4196         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4197         DE_NULL,
4198         (VkPipelineShaderStageCreateFlags)0,
4199         VK_SHADER_STAGE_COMPUTE_BIT, // stage
4200         *computeModuleGood,          // shader
4201         "main",
4202         DE_NULL, // pSpecializationInfo
4203     };
4204 
4205     const VkPipelineShaderStageCreateInfo shaderCreateInfoBad = {
4206         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4207         DE_NULL,
4208         (vk::VkPipelineShaderStageCreateFlags)0,
4209         vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
4210         *computeModuleBad,               // shader
4211         "main",
4212         DE_NULL, // pSpecializationInfo
4213     };
4214 
4215     const VkComputePipelineCreateInfo createInfoGood = {
4216         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
4217         DE_NULL,
4218         0u,                   // flags
4219         shaderCreateInfoGood, // cs
4220         *pipelineLayout,      // layout
4221         (vk::VkPipeline)0,    // basePipelineHandle
4222         0u,                   // basePipelineIndex
4223     };
4224 
4225     const VkComputePipelineCreateInfo createInfoBad = {
4226         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
4227         DE_NULL,
4228         0u,                  // flags
4229         shaderCreateInfoBad, // cs
4230         *pipelineLayout,     // descriptorSetLayout.get()
4231         (VkPipeline)0,       // basePipelineHandle
4232         0u,                  // basePipelineIndex
4233     };
4234 
4235     const Unique<VkPipeline> pipelineGood(createComputePipeline(vk, device, (VkPipelineCache)0u, &createInfoGood));
4236     const Unique<VkPipeline> pipelineBad(createComputePipeline(vk, device, (VkPipelineCache)0u, &createInfoBad));
4237 
4238     const VkAccessFlags inputBit                 = (VK_ACCESS_UNIFORM_READ_BIT);
4239     const VkBufferMemoryBarrier bufferBarriers[] = {{
4240                                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, DE_NULL,
4241                                                         VK_ACCESS_HOST_WRITE_BIT,  // srcAccessMask
4242                                                         inputBit,                  // dstAccessMask
4243                                                         VK_QUEUE_FAMILY_IGNORED,   // srcQueueFamilyIndex
4244                                                         VK_QUEUE_FAMILY_IGNORED,   // destQueueFamilyIndex
4245                                                         *bufferA,                  // buffer
4246                                                         (VkDeviceSize)0u,          // offset
4247                                                         (VkDeviceSize)bufferSizeA, // size
4248                                                     },
4249                                                     {
4250                                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, DE_NULL,
4251                                                         VK_ACCESS_HOST_WRITE_BIT,  // srcAccessMask
4252                                                         inputBit,                  // dstAccessMask
4253                                                         VK_QUEUE_FAMILY_IGNORED,   // srcQueueFamilyIndex
4254                                                         VK_QUEUE_FAMILY_IGNORED,   // destQueueFamilyIndex
4255                                                         *bufferB,                  // buffer
4256                                                         (VkDeviceSize)0u,          // offset
4257                                                         (VkDeviceSize)bufferSizeB, // size
4258                                                     }};
4259 
4260     const uint32_t numSrcBuffers = 1u;
4261 
4262     const uint32_t *const dynamicOffsets                = (DE_NULL);
4263     const uint32_t numDynamicOffsets                    = (0);
4264     const int numPreBarriers                            = numSrcBuffers;
4265     const vk::VkBufferMemoryBarrier *const postBarriers = result.getResultReadBarrier();
4266     const int numPostBarriers                           = 1;
4267     const tcu::Vec4 refQuadrantValue14                  = (colorA2);
4268     const tcu::Vec4 refQuadrantValue23                  = (colorA1);
4269     const tcu::Vec4 references[4]                       = {
4270         refQuadrantValue14,
4271         refQuadrantValue23,
4272         refQuadrantValue23,
4273         refQuadrantValue14,
4274     };
4275     tcu::Vec4 results[4];
4276 
4277     // submit and wait begin
4278 
4279     const tcu::UVec3 numWorkGroups = tcu::UVec3(4, 1u, 1);
4280 
4281     const VkCommandPoolCreateInfo cmdPoolCreateInfo = {
4282         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
4283         DE_NULL,                                    // pNext
4284         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // flags
4285         queueFamilyIndex,                           // queueFamilyIndex
4286     };
4287     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolCreateInfo));
4288     const VkCommandBufferAllocateInfo cmdBufCreateInfo = {
4289         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
4290         DE_NULL,                                        // pNext
4291         *cmdPool,                                       // commandPool
4292         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level
4293         1u,                                             // bufferCount;
4294     };
4295 
4296     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
4297         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
4298         DE_NULL,                                     // pNext
4299         0u,                                          // flags
4300         (const VkCommandBufferInheritanceInfo *)DE_NULL,
4301     };
4302 
4303     const Unique<VkCommandBuffer> cmd(allocateCommandBuffer(vk, device, &cmdBufCreateInfo));
4304 
4305     VK_CHECK(vk.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
4306 
4307     vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineBad);
4308     vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineGood);
4309     vk.cmdBindDescriptorSets(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
4310                              descriptorSets, numDynamicOffsets, dynamicOffsets);
4311 
4312     if (numPreBarriers)
4313         vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
4314                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, numPreBarriers, bufferBarriers,
4315                               0, (const VkImageMemoryBarrier *)DE_NULL);
4316 
4317     vk.cmdDispatch(*cmd, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
4318     vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
4319                           0, (const VkMemoryBarrier *)DE_NULL, numPostBarriers, postBarriers, 0,
4320                           (const VkImageMemoryBarrier *)DE_NULL);
4321     endCommandBuffer(vk, *cmd);
4322 
4323     // run
4324     // submit second primary buffer, the secondary should be executed too
4325     submitCommandsAndWait(vk, device, queue, cmd.get());
4326 
4327     // submit and wait end
4328     result.readResultContentsTo(&results);
4329 
4330     // verify
4331     if (results[0] == references[0] && results[1] == references[1] && results[2] == references[2] &&
4332         results[3] == references[3])
4333     {
4334         return tcu::TestStatus::pass("Pass");
4335     }
4336     else if (results[0] == tcu::Vec4(-1.0f) && results[1] == tcu::Vec4(-1.0f) && results[2] == tcu::Vec4(-1.0f) &&
4337              results[3] == tcu::Vec4(-1.0f))
4338     {
4339         context.getTestContext().getLog()
4340             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
4341         return tcu::TestStatus::fail("Result buffer was not written to");
4342     }
4343     else
4344     {
4345         context.getTestContext().getLog()
4346             << tcu::TestLog::Message << "Error expected [" << references[0] << ", " << references[1] << ", "
4347             << references[2] << ", " << references[3] << "], got [" << results[0] << ", " << results[1] << ", "
4348             << results[2] << ", " << results[3] << "]" << tcu::TestLog::EndMessage;
4349         return tcu::TestStatus::fail("Invalid result values");
4350     }
4351 }
4352 
4353 enum StateTransitionTest
4354 {
4355     STT_RECORDING_TO_INITIAL = 0,
4356     STT_EXECUTABLE_TO_INITIAL,
4357     STT_RECORDING_TO_INVALID,
4358     STT_EXECUTABLE_TO_INVALID,
4359 };
4360 
executeStateTransitionTest(Context & context,StateTransitionTest type)4361 tcu::TestStatus executeStateTransitionTest(Context &context, StateTransitionTest type)
4362 {
4363     const VkDevice vkDevice         = context.getDevice();
4364     const DeviceInterface &vk       = context.getDeviceInterface();
4365     const VkQueue queue             = context.getUniversalQueue();
4366     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
4367 
4368 #ifdef CTS_USES_VULKANSC
4369     if (context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
4370         TCU_THROW(NotSupportedError, "commandPoolResetCommandBuffer not supported by this implementation");
4371 #endif // CTS_USES_VULKANSC
4372 
4373     const Unique<VkCommandPool> cmdPool(
4374         createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
4375     const Unique<VkCommandBuffer> cmdBuffer(
4376         allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4377     const Unique<VkEvent> globalEvent(createEvent(vk, vkDevice));
4378 
4379     VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));
4380 
4381     switch (type)
4382     {
4383     case STT_RECORDING_TO_INITIAL:
4384     {
4385         beginCommandBuffer(vk, *cmdBuffer, 0u);
4386         vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4387         break;
4388         // command buffer is still in recording state
4389     }
4390     case STT_EXECUTABLE_TO_INITIAL:
4391     {
4392         beginCommandBuffer(vk, *cmdBuffer, 0u);
4393         vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4394         endCommandBuffer(vk, *cmdBuffer);
4395         break;
4396         // command buffer is still in executable state
4397     }
4398     case STT_RECORDING_TO_INVALID:
4399     {
4400         VkSubpassDescription subpassDescription;
4401         deMemset(&subpassDescription, 0, sizeof(VkSubpassDescription));
4402         subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
4403 
4404         VkRenderPassCreateInfo renderPassCreateInfo{
4405             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, DE_NULL, 0, 0, DE_NULL, 1, &subpassDescription, 0, DE_NULL};
4406 
4407         // Error here - renderpass and framebuffer were created localy
4408         Move<VkRenderPass> renderPass = createRenderPass(vk, vkDevice, &renderPassCreateInfo);
4409 
4410         VkFramebufferCreateInfo framebufferCreateInfo{
4411             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, DE_NULL, 0, *renderPass, 0, DE_NULL, 16, 16, 1};
4412         Move<VkFramebuffer> framebuffer = createFramebuffer(vk, vkDevice, &framebufferCreateInfo);
4413 
4414         VkRenderPassBeginInfo renderPassBeginInfo = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
4415                                                      DE_NULL,
4416                                                      *renderPass,
4417                                                      *framebuffer,
4418                                                      {{0, 0}, {16, 16}},
4419                                                      0,
4420                                                      DE_NULL};
4421 
4422         beginCommandBuffer(vk, *cmdBuffer, 0u);
4423         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
4424         vk.cmdEndRenderPass(*cmdBuffer);
4425 
4426         // not executing endCommandBuffer(vk, *cmdBuffer);
4427         // command buffer is still in recording state
4428         break;
4429         // renderpass and framebuffer are destroyed; command buffer should be now in invalid state
4430     }
4431     case STT_EXECUTABLE_TO_INVALID:
4432     {
4433         // create event that will be used to check if command buffer has been executed
4434         const Unique<VkEvent> localEvent(createEvent(vk, vkDevice));
4435         VK_CHECK(vk.resetEvent(vkDevice, *localEvent));
4436 
4437         beginCommandBuffer(vk, *cmdBuffer, 0u);
4438         vk.cmdSetEvent(*cmdBuffer, *localEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4439         endCommandBuffer(vk, *cmdBuffer);
4440         // command buffer is in executable state
4441         break;
4442         // localEvent is destroyed; command buffer should be now in invalid state
4443     }
4444     }
4445 
4446     VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));
4447 
4448     VK_CHECK(vk.resetCommandBuffer(*cmdBuffer, 0u));
4449     // command buffer should now be back in initial state
4450 
4451     // verify commandBuffer
4452     beginCommandBuffer(vk, *cmdBuffer, 0u);
4453     vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4454     endCommandBuffer(vk, *cmdBuffer);
4455     submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
4456 
4457     // check if buffer has been executed
4458     VkResult result = vk.getEventStatus(vkDevice, *globalEvent);
4459     if (result != VK_EVENT_SET)
4460         return tcu::TestStatus::fail("Submit failed");
4461 
4462     return tcu::TestStatus::pass("Pass");
4463 }
4464 
4465 // Shaders
genComputeSource(SourceCollections & programCollection)4466 void genComputeSource(SourceCollections &programCollection)
4467 {
4468     const char *const versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
4469     std::ostringstream bufGood;
4470 
4471     bufGood << versionDecl << "\n"
4472             << ""
4473             << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
4474             << "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
4475             << "{\n"
4476             << "    highp vec4 colorA;\n"
4477             << "    highp vec4 colorB;\n"
4478             << "} b_instance;\n"
4479             << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
4480             << "{\n"
4481             << "    highp vec4 read_colors[4];\n"
4482             << "} b_out;\n"
4483             << "void main(void)\n"
4484             << "{\n"
4485             << "    highp int quadrant_id = int(gl_WorkGroupID.x);\n"
4486             << "    highp vec4 result_color;\n"
4487             << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
4488             << "        result_color = b_instance.colorA;\n"
4489             << "    else\n"
4490             << "        result_color = b_instance.colorB;\n"
4491             << "    b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
4492             << "}\n";
4493 
4494     programCollection.glslSources.add("compute_good") << glu::ComputeSource(bufGood.str());
4495 
4496     std::ostringstream bufBad;
4497 
4498     bufBad << versionDecl << "\n"
4499            << ""
4500            << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
4501            << "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
4502            << "{\n"
4503            << "    highp vec4 colorA;\n"
4504            << "    highp vec4 colorB;\n"
4505            << "} b_instance;\n"
4506            << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
4507            << "{\n"
4508            << "    highp vec4 read_colors[4];\n"
4509            << "} b_out;\n"
4510            << "void main(void)\n"
4511            << "{\n"
4512            << "    highp int quadrant_id = int(gl_WorkGroupID.x);\n"
4513            << "    highp vec4 result_color;\n"
4514            << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
4515            << "        result_color = b_instance.colorA;\n"
4516            << "    else\n"
4517            << "        result_color = b_instance.colorB;\n"
4518            << "    b_out.read_colors[gl_WorkGroupID.x] = vec4(0.0, 0.0, 0.0, 0.0);\n"
4519            << "}\n";
4520 
4521     programCollection.glslSources.add("compute_bad") << glu::ComputeSource(bufBad.str());
4522 }
4523 
genComputeIncrementSource(SourceCollections & programCollection)4524 void genComputeIncrementSource(SourceCollections &programCollection)
4525 {
4526     const char *const versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
4527     std::ostringstream bufIncrement;
4528 
4529     bufIncrement << versionDecl << "\n"
4530                  << ""
4531                  << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
4532                  << "layout(set = 0, binding = 0, std140) buffer InOutBuf\n"
4533                  << "{\n"
4534                  << "    coherent uint count;\n"
4535                  << "} b_in_out;\n"
4536                  << "void main(void)\n"
4537                  << "{\n"
4538                  << "    atomicAdd(b_in_out.count, 1u);\n"
4539                  << "}\n";
4540 
4541     programCollection.glslSources.add("compute_increment") << glu::ComputeSource(bufIncrement.str());
4542 }
4543 
genComputeIncrementSourceBadInheritance(SourceCollections & programCollection,BadInheritanceInfoCase testCase)4544 void genComputeIncrementSourceBadInheritance(SourceCollections &programCollection, BadInheritanceInfoCase testCase)
4545 {
4546     DE_UNREF(testCase);
4547     return genComputeIncrementSource(programCollection);
4548 }
4549 
checkEventSupport(Context & context)4550 void checkEventSupport(Context &context)
4551 {
4552 #ifndef CTS_USES_VULKANSC
4553     if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
4554         !context.getPortabilitySubsetFeatures().events)
4555         TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4556 #else
4557     DE_UNREF(context);
4558 #endif // CTS_USES_VULKANSC
4559 }
4560 
checkCommandBufferSimultaneousUseSupport(Context & context)4561 void checkCommandBufferSimultaneousUseSupport(Context &context)
4562 {
4563 #ifdef CTS_USES_VULKANSC
4564     if (context.getDeviceVulkanSC10Properties().commandBufferSimultaneousUse == VK_FALSE)
4565         TCU_THROW(NotSupportedError, "commandBufferSimultaneousUse is not supported");
4566 #else
4567     DE_UNREF(context);
4568 #endif // CTS_USES_VULKANSC
4569 }
4570 
checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(Context & context)4571 void checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(Context &context)
4572 {
4573 #ifdef CTS_USES_VULKANSC
4574     if (context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
4575         TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
4576 #else
4577     DE_UNREF(context);
4578 #endif // CTS_USES_VULKANSC
4579 }
4580 
checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1(Context & context,bool value)4581 void checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1(Context &context, bool value)
4582 {
4583     DE_UNREF(value);
4584 #ifdef CTS_USES_VULKANSC
4585     if (context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
4586         TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
4587 #else
4588     DE_UNREF(context);
4589 #endif // CTS_USES_VULKANSC
4590 }
4591 
checkEventAndSecondaryCommandBufferNullFramebufferSupport(Context & context)4592 void checkEventAndSecondaryCommandBufferNullFramebufferSupport(Context &context)
4593 {
4594     checkEventSupport(context);
4595     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(context);
4596 }
4597 
checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context & context)4598 void checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context &context)
4599 {
4600     checkCommandBufferSimultaneousUseSupport(context);
4601     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(context);
4602 }
4603 
checkEventAndTimelineSemaphoreAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context & context)4604 void checkEventAndTimelineSemaphoreAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context &context)
4605 {
4606     checkEventSupport(context);
4607     context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
4608 
4609     checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(context);
4610 }
4611 
checkNestedCommandBufferSupport(Context & context)4612 void checkNestedCommandBufferSupport(Context &context)
4613 {
4614     checkEventAndSecondaryCommandBufferNullFramebufferSupport(context);
4615     context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
4616 
4617 #ifndef CTS_USES_VULKANSC
4618     const auto &features =
4619         *findStructure<VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
4620     if (!features.nestedCommandBuffer)
4621 #endif // CTS_USES_VULKANSC
4622         TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
4623 }
4624 
checkNestedCommandBufferDepthSupport(Context & context)4625 void checkNestedCommandBufferDepthSupport(Context &context)
4626 {
4627     checkNestedCommandBufferSupport(context);
4628 
4629 #ifndef CTS_USES_VULKANSC
4630     const auto &properties =
4631         *findStructure<VkPhysicalDeviceNestedCommandBufferPropertiesEXT>(&context.getDeviceProperties2());
4632     if (properties.maxCommandBufferNestingLevel <= 1)
4633 #endif // CTS_USES_VULKANSC
4634         TCU_THROW(NotSupportedError, "nestedCommandBuffer with nesting level greater than 1 is not supported");
4635 }
4636 
checkNestedCommandBufferRenderPassContinueSupport(Context & context,bool value)4637 void checkNestedCommandBufferRenderPassContinueSupport(Context &context, bool value)
4638 {
4639     checkNestedCommandBufferSupport(context);
4640 
4641     DE_UNREF(value);
4642 #ifndef CTS_USES_VULKANSC
4643     const auto &features =
4644         *findStructure<VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
4645     if (!features.nestedCommandBufferRendering)
4646 #endif // CTS_USES_VULKANSC
4647         TCU_THROW(NotSupportedError, "nestedCommandBufferRendering is not supported");
4648 }
4649 
checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport(Context & context)4650 void checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport(Context &context)
4651 {
4652     checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(context);
4653     checkNestedCommandBufferSupport(context);
4654 #ifndef CTS_USES_VULKANSC
4655     const auto &features =
4656         *findStructure<VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
4657     if (!features.nestedCommandBufferSimultaneousUse)
4658 #endif // CTS_USES_VULKANSC
4659         TCU_THROW(NotSupportedError, "nestedCommandBufferSimultaneousUse is not supported");
4660 }
4661 
4662 #ifndef CTS_USES_VULKANSC
checkEventSupport(Context & context,const VkCommandBufferLevel)4663 void checkEventSupport(Context &context, const VkCommandBufferLevel)
4664 {
4665     checkEventSupport(context);
4666 }
4667 #endif // CTS_USES_VULKANSC
4668 
4669 struct ManyDrawsParams
4670 {
4671     VkCommandBufferLevel level;
4672     VkExtent3D imageExtent;
4673     uint32_t seed;
4674 
ManyDrawsParamsvkt::api::__anone03e194a0111::ManyDrawsParams4675     ManyDrawsParams(VkCommandBufferLevel level_, const VkExtent3D &extent_, uint32_t seed_)
4676         : level(level_)
4677         , imageExtent(extent_)
4678         , seed(seed_)
4679     {
4680     }
4681 };
4682 
4683 struct ManyDrawsVertex
4684 {
4685     using Color = tcu::Vector<uint8_t, 4>;
4686 
4687     tcu::Vec2 coords;
4688     Color color;
4689 
ManyDrawsVertexvkt::api::__anone03e194a0111::ManyDrawsVertex4690     ManyDrawsVertex(const tcu::Vec2 &coords_, const Color &color_) : coords(coords_), color(color_)
4691     {
4692     }
4693 };
4694 
getSupportedDepthStencilFormat(const InstanceInterface & vki,VkPhysicalDevice physDev)4695 VkFormat getSupportedDepthStencilFormat(const InstanceInterface &vki, VkPhysicalDevice physDev)
4696 {
4697     const VkFormat formatList[] = {VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
4698     const VkFormatFeatureFlags requirements =
4699         (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
4700 
4701     for (int i = 0; i < DE_LENGTH_OF_ARRAY(formatList); ++i)
4702     {
4703         const auto properties = getPhysicalDeviceFormatProperties(vki, physDev, formatList[i]);
4704         if ((properties.optimalTilingFeatures & requirements) == requirements)
4705             return formatList[i];
4706     }
4707 
4708     TCU_THROW(NotSupportedError, "No suitable depth/stencil format support");
4709     return VK_FORMAT_UNDEFINED;
4710 }
4711 
4712 class ManyDrawsCase : public TestCase
4713 {
4714 public:
4715     ManyDrawsCase(tcu::TestContext &testCtx, const std::string &name, const ManyDrawsParams &params);
~ManyDrawsCase(void)4716     virtual ~ManyDrawsCase(void)
4717     {
4718     }
4719 
4720     virtual void checkSupport(Context &context) const;
4721     virtual void initPrograms(vk::SourceCollections &programCollection) const;
4722     virtual TestInstance *createInstance(Context &context) const;
4723 
getColorFormat(void)4724     static VkFormat getColorFormat(void)
4725     {
4726         return VK_FORMAT_R8G8B8A8_UINT;
4727     }
4728 
4729 protected:
4730     ManyDrawsParams m_params;
4731 };
4732 
4733 class ManyDrawsInstance : public TestInstance
4734 {
4735 public:
4736     ManyDrawsInstance(Context &context, const ManyDrawsParams &params);
~ManyDrawsInstance(void)4737     virtual ~ManyDrawsInstance(void)
4738     {
4739     }
4740 
4741     virtual tcu::TestStatus iterate(void);
4742 
4743 protected:
4744     ManyDrawsParams m_params;
4745 };
4746 
4747 using BufferPtr = de::MovePtr<BufferWithMemory>;
4748 using ImagePtr  = de::MovePtr<ImageWithMemory>;
4749 
4750 struct ManyDrawsVertexBuffers
4751 {
4752     BufferPtr stagingBuffer;
4753     BufferPtr vertexBuffer;
4754 };
4755 
4756 struct ManyDrawsAllocatedData
4757 {
4758     ManyDrawsVertexBuffers frontBuffers;
4759     ManyDrawsVertexBuffers backBuffers;
4760     ImagePtr colorAttachment;
4761     ImagePtr dsAttachment;
4762     BufferPtr colorCheckBuffer;
4763     BufferPtr stencilCheckBuffer;
4764 
calcNumPixelsvkt::api::__anone03e194a0111::ManyDrawsAllocatedData4765     static uint32_t calcNumPixels(const VkExtent3D &extent)
4766     {
4767         DE_ASSERT(extent.depth == 1u);
4768         return (extent.width * extent.height);
4769     }
calcNumVerticesvkt::api::__anone03e194a0111::ManyDrawsAllocatedData4770     static uint32_t calcNumVertices(const VkExtent3D &extent)
4771     {
4772         // One triangle (3 vertices) per output image pixel.
4773         return (calcNumPixels(extent) * 3u);
4774     }
4775 
calcVertexBufferSizevkt::api::__anone03e194a0111::ManyDrawsAllocatedData4776     static VkDeviceSize calcVertexBufferSize(const VkExtent3D &extent)
4777     {
4778         return calcNumVertices(extent) * sizeof(ManyDrawsVertex);
4779     }
4780 
makeVertexBuffersvkt::api::__anone03e194a0111::ManyDrawsAllocatedData4781     static void makeVertexBuffers(const DeviceInterface &vkd, VkDevice device, Allocator &alloc, VkDeviceSize size,
4782                                   ManyDrawsVertexBuffers &buffers)
4783     {
4784         const auto stagingBufferInfo = makeBufferCreateInfo(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
4785         const auto vertexBufferInfo =
4786             makeBufferCreateInfo(size, (VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
4787 
4788         buffers.stagingBuffer =
4789             BufferPtr(new BufferWithMemory(vkd, device, alloc, stagingBufferInfo, MemoryRequirement::HostVisible));
4790         buffers.vertexBuffer =
4791             BufferPtr(new BufferWithMemory(vkd, device, alloc, vertexBufferInfo, MemoryRequirement::Any));
4792     }
4793 
ManyDrawsAllocatedDatavkt::api::__anone03e194a0111::ManyDrawsAllocatedData4794     ManyDrawsAllocatedData(const DeviceInterface &vkd, VkDevice device, Allocator &alloc, const VkExtent3D &imageExtent,
4795                            VkFormat colorFormat, VkFormat dsFormat)
4796     {
4797         const auto numPixels        = calcNumPixels(imageExtent);
4798         const auto vertexBufferSize = calcVertexBufferSize(imageExtent);
4799 
4800         makeVertexBuffers(vkd, device, alloc, vertexBufferSize, frontBuffers);
4801         makeVertexBuffers(vkd, device, alloc, vertexBufferSize, backBuffers);
4802 
4803         const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
4804         const auto dsUsage    = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
4805 
4806         const VkImageCreateInfo colorAttachmentInfo = {
4807             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
4808             nullptr,                             // const void* pNext;
4809             0u,                                  // VkImageCreateFlags flags;
4810             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
4811             colorFormat,                         // VkFormat format;
4812             imageExtent,                         // VkExtent3D extent;
4813             1u,                                  // uint32_t mipLevels;
4814             1u,                                  // uint32_t arrayLayers;
4815             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
4816             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
4817             colorUsage,                          // VkImageUsageFlags usage;
4818             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
4819             0u,                                  // uint32_t queueFamilyIndexCount;
4820             nullptr,                             // const uint32_t* pQueueFamilyIndices;
4821             VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
4822         };
4823         colorAttachment =
4824             ImagePtr(new ImageWithMemory(vkd, device, alloc, colorAttachmentInfo, MemoryRequirement::Any));
4825 
4826         const VkImageCreateInfo dsAttachmentInfo = {
4827             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
4828             nullptr,                             // const void* pNext;
4829             0u,                                  // VkImageCreateFlags flags;
4830             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
4831             dsFormat,                            // VkFormat format;
4832             imageExtent,                         // VkExtent3D extent;
4833             1u,                                  // uint32_t mipLevels;
4834             1u,                                  // uint32_t arrayLayers;
4835             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
4836             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
4837             dsUsage,                             // VkImageUsageFlags usage;
4838             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
4839             0u,                                  // uint32_t queueFamilyIndexCount;
4840             nullptr,                             // const uint32_t* pQueueFamilyIndices;
4841             VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
4842         };
4843         dsAttachment = ImagePtr(new ImageWithMemory(vkd, device, alloc, dsAttachmentInfo, MemoryRequirement::Any));
4844 
4845         const auto colorCheckBufferSize =
4846             static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(mapVkFormat(colorFormat)));
4847         const auto colorCheckBufferInfo = makeBufferCreateInfo(colorCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4848 
4849         colorCheckBuffer =
4850             BufferPtr(new BufferWithMemory(vkd, device, alloc, colorCheckBufferInfo, MemoryRequirement::HostVisible));
4851 
4852         const auto stencilFormat = tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
4853         const auto stencilCheckBufferSize = static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(stencilFormat));
4854         const auto stencilCheckBufferInfo =
4855             makeBufferCreateInfo(stencilCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4856 
4857         stencilCheckBuffer =
4858             BufferPtr(new BufferWithMemory(vkd, device, alloc, stencilCheckBufferInfo, MemoryRequirement::HostVisible));
4859     }
4860 };
4861 
ManyDrawsCase(tcu::TestContext & testCtx,const std::string & name,const ManyDrawsParams & params)4862 ManyDrawsCase::ManyDrawsCase(tcu::TestContext &testCtx, const std::string &name, const ManyDrawsParams &params)
4863     : TestCase(testCtx, name)
4864     , m_params(params)
4865 {
4866 }
4867 
checkSupport(Context & context) const4868 void ManyDrawsCase::checkSupport(Context &context) const
4869 {
4870     const auto &vki     = context.getInstanceInterface();
4871     const auto physDev  = context.getPhysicalDevice();
4872     const auto &vkd     = context.getDeviceInterface();
4873     const auto device   = context.getDevice();
4874     auto &alloc         = context.getDefaultAllocator();
4875     const auto dsFormat = getSupportedDepthStencilFormat(vki, physDev);
4876 
4877     try
4878     {
4879         ManyDrawsAllocatedData allocatedData(vkd, device, alloc, m_params.imageExtent, getColorFormat(), dsFormat);
4880     }
4881     catch (const vk::Error &err)
4882     {
4883         const auto result = err.getError();
4884         if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY)
4885             TCU_THROW(NotSupportedError, "Not enough memory to run this test");
4886         throw;
4887     }
4888 }
4889 
initPrograms(vk::SourceCollections & programCollection) const4890 void ManyDrawsCase::initPrograms(vk::SourceCollections &programCollection) const
4891 {
4892     std::ostringstream vert;
4893     vert << "#version 450\n"
4894          << "\n"
4895          << "layout(location=0) in vec2 inCoords;\n"
4896          << "layout(location=1) in uvec4 inColor;\n"
4897          << "\n"
4898          << "layout(location=0) out flat uvec4 outColor;\n"
4899          << "\n"
4900          << "void main()\n"
4901          << "{\n"
4902          << "    gl_Position = vec4(inCoords, 0.0, 1.0);\n"
4903          << "    outColor = inColor;\n"
4904          << "}\n";
4905 
4906     std::ostringstream frag;
4907     frag << "#version 450\n"
4908          << "\n"
4909          << "layout(location=0) in flat uvec4 inColor;\n"
4910          << "layout(location=0) out uvec4 outColor;\n"
4911          << "\n"
4912          << "void main()\n"
4913          << "{\n"
4914          << "    outColor = inColor;\n"
4915          << "}\n";
4916 
4917     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
4918     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
4919 }
4920 
createInstance(Context & context) const4921 TestInstance *ManyDrawsCase::createInstance(Context &context) const
4922 {
4923     return new ManyDrawsInstance(context, m_params);
4924 }
4925 
ManyDrawsInstance(Context & context,const ManyDrawsParams & params)4926 ManyDrawsInstance::ManyDrawsInstance(Context &context, const ManyDrawsParams &params)
4927     : TestInstance(context)
4928     , m_params(params)
4929 {
4930 }
4931 
copyAndFlush(const DeviceInterface & vkd,VkDevice device,BufferWithMemory & buffer,const std::vector<ManyDrawsVertex> & vertices)4932 void copyAndFlush(const DeviceInterface &vkd, VkDevice device, BufferWithMemory &buffer,
4933                   const std::vector<ManyDrawsVertex> &vertices)
4934 {
4935     auto &alloc   = buffer.getAllocation();
4936     void *hostPtr = alloc.getHostPtr();
4937 
4938     deMemcpy(hostPtr, vertices.data(), de::dataSize(vertices));
4939     flushAlloc(vkd, device, alloc);
4940 }
4941 
iterate(void)4942 tcu::TestStatus ManyDrawsInstance::iterate(void)
4943 {
4944     const auto &vki    = m_context.getInstanceInterface();
4945     const auto physDev = m_context.getPhysicalDevice();
4946     const auto &vkd    = m_context.getDeviceInterface();
4947     const auto device  = m_context.getDevice();
4948     auto &alloc        = m_context.getDefaultAllocator();
4949     const auto qIndex  = m_context.getUniversalQueueFamilyIndex();
4950     const auto queue   = m_context.getUniversalQueue();
4951 
4952     const auto colorFormat        = ManyDrawsCase::getColorFormat();
4953     const auto dsFormat           = getSupportedDepthStencilFormat(vki, physDev);
4954     const auto vertexBufferSize   = ManyDrawsAllocatedData::calcVertexBufferSize(m_params.imageExtent);
4955     const auto vertexBufferOffset = static_cast<VkDeviceSize>(0);
4956     const auto numPixels          = ManyDrawsAllocatedData::calcNumPixels(m_params.imageExtent);
4957     const auto numVertices        = ManyDrawsAllocatedData::calcNumVertices(m_params.imageExtent);
4958     const auto alphaValue         = std::numeric_limits<uint8_t>::max();
4959     const auto pixelWidth         = 2.0f / static_cast<float>(m_params.imageExtent.width);  // Normalized size.
4960     const auto pixelWidthHalf     = pixelWidth / 2.0f;                                      // Normalized size.
4961     const auto pixelHeight        = 2.0f / static_cast<float>(m_params.imageExtent.height); // Normalized size.
4962     const auto useSecondary       = (m_params.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);
4963 
4964     // Allocate all needed data up front.
4965     ManyDrawsAllocatedData testData(vkd, device, alloc, m_params.imageExtent, colorFormat, dsFormat);
4966 
4967     // Generate random colors.
4968     de::Random rnd(m_params.seed);
4969     std::vector<ManyDrawsVertex::Color> colors;
4970 
4971     colors.reserve(numPixels);
4972     for (uint32_t i = 0; i < numPixels; ++i)
4973     {
4974 #if 0
4975         const uint8_t red = ((i      ) & 0xFFu);
4976         const uint8_t green = ((i >>  8) & 0xFFu);
4977         const uint8_t blue = ((i >> 16) & 0xFFu);
4978         colors.push_back(ManyDrawsVertex::Color(red, green, blue, alphaValue));
4979 #else
4980         colors.push_back(ManyDrawsVertex::Color(rnd.getUint8(), rnd.getUint8(), rnd.getUint8(), alphaValue));
4981 #endif
4982     }
4983 
4984     // Fill vertex data. One triangle per pixel, front and back.
4985     std::vector<ManyDrawsVertex> frontVector;
4986     std::vector<ManyDrawsVertex> backVector;
4987     frontVector.reserve(numVertices);
4988     backVector.reserve(numVertices);
4989 
4990     for (uint32_t y = 0; y < m_params.imageExtent.height; ++y)
4991         for (uint32_t x = 0; x < m_params.imageExtent.width; ++x)
4992         {
4993             float x_left   = static_cast<float>(x) * pixelWidth - 1.0f;
4994             float x_mid    = x_left + pixelWidthHalf;
4995             float x_right  = x_left + pixelWidth;
4996             float y_top    = static_cast<float>(y) * pixelHeight - 1.0f;
4997             float y_bottom = y_top + pixelHeight;
4998 
4999             // Triangles in the "back" mesh will have different colors.
5000             const auto colorIdx    = y * m_params.imageExtent.width + x;
5001             const auto &frontColor = colors[colorIdx];
5002             const auto &backColor  = colors[colors.size() - 1u - colorIdx];
5003 
5004             const tcu::Vec2 triangle[3u] = {
5005                 tcu::Vec2(x_left, y_top),
5006                 tcu::Vec2(x_right, y_top),
5007                 tcu::Vec2(x_mid, y_bottom),
5008             };
5009 
5010             frontVector.emplace_back(triangle[0], frontColor);
5011             frontVector.emplace_back(triangle[1], frontColor);
5012             frontVector.emplace_back(triangle[2], frontColor);
5013 
5014             backVector.emplace_back(triangle[0], backColor);
5015             backVector.emplace_back(triangle[1], backColor);
5016             backVector.emplace_back(triangle[2], backColor);
5017         }
5018 
5019     // Copy vertex data to staging buffers.
5020     copyAndFlush(vkd, device, *testData.frontBuffers.stagingBuffer, frontVector);
5021     copyAndFlush(vkd, device, *testData.backBuffers.stagingBuffer, backVector);
5022 
5023     // Color attachment view.
5024     const auto colorResourceRange  = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
5025     const auto colorAttachmentView = makeImageView(vkd, device, testData.colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D,
5026                                                    colorFormat, colorResourceRange);
5027 
5028     // Depth/stencil attachment view.
5029     const auto dsResourceRange =
5030         makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
5031     const auto dsAttachmentView =
5032         makeImageView(vkd, device, testData.dsAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsResourceRange);
5033 
5034     const VkImageView attachmentArray[] = {colorAttachmentView.get(), dsAttachmentView.get()};
5035     const auto numAttachments           = static_cast<uint32_t>(DE_LENGTH_OF_ARRAY(attachmentArray));
5036 
5037     const auto renderPass  = makeRenderPass(vkd, device, colorFormat, dsFormat);
5038     const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), numAttachments, attachmentArray,
5039                                              m_params.imageExtent.width, m_params.imageExtent.height);
5040 
5041     const auto vertModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
5042     const auto fragModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
5043 
5044     const std::vector<VkViewport> viewports(1u, makeViewport(m_params.imageExtent));
5045     const std::vector<VkRect2D> scissors(1u, makeRect2D(m_params.imageExtent));
5046 
5047     const auto descriptorSetLayout = DescriptorSetLayoutBuilder().build(vkd, device);
5048     const auto pipelineLayout      = makePipelineLayout(vkd, device, descriptorSetLayout.get());
5049 
5050     const VkVertexInputBindingDescription bindings[] = {
5051         makeVertexInputBindingDescription(0u, static_cast<uint32_t>(sizeof(ManyDrawsVertex)),
5052                                           VK_VERTEX_INPUT_RATE_VERTEX),
5053     };
5054 
5055     const VkVertexInputAttributeDescription attributes[] = {
5056         makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32_SFLOAT,
5057                                             static_cast<uint32_t>(offsetof(ManyDrawsVertex, coords))),
5058         makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R8G8B8A8_UINT,
5059                                             static_cast<uint32_t>(offsetof(ManyDrawsVertex, color))),
5060     };
5061 
5062     const VkPipelineVertexInputStateCreateInfo inputState = {
5063         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
5064         nullptr,                                                   // const void* pNext;
5065         0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
5066         static_cast<uint32_t>(DE_LENGTH_OF_ARRAY(bindings)),       // uint32_t vertexBindingDescriptionCount;
5067         bindings, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
5068         static_cast<uint32_t>(DE_LENGTH_OF_ARRAY(attributes)), // uint32_t vertexAttributeDescriptionCount;
5069         attributes, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
5070     };
5071 
5072     // Stencil state: this is key for checking and obtaining the right results. The stencil buffer will be cleared to 0. The first
5073     // set of draws ("front" set of triangles) will pass the test and increment the stencil value to 1. The second set of draws
5074     // ("back" set of triangles, not really in the back because all of them have depth 0.0) will not pass the stencil test then, but
5075     // still increment the stencil value to 2.
5076     //
5077     // At the end of the test, if every draw command was executed correctly in the expected order, the color buffer will have the
5078     // colors of the front set, and the stencil buffer will be full of 2s.
5079     const auto stencilOpState = makeStencilOpState(VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP,
5080                                                    VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xFFu, 0xFFu, 0u);
5081 
5082     const VkPipelineDepthStencilStateCreateInfo dsState = {
5083         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                          sType
5084         nullptr,                                                    // const void*                              pNext
5085         0u,                                                         // VkPipelineDepthStencilStateCreateFlags   flags
5086         VK_FALSE,            // VkBool32                                 depthTestEnable
5087         VK_FALSE,            // VkBool32                                 depthWriteEnable
5088         VK_COMPARE_OP_NEVER, // VkCompareOp                              depthCompareOp
5089         VK_FALSE,            // VkBool32                                 depthBoundsTestEnable
5090         VK_TRUE,             // VkBool32                                 stencilTestEnable
5091         stencilOpState,      // VkStencilOpState                         front
5092         stencilOpState,      // VkStencilOpState                         back
5093         0.0f,                // float                                    minDepthBounds
5094         1.0f,                // float                                    maxDepthBounds
5095     };
5096 
5097     const auto pipeline =
5098         makeGraphicsPipeline(vkd, device, pipelineLayout.get(), vertModule.get(), DE_NULL, DE_NULL, DE_NULL,
5099                              fragModule.get(), renderPass.get(), viewports, scissors,
5100                              VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &inputState, nullptr, nullptr, &dsState);
5101 
5102     // Command pool and buffers.
5103     using CmdBufferPtr    = Move<VkCommandBuffer>;
5104     const auto cmdPool    = makeCommandPool(vkd, device, qIndex);
5105     const auto secCmdPool = makeCommandPool(vkd, device, qIndex);
5106 
5107     CmdBufferPtr primaryCmdBufferPtr;
5108     CmdBufferPtr secondaryCmdBufferPtr;
5109     VkCommandBuffer primaryCmdBuffer;
5110     VkCommandBuffer secondaryCmdBuffer;
5111     VkCommandBuffer drawsCmdBuffer;
5112 
5113     primaryCmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5114     primaryCmdBuffer    = primaryCmdBufferPtr.get();
5115     drawsCmdBuffer      = primaryCmdBuffer;
5116     beginCommandBuffer(vkd, primaryCmdBuffer);
5117 
5118     // Clear values.
5119     std::vector<VkClearValue> clearValues(2u);
5120     clearValues[0] = makeClearValueColorU32(0u, 0u, 0u, 0u);
5121     clearValues[1] = makeClearValueDepthStencil(1.0f, 0u);
5122 
5123     // Copy staging buffers to vertex buffers.
5124     const auto copyRegion = makeBufferCopy(0ull, 0ull, vertexBufferSize);
5125     vkd.cmdCopyBuffer(primaryCmdBuffer, testData.frontBuffers.stagingBuffer->get(),
5126                       testData.frontBuffers.vertexBuffer->get(), 1u, &copyRegion);
5127     vkd.cmdCopyBuffer(primaryCmdBuffer, testData.backBuffers.stagingBuffer->get(),
5128                       testData.backBuffers.vertexBuffer->get(), 1u, &copyRegion);
5129 
5130     // Use barrier for vertex reads.
5131     const auto vertexBarier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
5132     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 1u,
5133                            &vertexBarier, 0u, nullptr, 0u, nullptr);
5134 
5135     // Change depth/stencil attachment layout.
5136     const auto dsBarrier = makeImageMemoryBarrier(
5137         0, (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT),
5138         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, testData.dsAttachment->get(),
5139         dsResourceRange);
5140     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
5141                            (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), 0u,
5142                            0u, nullptr, 0u, nullptr, 1u, &dsBarrier);
5143 
5144     beginRenderPass(vkd, primaryCmdBuffer, renderPass.get(), framebuffer.get(), scissors[0],
5145                     static_cast<uint32_t>(clearValues.size()), clearValues.data(),
5146                     (useSecondary ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE));
5147 
5148     if (useSecondary)
5149     {
5150         secondaryCmdBufferPtr = allocateCommandBuffer(vkd, device, secCmdPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5151         secondaryCmdBuffer    = secondaryCmdBufferPtr.get();
5152         drawsCmdBuffer        = secondaryCmdBuffer;
5153 
5154         const VkCommandBufferInheritanceInfo inheritanceInfo = {
5155             VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
5156             nullptr,                                           // const void* pNext;
5157             renderPass.get(),                                  // VkRenderPass renderPass;
5158             0u,                                                // uint32_t subpass;
5159             framebuffer.get(),                                 // VkFramebuffer framebuffer;
5160             0u,                                                // VkBool32 occlusionQueryEnable;
5161             0u,                                                // VkQueryControlFlags queryFlags;
5162             0u,                                                // VkQueryPipelineStatisticFlags pipelineStatistics;
5163         };
5164 
5165         const VkCommandBufferUsageFlags usageFlags =
5166             (VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
5167         const VkCommandBufferBeginInfo beginInfo = {
5168             VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
5169             usageFlags,       // VkCommandBufferUsageFlags flags;
5170             &inheritanceInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
5171         };
5172 
5173         VK_CHECK(vkd.beginCommandBuffer(secondaryCmdBuffer, &beginInfo));
5174     }
5175 
5176     // Bind pipeline.
5177     vkd.cmdBindPipeline(drawsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
5178 
5179     // Draw triangles in front.
5180     vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.frontBuffers.vertexBuffer->get(), &vertexBufferOffset);
5181     for (uint32_t i = 0; i < numPixels; ++i)
5182         vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i * 3u, 0u);
5183 
5184     // Draw triangles in the "back". This should have no effect due to the stencil test.
5185     vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.backBuffers.vertexBuffer->get(), &vertexBufferOffset);
5186     for (uint32_t i = 0; i < numPixels; ++i)
5187         vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i * 3u, 0u);
5188 
5189     if (useSecondary)
5190     {
5191         endCommandBuffer(vkd, secondaryCmdBuffer);
5192         vkd.cmdExecuteCommands(primaryCmdBuffer, 1u, &secondaryCmdBuffer);
5193     }
5194 
5195     endRenderPass(vkd, primaryCmdBuffer);
5196 
5197     // Copy color and depth/stencil attachments to verification buffers.
5198     const auto colorAttachmentBarrier = makeImageMemoryBarrier(
5199         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5200         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.colorAttachment->get(), colorResourceRange);
5201     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
5202                            VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorAttachmentBarrier);
5203 
5204     const auto colorResourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
5205     const auto colorCopyRegion     = makeBufferImageCopy(m_params.imageExtent, colorResourceLayers);
5206     vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.colorAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5207                              testData.colorCheckBuffer->get(), 1u, &colorCopyRegion);
5208 
5209     const auto stencilAttachmentBarrier =
5210         makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
5211                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5212                                testData.dsAttachment->get(), dsResourceRange);
5213     vkd.cmdPipelineBarrier(primaryCmdBuffer,
5214                            (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT),
5215                            VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &stencilAttachmentBarrier);
5216 
5217     const auto stencilResourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u);
5218     const auto stencilCopyRegion     = makeBufferImageCopy(m_params.imageExtent, stencilResourceLayers);
5219     vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.dsAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5220                              testData.stencilCheckBuffer->get(), 1u, &stencilCopyRegion);
5221 
5222     const auto verificationBuffersBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5223     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u,
5224                            &verificationBuffersBarrier, 0u, nullptr, 0u, nullptr);
5225 
5226     endCommandBuffer(vkd, primaryCmdBuffer);
5227     submitCommandsAndWait(vkd, device, queue, primaryCmdBuffer);
5228 
5229     // Check buffer contents.
5230     auto &colorCheckBufferAlloc = testData.colorCheckBuffer->getAllocation();
5231     void *colorCheckBufferData  = colorCheckBufferAlloc.getHostPtr();
5232     invalidateAlloc(vkd, device, colorCheckBufferAlloc);
5233 
5234     auto &stencilCheckBufferAlloc = testData.stencilCheckBuffer->getAllocation();
5235     void *stencilCheckBufferData  = stencilCheckBufferAlloc.getHostPtr();
5236     invalidateAlloc(vkd, device, stencilCheckBufferAlloc);
5237 
5238     const auto iWidth           = static_cast<int>(m_params.imageExtent.width);
5239     const auto iHeight          = static_cast<int>(m_params.imageExtent.height);
5240     const auto colorTcuFormat   = mapVkFormat(colorFormat);
5241     const auto stencilTcuFormat = tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
5242 
5243     tcu::TextureLevel referenceLevel(colorTcuFormat, iWidth, iHeight);
5244     tcu::PixelBufferAccess referenceAccess = referenceLevel.getAccess();
5245     tcu::TextureLevel colorErrorLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
5246     tcu::PixelBufferAccess colorErrorAccess = colorErrorLevel.getAccess();
5247     tcu::TextureLevel stencilErrorLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
5248     tcu::PixelBufferAccess stencilErrorAccess = stencilErrorLevel.getAccess();
5249     tcu::ConstPixelBufferAccess colorAccess(colorTcuFormat, iWidth, iHeight, 1, colorCheckBufferData);
5250     tcu::ConstPixelBufferAccess stencilAccess(stencilTcuFormat, iWidth, iHeight, 1, stencilCheckBufferData);
5251     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
5252     const tcu::Vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
5253     const int expectedStencil = 2;
5254     bool colorFail            = false;
5255     bool stencilFail          = false;
5256 
5257     for (int y = 0; y < iHeight; ++y)
5258         for (int x = 0; x < iWidth; ++x)
5259         {
5260             const tcu::UVec4 colorValue = colorAccess.getPixelUint(x, y);
5261             const auto expectedPixel    = colors[y * iWidth + x];
5262             const tcu::UVec4 expectedValue(expectedPixel.x(), expectedPixel.y(), expectedPixel.z(), expectedPixel.w());
5263             const bool colorMismatch = (colorValue != expectedValue);
5264 
5265             const auto stencilValue    = stencilAccess.getPixStencil(x, y);
5266             const bool stencilMismatch = (stencilValue != expectedStencil);
5267 
5268             referenceAccess.setPixel(expectedValue, x, y);
5269             colorErrorAccess.setPixel((colorMismatch ? red : green), x, y);
5270             stencilErrorAccess.setPixel((stencilMismatch ? red : green), x, y);
5271 
5272             if (stencilMismatch)
5273                 stencilFail = true;
5274 
5275             if (colorMismatch)
5276                 colorFail = true;
5277         }
5278 
5279     if (colorFail || stencilFail)
5280     {
5281         auto &log = m_context.getTestContext().getLog();
5282         log << tcu::TestLog::ImageSet("Result", "") << tcu::TestLog::Image("ColorOutput", "", colorAccess)
5283             << tcu::TestLog::Image("ColorReference", "", referenceAccess)
5284             << tcu::TestLog::Image("ColorError", "", colorErrorAccess)
5285             << tcu::TestLog::Image("StencilError", "", stencilErrorAccess) << tcu::TestLog::EndImageSet;
5286         TCU_FAIL("Mismatched output and reference color or stencil; please check test log --");
5287     }
5288 
5289     return tcu::TestStatus::pass("Pass");
5290 }
5291 
initManyIndirectDrawsPrograms(SourceCollections & dst)5292 void initManyIndirectDrawsPrograms(SourceCollections &dst)
5293 {
5294     std::ostringstream vert;
5295     vert << "#version 460\n"
5296          << "layout (location=0) in vec4 inPos;\n"
5297          << "void main (void) {\n"
5298          << "    gl_PointSize = 1.0;\n"
5299          << "    gl_Position = inPos;\n"
5300          << "}\n";
5301     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
5302 
5303     std::ostringstream frag;
5304     frag << "#version 460\n"
5305          << "layout (location=0) out vec4 outColor;\n"
5306          << "void main (void) {\n"
5307          << "    outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
5308          << "}\n";
5309     dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
5310 }
5311 
manyIndirectDrawsTest(Context & context)5312 tcu::TestStatus manyIndirectDrawsTest(Context &context)
5313 {
5314     const auto &ctx = context.getContextCommonData();
5315     const tcu::IVec3 fbExtent(64, 64, 1);
5316     const auto vkExtent   = makeExtent3D(fbExtent);
5317     const auto floatExt   = fbExtent.cast<float>();
5318     const auto pixelCount = vkExtent.width * vkExtent.height;
5319     const auto fbFormat   = VK_FORMAT_R8G8B8A8_UNORM;
5320     const auto tcuFormat  = mapVkFormat(fbFormat);
5321     const auto fbUsage    = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
5322     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
5323     const tcu::Vec4 geomColor(0.0f, 0.0f, 1.0f, 1.0f); // Must match fragment shader.
5324     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
5325     const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
5326 
5327     // Color buffer with verification buffer.
5328     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
5329 
5330     // Vertices for each point.
5331     std::vector<tcu::Vec4> vertices;
5332     vertices.reserve(pixelCount);
5333     for (int y = 0; y < fbExtent.y(); ++y)
5334         for (int x = 0; x < fbExtent.x(); ++x)
5335         {
5336             const auto xCoord = ((static_cast<float>(x) + 0.5f) / floatExt.x()) * 2.0f - 1.0f;
5337             const auto yCoord = ((static_cast<float>(y) + 0.5f) / floatExt.y()) * 2.0f - 1.0f;
5338             vertices.push_back(tcu::Vec4(xCoord, yCoord, 0.0f, 1.0f));
5339         };
5340 
5341     // Vertex buffer
5342     const auto vbSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
5343     const auto vbInfo = makeBufferCreateInfo(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
5344     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vbInfo, MemoryRequirement::HostVisible);
5345     const auto vbAlloc  = vertexBuffer.getAllocation();
5346     void *vbData        = vbAlloc.getHostPtr();
5347     const auto vbOffset = static_cast<VkDeviceSize>(0);
5348 
5349     deMemcpy(vbData, de::dataOrNull(vertices), de::dataSize(vertices));
5350     flushAlloc(ctx.vkd, ctx.device, vbAlloc);
5351 
5352     std::vector<VkDrawIndirectCommand> indirectCommands;
5353     indirectCommands.reserve(pixelCount);
5354     const auto indirectCmdSize = static_cast<uint32_t>(sizeof(decltype(indirectCommands)::value_type));
5355 
5356     for (uint32_t i = 0u; i < pixelCount; ++i)
5357     {
5358         indirectCommands.push_back({
5359             1u, // uint32_t vertexCount;
5360             1u, // uint32_t instanceCount;
5361             i,  // uint32_t firstVertex;
5362             0u, // uint32_t firstInstance;
5363         });
5364     }
5365 
5366     // Indirect draw buffer.
5367     const auto ibSize = static_cast<VkDeviceSize>(de::dataSize(indirectCommands));
5368     const auto ibInfo = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
5369     BufferWithMemory indirectBuffer(ctx.vkd, ctx.device, ctx.allocator, ibInfo, MemoryRequirement::HostVisible);
5370     const auto ibAlloc = indirectBuffer.getAllocation();
5371     void *ibData       = ibAlloc.getHostPtr();
5372 
5373     deMemcpy(ibData, de::dataOrNull(indirectCommands), de::dataSize(indirectCommands));
5374     flushAlloc(ctx.vkd, ctx.device, ibAlloc);
5375 
5376     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
5377     const auto renderPass     = makeRenderPass(ctx.vkd, ctx.device, fbFormat);
5378     const auto framebuffer =
5379         makeFramebuffer(ctx.vkd, ctx.device, *renderPass, colorBuffer.getImageView(), vkExtent.width, vkExtent.height);
5380 
5381     // Modules.
5382     const auto &binaries  = context.getBinaryCollection();
5383     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
5384     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
5385 
5386     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
5387     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
5388 
5389     // Other default values work for the current setup, including the vertex input data format.
5390     const auto pipeline = makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout, *vertModule, VK_NULL_HANDLE,
5391                                                VK_NULL_HANDLE, VK_NULL_HANDLE, *fragModule, *renderPass, viewports,
5392                                                scissors, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
5393 
5394     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
5395     const auto cmdBuffer = *cmd.cmdBuffer;
5396     const auto secCmdBuffer =
5397         allocateCommandBuffer(ctx.vkd, ctx.device, *cmd.cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5398 
5399     beginSecondaryCommandBuffer(ctx.vkd, *secCmdBuffer, *renderPass, *framebuffer);
5400     ctx.vkd.cmdBindVertexBuffers(*secCmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
5401     ctx.vkd.cmdBindPipeline(*secCmdBuffer, bindPoint, *pipeline);
5402     for (uint32_t i = 0; i < pixelCount; ++i)
5403         ctx.vkd.cmdDrawIndirect(*secCmdBuffer, indirectBuffer.get(), static_cast<VkDeviceSize>(i * indirectCmdSize), 1u,
5404                                 indirectCmdSize);
5405     endCommandBuffer(ctx.vkd, *secCmdBuffer);
5406 
5407     beginCommandBuffer(ctx.vkd, cmdBuffer);
5408     beginRenderPass(ctx.vkd, cmdBuffer, *renderPass, *framebuffer, scissors.at(0u), clearColor,
5409                     VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
5410     ctx.vkd.cmdExecuteCommands(cmdBuffer, 1u, &(*secCmdBuffer));
5411     endRenderPass(ctx.vkd, cmdBuffer);
5412     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1),
5413                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
5414                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
5415                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
5416     endCommandBuffer(ctx.vkd, cmdBuffer);
5417     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
5418 
5419     // Verify color output.
5420     invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
5421     tcu::PixelBufferAccess resultAccess(tcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
5422 
5423     tcu::TextureLevel referenceLevel(tcuFormat, fbExtent.x(), fbExtent.y());
5424     auto referenceAccess = referenceLevel.getAccess();
5425     tcu::clear(referenceAccess, geomColor);
5426 
5427     auto &log = context.getTestContext().getLog();
5428     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold,
5429                                     tcu::COMPARE_LOG_ON_ERROR))
5430         return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
5431 
5432     return tcu::TestStatus::pass("Pass");
5433 }
5434 
5435 constexpr uint32_t kIndirectDispatchValueOffset = 1000000u;
5436 
initManyIndirectDispatchesPrograms(SourceCollections & dst)5437 void initManyIndirectDispatchesPrograms(SourceCollections &dst)
5438 {
5439     std::ostringstream comp;
5440     comp << "#version 460\n"
5441          << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
5442          << "layout (push_constant, std430) uniform PushConstantBlock { uint index; } pc;\n"
5443          << "layout (set=0, binding=0, std430) buffer OutputBlock { uint data[]; } outputValues;\n"
5444          << "void main (void) {\n"
5445          << "    outputValues.data[pc.index] += pc.index + " << kIndirectDispatchValueOffset << "u;\n"
5446          << "}\n";
5447     dst.glslSources.add("comp") << glu::ComputeSource(comp.str());
5448 }
5449 
checkManyIndirectDispatchesSupport(Context & context)5450 void checkManyIndirectDispatchesSupport(Context &context)
5451 {
5452     // The device must have support for a compute queue.
5453     // getComputeQueue() will throw NotSupportedError if the device doesn't have one.
5454     context.getComputeQueue();
5455 }
5456 
manyIndirectDispatchesTest(Context & context)5457 tcu::TestStatus manyIndirectDispatchesTest(Context &context)
5458 {
5459     const auto &ctx       = context.getContextCommonData();
5460     const auto descType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
5461     const auto bindPoint  = VK_PIPELINE_BIND_POINT_COMPUTE;
5462     const auto dataStages = VK_SHADER_STAGE_COMPUTE_BIT;
5463     const auto valueCount = 4096u;
5464     const auto qfIndex    = context.getComputeQueueFamilyIndex();
5465     const auto queue      = context.getComputeQueue();
5466 
5467     // Host-side buffer values.
5468     std::vector<uint32_t> bufferValues(valueCount, 0u);
5469 
5470     // Storage buffer.
5471     const auto sbSize = static_cast<VkDeviceSize>(de::dataSize(bufferValues));
5472     const auto sbInfo = makeBufferCreateInfo(sbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
5473     BufferWithMemory storageBuffer(ctx.vkd, ctx.device, ctx.allocator, sbInfo, MemoryRequirement::HostVisible);
5474     const auto sbAlloc  = storageBuffer.getAllocation();
5475     void *sbData        = sbAlloc.getHostPtr();
5476     const auto sbOffset = static_cast<VkDeviceSize>(0);
5477 
5478     deMemcpy(sbData, de::dataOrNull(bufferValues), de::dataSize(bufferValues));
5479     flushAlloc(ctx.vkd, ctx.device, sbAlloc);
5480 
5481     // Indirect dispatch buffer. We'll pretend to have 4096 indirect commands but all of them will launch 1 group with 1 invocation.
5482     const VkDispatchIndirectCommand defaultCommand{1u, 1u, 1u};
5483     const std::vector<VkDispatchIndirectCommand> indirectCommands(valueCount, defaultCommand);
5484 
5485     const auto ibSize = static_cast<VkDeviceSize>(de::dataSize(indirectCommands));
5486     const auto ibInfo = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
5487     BufferWithMemory indirectBuffer(ctx.vkd, ctx.device, ctx.allocator, ibInfo, MemoryRequirement::HostVisible);
5488     const auto ibAlloc = indirectBuffer.getAllocation();
5489     void *ibData       = ibAlloc.getHostPtr();
5490 
5491     deMemcpy(ibData, de::dataOrNull(indirectCommands), de::dataSize(indirectCommands));
5492     flushAlloc(ctx.vkd, ctx.device, ibAlloc);
5493 
5494     // Descriptor pool, set, layout, etc.
5495     DescriptorPoolBuilder poolBuilder;
5496     poolBuilder.addType(descType);
5497     const auto descriptorPool =
5498         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
5499 
5500     DescriptorSetLayoutBuilder layoutBuilder;
5501     layoutBuilder.addSingleBinding(descType, dataStages);
5502     const auto setLayout     = layoutBuilder.build(ctx.vkd, ctx.device);
5503     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
5504 
5505     DescriptorSetUpdateBuilder updateBuilder;
5506     const auto dbDescInfo = makeDescriptorBufferInfo(storageBuffer.get(), sbOffset, sbSize);
5507     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &dbDescInfo);
5508     updateBuilder.update(ctx.vkd, ctx.device);
5509 
5510     // Push constants.
5511     const auto pcSize  = static_cast<uint32_t>(sizeof(uint32_t));
5512     const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
5513 
5514     // Layout and pipeline.
5515     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, *setLayout, &pcRange);
5516     const auto &binaries      = context.getBinaryCollection();
5517     const auto compModule     = createShaderModule(ctx.vkd, ctx.device, binaries.get("comp"));
5518     const auto pipeline       = makeComputePipeline(ctx.vkd, ctx.device, *pipelineLayout, *compModule);
5519 
5520     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, qfIndex);
5521     const auto cmdBuffer = *cmd.cmdBuffer;
5522     const auto secCmdBufferPtr =
5523         allocateCommandBuffer(ctx.vkd, ctx.device, *cmd.cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5524     const auto secCmdBuffer = *secCmdBufferPtr;
5525 
5526     beginSecondaryCommandBuffer(ctx.vkd, secCmdBuffer);
5527     ctx.vkd.cmdBindPipeline(secCmdBuffer, bindPoint, *pipeline);
5528     ctx.vkd.cmdBindDescriptorSets(secCmdBuffer, bindPoint, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
5529     for (uint32_t i = 0; i < valueCount; ++i)
5530     {
5531         ctx.vkd.cmdPushConstants(secCmdBuffer, *pipelineLayout, dataStages, 0u, pcSize, &i);
5532         const auto dispatchOffset = static_cast<VkDeviceSize>(i * sizeof(VkDispatchIndirectCommand));
5533         ctx.vkd.cmdDispatchIndirect(secCmdBuffer, indirectBuffer.get(), dispatchOffset);
5534     }
5535     endCommandBuffer(ctx.vkd, secCmdBuffer);
5536 
5537     beginCommandBuffer(ctx.vkd, cmdBuffer);
5538     ctx.vkd.cmdExecuteCommands(cmdBuffer, 1u, &secCmdBuffer);
5539     {
5540         const auto compute2Host = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5541         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
5542                                  &compute2Host);
5543     }
5544     endCommandBuffer(ctx.vkd, cmdBuffer);
5545     submitCommandsAndWait(ctx.vkd, ctx.device, queue, cmdBuffer);
5546 
5547     // Verify values.
5548     std::vector<uint32_t> outputValues(valueCount, 0u);
5549     invalidateAlloc(ctx.vkd, ctx.device, sbAlloc);
5550     deMemcpy(outputValues.data(), sbData, de::dataSize(outputValues));
5551 
5552     for (uint32_t i = 0u; i < valueCount; ++i)
5553     {
5554         const auto refValue = bufferValues[i] + i + kIndirectDispatchValueOffset;
5555         if (outputValues[i] != refValue)
5556         {
5557             std::ostringstream msg;
5558             msg << "Unexpected value found at position " << i << ": expected " << refValue << " but found "
5559                 << outputValues[i];
5560             TCU_FAIL(msg.str());
5561         }
5562     }
5563 
5564     return tcu::TestStatus::pass("Pass");
5565 }
5566 
5567 struct IndirectDispatchAlignmentParams
5568 {
5569     uint32_t memOffset;
5570     uint32_t dispatchOffset;
5571 };
5572 
5573 class IndirectDispatchAlignmentInstance : public vkt::TestInstance
5574 {
5575 public:
IndirectDispatchAlignmentInstance(Context & context,const IndirectDispatchAlignmentParams & params)5576     IndirectDispatchAlignmentInstance(Context &context, const IndirectDispatchAlignmentParams &params)
5577         : vkt::TestInstance(context)
5578         , m_params(params)
5579     {
5580     }
~IndirectDispatchAlignmentInstance(void)5581     virtual ~IndirectDispatchAlignmentInstance(void)
5582     {
5583     }
5584 
5585     tcu::TestStatus iterate(void) override;
5586 
5587 protected:
5588     const IndirectDispatchAlignmentParams m_params;
5589 };
5590 
5591 class IndirectDispatchAlignmentCase : public vkt::TestCase
5592 {
5593 public:
IndirectDispatchAlignmentCase(tcu::TestContext & testCtx,const std::string & name,const IndirectDispatchAlignmentParams & params)5594     IndirectDispatchAlignmentCase(tcu::TestContext &testCtx, const std::string &name,
5595                                   const IndirectDispatchAlignmentParams &params)
5596         : vkt::TestCase(testCtx, name)
5597         , m_params(params)
5598     {
5599     }
~IndirectDispatchAlignmentCase(void)5600     virtual ~IndirectDispatchAlignmentCase(void)
5601     {
5602     }
5603 
5604     void initPrograms(vk::SourceCollections &programCollection) const override;
5605     TestInstance *createInstance(Context &context) const override;
5606     void checkSupport(Context &context) const override;
5607 
5608 protected:
5609     const IndirectDispatchAlignmentParams m_params;
5610 };
5611 
checkSupport(Context & context) const5612 void IndirectDispatchAlignmentCase::checkSupport(Context &context) const
5613 {
5614     // Will throw NotSupportedError if not found.
5615     context.getComputeQueue();
5616 }
5617 
initPrograms(vk::SourceCollections & programCollection) const5618 void IndirectDispatchAlignmentCase::initPrograms(vk::SourceCollections &programCollection) const
5619 {
5620     std::ostringstream comp;
5621     comp << "#version 460\n"
5622          << "layout (local_size_x=64, local_size_y=1, local_size_z=1) in;\n"
5623          << "layout (set=0, binding=0, std430) buffer OutputBlock { uint data[64]; } outputValues;\n"
5624          << "void main (void) {\n"
5625          << "    outputValues.data[gl_LocalInvocationIndex] += gl_LocalInvocationIndex + "
5626          << kIndirectDispatchValueOffset << "u;\n"
5627          << "}\n";
5628     programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
5629 }
5630 
createInstance(Context & context) const5631 TestInstance *IndirectDispatchAlignmentCase::createInstance(Context &context) const
5632 {
5633     return new IndirectDispatchAlignmentInstance(context, m_params);
5634 }
5635 
iterate(void)5636 tcu::TestStatus IndirectDispatchAlignmentInstance::iterate(void)
5637 {
5638     const auto &ctx       = m_context.getContextCommonData();
5639     const auto descType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
5640     const auto bindPoint  = VK_PIPELINE_BIND_POINT_COMPUTE;
5641     const auto dataStages = VK_SHADER_STAGE_COMPUTE_BIT;
5642     const auto valueCount = 64u; // Must match compute shader.
5643     const auto qfIndex    = m_context.getComputeQueueFamilyIndex();
5644     const auto queue      = m_context.getComputeQueue();
5645     auto &log             = m_context.getTestContext().getLog();
5646 
5647     // Host-side buffer values.
5648     std::vector<uint32_t> bufferValues(valueCount, 0u);
5649 
5650     // Storage buffer.
5651     const auto sbSize = static_cast<VkDeviceSize>(de::dataSize(bufferValues));
5652     const auto sbInfo = makeBufferCreateInfo(sbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
5653     BufferWithMemory storageBuffer(ctx.vkd, ctx.device, ctx.allocator, sbInfo, MemoryRequirement::HostVisible);
5654     const auto sbAlloc  = storageBuffer.getAllocation();
5655     void *sbData        = sbAlloc.getHostPtr();
5656     const auto sbOffset = static_cast<VkDeviceSize>(0);
5657 
5658     deMemcpy(sbData, de::dataOrNull(bufferValues), de::dataSize(bufferValues));
5659     flushAlloc(ctx.vkd, ctx.device, sbAlloc);
5660 
5661     // Indirect dispatch buffer contents.
5662     const VkDispatchIndirectCommand defaultCommand{1u, 1u, 1u};
5663     const std::vector<VkDispatchIndirectCommand> indirectCommands(1u, defaultCommand);
5664 
5665     // Note the calculated indirect buffer size takes into account the dispatche offset.
5666     const auto ibSize         = static_cast<VkDeviceSize>(m_params.dispatchOffset + de::dataSize(indirectCommands));
5667     const auto ibInfo         = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
5668     const auto indirectBuffer = makeBuffer(ctx.vkd, ctx.device, ibInfo);
5669 
5670     // Allocate more memory if needed and bind with an offset.
5671     const auto memReqs   = getBufferMemoryRequirements(ctx.vkd, ctx.device, *indirectBuffer);
5672     const auto memOffset = de::roundUp(static_cast<VkDeviceSize>(m_params.memOffset), memReqs.alignment);
5673 
5674     log << tcu::TestLog::Message << "Test parameters: memoryOffset=" << m_params.memOffset
5675         << " dispatchOffset=" << m_params.dispatchOffset << tcu::TestLog::EndMessage;
5676     log << tcu::TestLog::Message << "Buffer memory requirements: size=" << memReqs.size
5677         << " alignment=" << memReqs.alignment << tcu::TestLog::EndMessage;
5678     log << tcu::TestLog::Message << "Used memory offset: " << memOffset << tcu::TestLog::EndMessage;
5679 
5680     const VkMemoryRequirements allocationRequirements = {
5681         memOffset + memReqs.size, // VkDeviceSize size;
5682         memReqs.alignment,        // VkDeviceSize alignment;
5683         memReqs.memoryTypeBits,   // uint32_t memoryTypeBits;
5684     };
5685     const auto ibMemory = ctx.allocator.allocate(allocationRequirements, MemoryRequirement::HostVisible);
5686     ctx.vkd.bindBufferMemory(ctx.device, *indirectBuffer, ibMemory->getMemory(), memOffset);
5687 
5688     // Copy data to the buffer taking into account the dispatch offset.
5689     char *ibData = reinterpret_cast<char *>(ibMemory->getHostPtr()) + static_cast<size_t>(memOffset);
5690     deMemcpy(ibData + m_params.dispatchOffset, de::dataOrNull(indirectCommands), de::dataSize(indirectCommands));
5691     flushAlloc(ctx.vkd, ctx.device, *ibMemory);
5692 
5693     // Descriptor pool, set, layout, etc.
5694     DescriptorPoolBuilder poolBuilder;
5695     poolBuilder.addType(descType);
5696     const auto descriptorPool =
5697         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
5698 
5699     DescriptorSetLayoutBuilder layoutBuilder;
5700     layoutBuilder.addSingleBinding(descType, dataStages);
5701     const auto setLayout     = layoutBuilder.build(ctx.vkd, ctx.device);
5702     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
5703 
5704     DescriptorSetUpdateBuilder updateBuilder;
5705     const auto dbDescInfo = makeDescriptorBufferInfo(storageBuffer.get(), sbOffset, sbSize);
5706     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &dbDescInfo);
5707     updateBuilder.update(ctx.vkd, ctx.device);
5708 
5709     // Layout and pipeline.
5710     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, *setLayout);
5711     const auto &binaries      = m_context.getBinaryCollection();
5712     const auto compModule     = createShaderModule(ctx.vkd, ctx.device, binaries.get("comp"));
5713     const auto pipeline       = makeComputePipeline(ctx.vkd, ctx.device, *pipelineLayout, *compModule);
5714 
5715     // To make it more interesting, we'll also use secondary command buffers.
5716     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, qfIndex);
5717     const auto cmdBuffer = *cmd.cmdBuffer;
5718     const auto secCmdBufferPtr =
5719         allocateCommandBuffer(ctx.vkd, ctx.device, *cmd.cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5720     const auto secCmdBuffer = *secCmdBufferPtr;
5721 
5722     beginSecondaryCommandBuffer(ctx.vkd, secCmdBuffer);
5723     ctx.vkd.cmdBindPipeline(secCmdBuffer, bindPoint, *pipeline);
5724     ctx.vkd.cmdBindDescriptorSets(secCmdBuffer, bindPoint, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
5725     const auto dispatchOffset = m_params.dispatchOffset;
5726     ctx.vkd.cmdDispatchIndirect(secCmdBuffer, indirectBuffer.get(), dispatchOffset);
5727     endCommandBuffer(ctx.vkd, secCmdBuffer);
5728 
5729     beginCommandBuffer(ctx.vkd, cmdBuffer);
5730     ctx.vkd.cmdExecuteCommands(cmdBuffer, 1u, &secCmdBuffer);
5731     {
5732         const auto compute2Host = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5733         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
5734                                  &compute2Host);
5735     }
5736     endCommandBuffer(ctx.vkd, cmdBuffer);
5737     submitCommandsAndWait(ctx.vkd, ctx.device, queue, cmdBuffer);
5738 
5739     // Verify values.
5740     std::vector<uint32_t> outputValues(valueCount, 0u);
5741     invalidateAlloc(ctx.vkd, ctx.device, sbAlloc);
5742     deMemcpy(outputValues.data(), sbData, de::dataSize(outputValues));
5743 
5744     for (uint32_t i = 0u; i < valueCount; ++i)
5745     {
5746         const auto refValue = bufferValues[i] + i + kIndirectDispatchValueOffset;
5747         if (outputValues[i] != refValue)
5748         {
5749             std::ostringstream msg;
5750             msg << "Unexpected value found at position " << i << ": expected " << refValue << " but found "
5751                 << outputValues[i];
5752             TCU_FAIL(msg.str());
5753         }
5754     }
5755 
5756     return tcu::TestStatus::pass("Pass");
5757 }
5758 
5759 } // namespace
5760 
createCommandBuffersTests(tcu::TestContext & testCtx)5761 tcu::TestCaseGroup *createCommandBuffersTests(tcu::TestContext &testCtx)
5762 {
5763     de::MovePtr<tcu::TestCaseGroup> commandBuffersTests(new tcu::TestCaseGroup(testCtx, "command_buffers"));
5764 
5765     /* 19.1. Command Pools (5.1 in VK 1.0 Spec) */
5766     addFunctionCase(commandBuffersTests.get(), "pool_create_null_params", createPoolNullParamsTest);
5767 #ifndef CTS_USES_VULKANSC
5768     // VkAllocationCallbacks must be NULL in Vulkan SC
5769     addFunctionCase(commandBuffersTests.get(), "pool_create_non_null_allocator", createPoolNonNullAllocatorTest);
5770 #endif // CTS_USES_VULKANSC
5771     addFunctionCase(commandBuffersTests.get(), "pool_create_transient_bit", createPoolTransientBitTest);
5772     addFunctionCase(commandBuffersTests.get(), "pool_create_reset_bit", createPoolResetBitTest);
5773 #ifndef CTS_USES_VULKANSC
5774     addFunctionCase(commandBuffersTests.get(), "pool_reset_release_res", resetPoolReleaseResourcesBitTest);
5775 #endif // CTS_USES_VULKANSC
5776     addFunctionCase(commandBuffersTests.get(), "pool_reset_no_flags_res", resetPoolNoFlagsTest);
5777 #ifndef CTS_USES_VULKANSC
5778     addFunctionCase(commandBuffersTests.get(), "pool_reset_reuse", checkEventSupport, resetPoolReuseTest);
5779 #endif // CTS_USES_VULKANSC
5780     /* 19.2. Command Buffer Lifetime (5.2 in VK 1.0 Spec) */
5781     addFunctionCase(commandBuffersTests.get(), "allocate_single_primary", allocatePrimaryBufferTest);
5782     addFunctionCase(commandBuffersTests.get(), "allocate_many_primary", allocateManyPrimaryBuffersTest);
5783     addFunctionCase(commandBuffersTests.get(), "allocate_single_secondary", allocateSecondaryBufferTest);
5784     addFunctionCase(commandBuffersTests.get(), "allocate_many_secondary", allocateManySecondaryBuffersTest);
5785     addFunctionCase(commandBuffersTests.get(), "execute_small_primary", checkEventSupport, executePrimaryBufferTest);
5786     addFunctionCase(commandBuffersTests.get(), "execute_large_primary", checkEventSupport,
5787                     executeLargePrimaryBufferTest);
5788     addFunctionCase(commandBuffersTests.get(), "reset_implicit", checkEventSupport, resetBufferImplicitlyTest);
5789 #ifndef CTS_USES_VULKANSC
5790     addFunctionCase(commandBuffersTests.get(), "trim_command_pool", checkEventSupport, trimCommandPoolTest,
5791                     VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5792     addFunctionCase(commandBuffersTests.get(), "trim_command_pool_secondary", checkEventSupport, trimCommandPoolTest,
5793                     VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5794 #endif // CTS_USES_VULKANSC
5795     /* 19.3. Command Buffer Recording (5.3 in VK 1.0 Spec) */
5796     addFunctionCase(commandBuffersTests.get(), "record_single_primary", checkEventSupport,
5797                     recordSinglePrimaryBufferTest);
5798     addFunctionCase(commandBuffersTests.get(), "record_many_primary", checkEventSupport, recordLargePrimaryBufferTest);
5799     addFunctionCase(commandBuffersTests.get(), "record_single_secondary",
5800                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, recordSingleSecondaryBufferTest);
5801     addFunctionCase(commandBuffersTests.get(), "record_many_secondary",
5802                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, recordLargeSecondaryBufferTest);
5803     {
5804         uint32_t seed          = 1614182419u;
5805         const auto smallExtent = makeExtent3D(128u, 128u, 1u);
5806         const auto largeExtent = makeExtent3D(512u, 256u, 1u);
5807 
5808         commandBuffersTests->addChild(
5809             new ManyDrawsCase(testCtx, "record_many_draws_primary_1",
5810                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY, smallExtent, seed++)));
5811         commandBuffersTests->addChild(
5812             new ManyDrawsCase(testCtx, "record_many_draws_primary_2",
5813                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY, largeExtent, seed++)));
5814         commandBuffersTests->addChild(
5815             new ManyDrawsCase(testCtx, "record_many_draws_secondary_1",
5816                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY, smallExtent, seed++)));
5817         commandBuffersTests->addChild(
5818             new ManyDrawsCase(testCtx, "record_many_draws_secondary_2",
5819                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY, largeExtent, seed++)));
5820     }
5821     addFunctionCase(commandBuffersTests.get(), "submit_twice_primary", checkEventSupport, submitPrimaryBufferTwiceTest);
5822     addFunctionCase(commandBuffersTests.get(), "submit_twice_secondary",
5823                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, submitSecondaryBufferTwiceTest);
5824     addFunctionCase(commandBuffersTests.get(), "record_one_time_submit_primary", checkEventSupport,
5825                     oneTimeSubmitFlagPrimaryBufferTest);
5826     addFunctionCase(commandBuffersTests.get(), "record_one_time_submit_secondary",
5827                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, oneTimeSubmitFlagSecondaryBufferTest);
5828     addFunctionCase(commandBuffersTests.get(), "render_pass_continue", renderPassContinueTest, true);
5829     addFunctionCase(commandBuffersTests.get(), "nested_render_pass_continue",
5830                     checkNestedCommandBufferRenderPassContinueSupport, renderPassContinueNestedTest, true);
5831     addFunctionCase(commandBuffersTests.get(), "render_pass_continue_no_fb",
5832                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1, renderPassContinueTest, false);
5833     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_secondary_one_primary",
5834                                 checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport,
5835                                 genComputeIncrementSource, simultaneousUseSecondaryBufferOnePrimaryBufferTest);
5836     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_secondary_two_primary",
5837                                 checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport,
5838                                 genComputeIncrementSource, simultaneousUseSecondaryBufferTwoPrimaryBuffersTest);
5839     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_nested",
5840                                 checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport,
5841                                 genComputeIncrementSource, simultaneousUseNestedSecondaryBufferTest);
5842     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_twice_nested",
5843                                 checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport,
5844                                 genComputeIncrementSource, simultaneousUseNestedSecondaryBufferTwiceTest);
5845     addFunctionCase(commandBuffersTests.get(), "record_query_precise_w_flag",
5846                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport, recordBufferQueryPreciseWithFlagTest);
5847     addFunctionCase(commandBuffersTests.get(), "record_query_imprecise_w_flag",
5848                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport,
5849                     recordBufferQueryImpreciseWithFlagTest);
5850     addFunctionCase(commandBuffersTests.get(), "record_query_imprecise_wo_flag",
5851                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport,
5852                     recordBufferQueryImpreciseWithoutFlagTest);
5853     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_random",
5854                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5855                                 BadInheritanceInfoCase::RANDOM_PTR);
5856     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_random_cont",
5857                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5858                                 BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION);
5859     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_random_data",
5860                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5861                                 BadInheritanceInfoCase::RANDOM_DATA_PTR);
5862     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_invalid_type",
5863                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5864                                 BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE);
5865     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_valid_nonsense_type",
5866                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5867                                 BadInheritanceInfoCase::VALID_NONSENSE_TYPE);
5868     /* 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) */
5869     addFunctionCase(commandBuffersTests.get(), "submit_count_non_zero", checkEventSupport, submitBufferCountNonZero);
5870     addFunctionCase(commandBuffersTests.get(), "submit_count_equal_zero", checkEventSupport,
5871                     submitBufferCountEqualZero);
5872     addFunctionCase(commandBuffersTests.get(), "submit_wait_single_semaphore", checkEventSupport,
5873                     submitBufferWaitSingleSemaphore);
5874     addFunctionCase(commandBuffersTests.get(), "submit_wait_many_semaphores", checkEventSupport,
5875                     submitBufferWaitManySemaphores);
5876     addFunctionCase(commandBuffersTests.get(), "submit_null_fence", checkEventSupport, submitBufferNullFence);
5877     addFunctionCase(commandBuffersTests.get(), "submit_two_buffers_one_buffer_null_with_fence", checkEventSupport,
5878                     submitTwoBuffersOneBufferNullWithFence);
5879     /* 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) */
5880     addFunctionCase(commandBuffersTests.get(), "secondary_execute",
5881                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, executeSecondaryBufferTest);
5882     addFunctionCase(commandBuffersTests.get(), "secondary_execute_twice",
5883                     checkEventAndTimelineSemaphoreAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport,
5884                     executeSecondaryBufferTwiceTest);
5885     /* 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) */
5886     addFunctionCaseWithPrograms(commandBuffersTests.get(), "order_bind_pipeline", genComputeSource,
5887                                 orderBindPipelineTest);
5888     /* Verify untested transitions between command buffer states */
5889     addFunctionCase(commandBuffersTests.get(), "recording_to_ininitial", executeStateTransitionTest,
5890                     STT_RECORDING_TO_INITIAL);
5891     addFunctionCase(commandBuffersTests.get(), "executable_to_ininitial", executeStateTransitionTest,
5892                     STT_EXECUTABLE_TO_INITIAL);
5893     addFunctionCase(commandBuffersTests.get(), "recording_to_invalid", executeStateTransitionTest,
5894                     STT_RECORDING_TO_INVALID);
5895     addFunctionCase(commandBuffersTests.get(), "executable_to_invalid", executeStateTransitionTest,
5896                     STT_EXECUTABLE_TO_INVALID);
5897     addFunctionCaseWithPrograms(commandBuffersTests.get(), "many_indirect_draws_on_secondary",
5898                                 initManyIndirectDrawsPrograms, manyIndirectDrawsTest);
5899     addFunctionCaseWithPrograms(commandBuffersTests.get(), "many_indirect_disps_on_secondary",
5900                                 checkManyIndirectDispatchesSupport, initManyIndirectDispatchesPrograms,
5901                                 manyIndirectDispatchesTest);
5902 
5903     addFunctionCase(commandBuffersTests.get(), "nested_execute", checkNestedCommandBufferSupport,
5904                     executeNestedBufferTest);
5905     addFunctionCase(commandBuffersTests.get(), "nested_execute_multiple_levels", checkNestedCommandBufferDepthSupport,
5906                     executeMultipleLevelsNestedBufferTest);
5907 
5908     // Test indirect dispatches with different offsets.
5909     {
5910         auto testGroup = commandBuffersTests.get();
5911 
5912         const std::vector<uint32_t> offsetsToTest{0u, 4u, 8u, 12u, 16u, 20u, 24u, 28u};
5913 
5914         for (const auto memOffset : offsetsToTest)
5915             for (const auto dispatchOffset : offsetsToTest)
5916             {
5917                 IndirectDispatchAlignmentParams params{memOffset, dispatchOffset};
5918                 const std::string testName = "indirect_compute_dispatch_offsets_" + std::to_string(memOffset) + "_" +
5919                                              std::to_string(dispatchOffset);
5920                 testGroup->addChild(new IndirectDispatchAlignmentCase(testCtx, testName, params));
5921             }
5922     }
5923 
5924     return commandBuffersTests.release();
5925 }
5926 
5927 } // namespace api
5928 } // namespace vkt
5929