• 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         nullptr,                                        // 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             nullptr,                             // 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, nullptr);
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             nullptr,                                  // 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, nullptr);
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             nullptr,                                   // 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, nullptr);
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             nullptr,                                        // 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         nullptr,                                             // const void*                      pNext;
287         *m_renderPass,                                       // VkRenderPass                     renderPass;
288         0u,                                                  // uint32_t                         subpass;
289         (framebufferHint ? *m_frameBuffer : VK_NULL_HANDLE), // 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         nullptr,                                     // 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         nullptr,                                             // const void*                      pNext;
311         *m_renderPass,                                       // VkRenderPass                     renderPass;
312         0u,                                                  // uint32_t                         subpass;
313         (framebufferHint ? *m_frameBuffer : VK_NULL_HANDLE), // 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         nullptr,                                     // 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             nullptr,                              // 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             nullptr                               // 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         nullptr,                                    // 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         nullptr,                                    // pNext;
421         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // flags;
422         queueFamilyIndex,                           // queueFamilyIndex;
423     };
424 
425     createCommandPool(vk, vkDevice, &cmdPoolParams, nullptr);
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         nullptr,                                         // pNext;
439         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
440         queueFamilyIndex,                                // queueFamilyIndex;
441     };
442 
443     createCommandPool(vk, vkDevice, &cmdPoolParams, nullptr);
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         nullptr,                                    // pNext;
458         0u,                                         // flags;
459         queueFamilyIndex,                           // queueFamilyIndex;
460     };
461 
462     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams, nullptr));
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         nullptr,                                    // pNext;
479         0u,                                         // flags;
480         queueFamilyIndex,                           // queueFamilyIndex;
481     };
482 
483     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams, nullptr));
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         nullptr,                                    // pNext;
521         0u,                                         // flags;
522         queueFamilyIndex                            // queueFamilyIndex;
523     };
524     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams, nullptr));
525     const VkCommandBufferAllocateInfo cmdBufParams = {
526         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
527         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                  // pNext
918         0u,                                       // waitSemaphoreCount
919         nullptr,                                  // pWaitSemaphores
920         nullptr,                                  // pWaitDstStageMask
921         static_cast<uint32_t>(cmdBuffers.size()), // commandBufferCount
922         &cmdBuffers[0],                           // pCommandBuffers
923         0u,                                       // signalSemaphoreCount
924         nullptr,                                  // 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         nullptr,                                        // 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         nullptr,
959         VK_NULL_HANDLE,                    // renderPass
960         0u,                                // subpass
961         VK_NULL_HANDLE,                    // 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         nullptr,                                     // 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         nullptr,                                         // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,
1213         VK_NULL_HANDLE,                    // renderPass
1214         0u,                                // subpass
1215         VK_NULL_HANDLE,                    // 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         nullptr,
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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                        // 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         nullptr,
1278         VK_NULL_HANDLE,                    // renderPass
1279         0u,                                // subpass
1280         VK_NULL_HANDLE,                    // 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         nullptr,
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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                        // 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         nullptr,
1446         VK_NULL_HANDLE,                    // renderPass
1447         0u,                                // subpass
1448         VK_NULL_HANDLE,                    // 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         nullptr,
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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                        // 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         nullptr,
1641         VK_NULL_HANDLE,                    // renderPass
1642         0u,                                // subpass
1643         VK_NULL_HANDLE,                    // 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         nullptr,
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         nullptr,                                         // 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         nullptr,                                        // 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         nullptr,                                        // 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         nullptr,
1818         VK_NULL_HANDLE,
1819         0u, // subpass
1820         VK_NULL_HANDLE,
1821         VK_FALSE, // occlusionQueryEnable
1822         (VkQueryControlFlags)0u,
1823         (VkQueryPipelineStatisticFlags)0u,
1824     };
1825     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
1826         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1827         nullptr,
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         nullptr,                                       // pNext
1848         (VkPipelineLayoutCreateFlags)0,
1849         numDescriptorSets,          // setLayoutCount
1850         &descriptorSetLayout.get(), // pSetLayouts
1851         0u,                         // pushConstantRangeCount
1852         nullptr,                    // 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         nullptr,
1862         (VkPipelineShaderStageCreateFlags)0,
1863         VK_SHADER_STAGE_COMPUTE_BIT, // stage
1864         *computeModule,              // shader
1865         "main",
1866         nullptr, // pSpecializationInfo
1867     };
1868 
1869     const VkComputePipelineCreateInfo pipelineCreateInfo = {
1870         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1871         nullptr,
1872         0u,               // flags
1873         shaderCreateInfo, // cs
1874         *pipelineLayout,  // layout
1875         VK_NULL_HANDLE,   // basePipelineHandle
1876         0u,               // basePipelineIndex
1877     };
1878 
1879     const VkBufferMemoryBarrier bufferBarrier = {
1880         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
1881         nullptr,                                 // 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, VK_NULL_HANDLE, &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, nullptr, 1, &bufferBarrier, 0, nullptr);
1902     }
1903     // end recording of secondary buffer
1904     endCommandBuffer(vk, *secCmdBuf);
1905 
1906     // record primary command buffer
1907     beginCommandBuffer(vk, *primCmdBuf, 0u);
1908     {
1909         // execute secondary buffer twice in same primary
1910         vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
1911         vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
1912     }
1913     endCommandBuffer(vk, *primCmdBuf);
1914 
1915     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
1916 
1917     uint32_t resultCount;
1918     result.readResultContentsTo(&resultCount);
1919     // check if secondary buffer has been executed
1920     if (resultCount == 2)
1921         return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
1922     else
1923         return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
1924 }
1925 
renderPassContinueNestedTest(Context & context,bool framebufferHint)1926 tcu::TestStatus renderPassContinueNestedTest(Context &context, bool framebufferHint)
1927 {
1928     bool maintenance7 = false;
1929 #ifndef CTS_USES_VULKANSC
1930     if (context.isDeviceFunctionalitySupported("VK_KHR_maintenance7"))
1931     {
1932         const auto &features = context.getMaintenance7Features();
1933         maintenance7         = features.maintenance7;
1934     }
1935 #endif
1936 
1937     if (!maintenance7)
1938     {
1939         context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
1940 #ifndef CTS_USES_VULKANSC
1941         const auto &features = context.getNestedCommandBufferFeaturesEXT();
1942         if (!features.nestedCommandBuffer)
1943 #endif // CTS_USES_VULKANSC
1944             TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
1945 #ifndef CTS_USES_VULKANSC
1946         if (!features.nestedCommandBufferRendering)
1947 #endif // CTS_USES_VULKANSC
1948             TCU_THROW(NotSupportedError, "nestedCommandBufferRendering is not supported");
1949     }
1950 
1951     const DeviceInterface &vkd = context.getDeviceInterface();
1952     CommandBufferRenderPassTestEnvironment env(context, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
1953 
1954     VkCommandBuffer primaryCommandBuffer   = env.getPrimaryCommandBuffer();
1955     VkCommandBuffer secondaryCommandBuffer = env.getSecondaryCommandBuffer();
1956     VkCommandBuffer nestedCommandBuffer    = env.getNestedCommandBuffer();
1957     const uint32_t clearColor[4]           = {2, 47, 131, 211};
1958 
1959     const VkClearAttachment clearAttachment = {
1960         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1961         0,                         // uint32_t colorAttachment;
1962         makeClearValueColorU32(clearColor[0], clearColor[1], clearColor[2],
1963                                clearColor[3]) // VkClearValue clearValue;
1964     };
1965 
1966     const uint32_t clearRectWidth  = CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.width / 2;
1967     const uint32_t clearRectHeight = CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.height / 2;
1968     const int32_t clearRectOffsetX = clearRectWidth;
1969     const int32_t clearRectOffsetY = clearRectHeight;
1970 
1971     const VkRect2D clearRectArea[4] = {{
1972                                            {0u, 0u},                          // VkOffset2D offset;
1973                                            {clearRectWidth, clearRectHeight}, // VkExtent2D extent;
1974                                        },
1975                                        {
1976                                            {0u, clearRectOffsetY},                // VkOffset2D offset;
1977                                            {clearRectWidth, clearRectHeight + 1}, // VkExtent2D extent;
1978                                        },
1979                                        {
1980                                            {clearRectOffsetX, 0u},                // VkOffset2D offset;
1981                                            {clearRectWidth + 1, clearRectHeight}, // VkExtent2D extent;
1982                                        },
1983                                        {
1984                                            {clearRectOffsetX, clearRectOffsetY},      // VkOffset2D offset;
1985                                            {clearRectWidth + 1, clearRectHeight + 1}, // VkExtent2D extent;
1986                                        }};
1987 
1988     const VkClearRect clearRect[4] = {{
1989                                           clearRectArea[0], // VkRect2D rect;
1990                                           0u,               // uint32_t baseArrayLayer;
1991                                           1u                // uint32_t layerCount;
1992                                       },
1993                                       {
1994                                           clearRectArea[1], // VkRect2D rect;
1995                                           0u,               // uint32_t baseArrayLayer;
1996                                           1u                // uint32_t layerCount;
1997                                       },
1998                                       {
1999                                           clearRectArea[2], // VkRect2D rect;
2000                                           0u,               // uint32_t baseArrayLayer;
2001                                           1u                // uint32_t layerCount;
2002                                       },
2003                                       {
2004                                           clearRectArea[3], // VkRect2D rect;
2005                                           0u,               // uint32_t baseArrayLayer;
2006                                           1u                // uint32_t layerCount;
2007                                       }};
2008 
2009     env.beginSecondaryCommandBuffer(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, framebufferHint);
2010     vkd.cmdClearAttachments(secondaryCommandBuffer, 1, &clearAttachment, 1, &clearRect[0]);
2011     endCommandBuffer(vkd, secondaryCommandBuffer);
2012 
2013     env.beginNestedCommandBuffer(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, framebufferHint);
2014     vkd.cmdExecuteCommands(nestedCommandBuffer, 1, &secondaryCommandBuffer);
2015     vkd.cmdClearAttachments(nestedCommandBuffer, 1, &clearAttachment, 1, &clearRect[1]);
2016     endCommandBuffer(vkd, nestedCommandBuffer);
2017 
2018     env.beginPrimaryCommandBuffer(0);
2019 #ifndef CTS_USES_VULKANSC
2020     env.beginRenderPass(VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT);
2021 #endif // CTS_USES_VULKANSC
2022     vkd.cmdClearAttachments(primaryCommandBuffer, 1, &clearAttachment, 1, &clearRect[2]);
2023     vkd.cmdExecuteCommands(primaryCommandBuffer, 1, &nestedCommandBuffer);
2024     vkd.cmdClearAttachments(primaryCommandBuffer, 1, &clearAttachment, 1, &clearRect[3]);
2025     endRenderPass(vkd, primaryCommandBuffer);
2026 
2027     endCommandBuffer(vkd, primaryCommandBuffer);
2028 
2029     env.submitPrimaryCommandBuffer();
2030     context.resetCommandPoolForVKSC(context.getDevice(), env.getCommandPool());
2031 
2032     de::MovePtr<tcu::TextureLevel> result    = env.readColorAttachment();
2033     tcu::PixelBufferAccess pixelBufferAccess = result->getAccess();
2034 
2035     for (uint32_t i = 0; i < (CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.width *
2036                               CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.height);
2037          ++i)
2038     {
2039         uint8_t *colorData = reinterpret_cast<uint8_t *>(pixelBufferAccess.getDataPtr());
2040         for (int colorComponent = 0; colorComponent < 4; ++colorComponent)
2041             if (colorData[i * 4 + colorComponent] != clearColor[colorComponent])
2042                 return tcu::TestStatus::fail("clear value mismatch");
2043     }
2044 
2045     return tcu::TestStatus::pass("render pass continue in nested command buffer test passed");
2046 }
2047 
simultaneousUseNestedSecondaryBufferTest(Context & context)2048 tcu::TestStatus simultaneousUseNestedSecondaryBufferTest(Context &context)
2049 {
2050     const VkDevice vkDevice         = context.getDevice();
2051     const DeviceInterface &vk       = context.getDeviceInterface();
2052     const VkQueue queue             = context.getUniversalQueue();
2053     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2054     Allocator &allocator            = context.getDefaultAllocator();
2055     const ComputeInstanceResultBuffer result(vk, vkDevice, allocator, 0.0f);
2056 
2057     const VkCommandPoolCreateInfo cmdPoolParams = {
2058         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
2059         nullptr,                                         // const void* pNext;
2060         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
2061         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
2062     };
2063     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2064 
2065     // Command buffer
2066     const VkCommandBufferAllocateInfo cmdBufParams = {
2067         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2068         nullptr,                                        // const void* pNext;
2069         *cmdPool,                                       // VkCommandPool pool;
2070         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
2071         1u,                                             // uint32_t bufferCount;
2072     };
2073     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2074 
2075     // Secondary Command buffer params
2076     const VkCommandBufferAllocateInfo secCmdBufParams = {
2077         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2078         nullptr,                                        // const void* pNext;
2079         *cmdPool,                                       // VkCommandPool pool;
2080         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
2081         1u,                                             // uint32_t bufferCount;
2082     };
2083     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2084     const Unique<VkCommandBuffer> nestedCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2085 
2086     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
2087         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2088         nullptr,
2089         VK_NULL_HANDLE,
2090         0u, // subpass
2091         VK_NULL_HANDLE,
2092         VK_FALSE, // occlusionQueryEnable
2093         (VkQueryControlFlags)0u,
2094         (VkQueryPipelineStatisticFlags)0u,
2095     };
2096     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
2097         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2098         nullptr,
2099         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
2100         &secCmdBufInheritInfo,
2101     };
2102 
2103     const uint32_t offset          = (0u);
2104     const uint32_t addressableSize = 256;
2105     const uint32_t dataSize        = 8;
2106     de::MovePtr<Allocation> bufferMem;
2107     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2108     // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
2109     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2110     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2111     const Unique<VkDescriptorSet> descriptorSet(
2112         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2113     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2114     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2115 
2116     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
2117         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
2118         nullptr,                                       // pNext
2119         (VkPipelineLayoutCreateFlags)0,
2120         numDescriptorSets,          // setLayoutCount
2121         &descriptorSetLayout.get(), // pSetLayouts
2122         0u,                         // pushConstantRangeCount
2123         nullptr,                    // pPushConstantRanges
2124     };
2125     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
2126 
2127     const Unique<VkShaderModule> computeModule(createShaderModule(
2128         vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2129 
2130     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2131         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2132         nullptr,
2133         (VkPipelineShaderStageCreateFlags)0,
2134         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2135         *computeModule,              // shader
2136         "main",
2137         nullptr, // pSpecializationInfo
2138     };
2139 
2140     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2141         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2142         nullptr,
2143         0u,               // flags
2144         shaderCreateInfo, // cs
2145         *pipelineLayout,  // layout
2146         VK_NULL_HANDLE,   // basePipelineHandle
2147         0u,               // basePipelineIndex
2148     };
2149 
2150     const VkBufferMemoryBarrier bufferBarrier = {
2151         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
2152         nullptr,                                 // pNext
2153         VK_ACCESS_SHADER_WRITE_BIT,              // srcAccessMask
2154         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
2155         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
2156         VK_QUEUE_FAMILY_IGNORED,                 // destQueueFamilyIndex
2157         *buffer,                                 // buffer
2158         (VkDeviceSize)0u,                        // offset
2159         (VkDeviceSize)VK_WHOLE_SIZE,             // size
2160     };
2161 
2162     const Unique<VkPipeline> pipeline(createComputePipeline(vk, vkDevice, VK_NULL_HANDLE, &pipelineCreateInfo));
2163 
2164     // record secondary command buffer
2165     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
2166     {
2167         vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2168         vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2169                                  descriptorSets, 0, 0);
2170         vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
2171         vk.cmdPipelineBarrier(*secCmdBuf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2172                               (VkDependencyFlags)0, 0, nullptr, 1, &bufferBarrier, 0, nullptr);
2173     }
2174     // end recording of secondary buffer
2175     endCommandBuffer(vk, *secCmdBuf);
2176 
2177     // record another secondary command buffer to nest the other into
2178     VK_CHECK(vk.beginCommandBuffer(*nestedCmdBuf, &secCmdBufBeginInfo));
2179     {
2180         // execute nested secondary buffer twice in same secondary buffer
2181         vk.cmdExecuteCommands(*nestedCmdBuf, 1, &secCmdBuf.get());
2182         vk.cmdExecuteCommands(*nestedCmdBuf, 1, &secCmdBuf.get());
2183     }
2184     endCommandBuffer(vk, *nestedCmdBuf);
2185 
2186     // record primary command buffer
2187     beginCommandBuffer(vk, *primCmdBuf, 0u);
2188     {
2189         // execute nested buffer
2190         vk.cmdExecuteCommands(*primCmdBuf, 1, &nestedCmdBuf.get());
2191     }
2192     endCommandBuffer(vk, *primCmdBuf);
2193 
2194     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
2195 
2196     uint32_t resultCount;
2197     result.readResultContentsTo(&resultCount);
2198     // check if secondary buffer has been executed
2199     if (resultCount == 2)
2200         return tcu::TestStatus::pass("Simultaneous Nested Command Buffer Execution succeeded");
2201     else
2202         return tcu::TestStatus::fail("Simultaneous Nested Command Buffer Execution FAILED");
2203 }
2204 
simultaneousUseNestedSecondaryBufferTwiceTest(Context & context)2205 tcu::TestStatus simultaneousUseNestedSecondaryBufferTwiceTest(Context &context)
2206 {
2207     const VkDevice vkDevice         = context.getDevice();
2208     const DeviceInterface &vk       = context.getDeviceInterface();
2209     const VkQueue queue             = context.getUniversalQueue();
2210     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2211     Allocator &allocator            = context.getDefaultAllocator();
2212     const ComputeInstanceResultBuffer result(vk, vkDevice, allocator, 0.0f);
2213 
2214     const VkCommandPoolCreateInfo cmdPoolParams = {
2215         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
2216         nullptr,                                         // const void* pNext;
2217         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
2218         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
2219     };
2220     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2221 
2222     // Command buffer
2223     const VkCommandBufferAllocateInfo cmdBufParams = {
2224         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2225         nullptr,                                        // const void* pNext;
2226         *cmdPool,                                       // VkCommandPool pool;
2227         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
2228         1u,                                             // uint32_t bufferCount;
2229     };
2230     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2231 
2232     // Secondary Command buffer params
2233     const VkCommandBufferAllocateInfo secCmdBufParams = {
2234         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2235         nullptr,                                        // const void* pNext;
2236         *cmdPool,                                       // VkCommandPool pool;
2237         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
2238         1u,                                             // uint32_t bufferCount;
2239     };
2240     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2241     const Unique<VkCommandBuffer> nestedCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2242 
2243     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
2244         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2245         nullptr,
2246         VK_NULL_HANDLE,
2247         0u, // subpass
2248         VK_NULL_HANDLE,
2249         VK_FALSE, // occlusionQueryEnable
2250         (VkQueryControlFlags)0u,
2251         (VkQueryPipelineStatisticFlags)0u,
2252     };
2253     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
2254         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2255         nullptr,
2256         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
2257         &secCmdBufInheritInfo,
2258     };
2259 
2260     const uint32_t offset          = (0u);
2261     const uint32_t addressableSize = 256;
2262     const uint32_t dataSize        = 8;
2263     de::MovePtr<Allocation> bufferMem;
2264     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2265     // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
2266     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2267     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2268     const Unique<VkDescriptorSet> descriptorSet(
2269         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2270     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2271     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2272 
2273     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
2274         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
2275         nullptr,                                       // pNext
2276         (VkPipelineLayoutCreateFlags)0,
2277         numDescriptorSets,          // setLayoutCount
2278         &descriptorSetLayout.get(), // pSetLayouts
2279         0u,                         // pushConstantRangeCount
2280         nullptr,                    // pPushConstantRanges
2281     };
2282     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
2283 
2284     const Unique<VkShaderModule> computeModule(createShaderModule(
2285         vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2286 
2287     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2288         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2289         nullptr,
2290         (VkPipelineShaderStageCreateFlags)0,
2291         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2292         *computeModule,              // shader
2293         "main",
2294         nullptr, // pSpecializationInfo
2295     };
2296 
2297     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2298         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2299         nullptr,
2300         0u,               // flags
2301         shaderCreateInfo, // cs
2302         *pipelineLayout,  // layout
2303         VK_NULL_HANDLE,   // basePipelineHandle
2304         0u,               // basePipelineIndex
2305     };
2306 
2307     const VkBufferMemoryBarrier bufferBarrier = {
2308         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
2309         nullptr,                                 // pNext
2310         VK_ACCESS_SHADER_WRITE_BIT,              // srcAccessMask
2311         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
2312         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
2313         VK_QUEUE_FAMILY_IGNORED,                 // destQueueFamilyIndex
2314         *buffer,                                 // buffer
2315         (VkDeviceSize)0u,                        // offset
2316         (VkDeviceSize)VK_WHOLE_SIZE,             // size
2317     };
2318 
2319     const Unique<VkPipeline> pipeline(createComputePipeline(vk, vkDevice, VK_NULL_HANDLE, &pipelineCreateInfo));
2320 
2321     // record secondary command buffer
2322     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
2323     {
2324         vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2325         vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2326                                  descriptorSets, 0, 0);
2327         vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
2328         vk.cmdPipelineBarrier(*secCmdBuf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2329                               (VkDependencyFlags)0, 0, nullptr, 1, &bufferBarrier, 0, nullptr);
2330     }
2331     // end recording of secondary buffer
2332     endCommandBuffer(vk, *secCmdBuf);
2333 
2334     // record another secondary command buffer to nest the other into
2335     VK_CHECK(vk.beginCommandBuffer(*nestedCmdBuf, &secCmdBufBeginInfo));
2336     {
2337         // execute nested secondary buffer
2338         vk.cmdExecuteCommands(*nestedCmdBuf, 1, &secCmdBuf.get());
2339     }
2340     endCommandBuffer(vk, *nestedCmdBuf);
2341 
2342     // record primary command buffer
2343     beginCommandBuffer(vk, *primCmdBuf, 0u);
2344     {
2345         // execute nested secondary buffers twice in same primary buffer
2346         vk.cmdExecuteCommands(*primCmdBuf, 1, &nestedCmdBuf.get());
2347         vk.cmdExecuteCommands(*primCmdBuf, 1, &nestedCmdBuf.get());
2348     }
2349     endCommandBuffer(vk, *primCmdBuf);
2350 
2351     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
2352 
2353     uint32_t resultCount;
2354     result.readResultContentsTo(&resultCount);
2355     // check if secondary buffer has been executed
2356     if (resultCount == 2)
2357         return tcu::TestStatus::pass("Simultaneous Nested Command Buffer Execution succeeded");
2358     else
2359         return tcu::TestStatus::fail("Simultaneous Nested Command Buffer Execution FAILED");
2360 }
2361 
2362 enum class BadInheritanceInfoCase
2363 {
2364     RANDOM_PTR = 0,
2365     RANDOM_PTR_CONTINUATION,
2366     RANDOM_DATA_PTR,
2367     INVALID_STRUCTURE_TYPE,
2368     VALID_NONSENSE_TYPE,
2369 };
2370 
badInheritanceInfoTest(Context & context,BadInheritanceInfoCase testCase)2371 tcu::TestStatus badInheritanceInfoTest(Context &context, BadInheritanceInfoCase testCase)
2372 {
2373     const auto &vkd             = context.getDeviceInterface();
2374     const auto device           = context.getDevice();
2375     const auto queue            = context.getUniversalQueue();
2376     const auto queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2377     auto &allocator             = context.getDefaultAllocator();
2378     const ComputeInstanceResultBuffer result(vkd, device, allocator, 0.0f);
2379 
2380     // Command pool and command buffer.
2381     const auto cmdPool      = makeCommandPool(vkd, device, queueFamilyIndex);
2382     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2383     const auto cmdBuffer    = cmdBufferPtr.get();
2384 
2385     // Buffers, descriptor set layouts and descriptor sets.
2386     const uint32_t offset          = 0u;
2387     const uint32_t addressableSize = 256u;
2388     const uint32_t dataSize        = 8u;
2389 
2390     // The uniform buffer will not be used by the shader but is needed by auxiliar functions here.
2391     de::MovePtr<Allocation> bufferMem;
2392     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2393 
2394     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2395     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2396     const Unique<VkDescriptorSet> descriptorSet(
2397         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2398     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2399     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2400 
2401     // Pipeline layout.
2402     const auto pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
2403 
2404     // Compute shader module.
2405     const Unique<VkShaderModule> computeModule(createShaderModule(
2406         vkd, device, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2407 
2408     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2409         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2410         nullptr,
2411         (VkPipelineShaderStageCreateFlags)0,
2412         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2413         *computeModule,              // shader
2414         "main",
2415         nullptr, // pSpecializationInfo
2416     };
2417 
2418     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2419         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2420         nullptr,
2421         0u,               // flags
2422         shaderCreateInfo, // cs
2423         *pipelineLayout,  // layout
2424         VK_NULL_HANDLE,   // basePipelineHandle
2425         0u,               // basePipelineIndex
2426     };
2427 
2428     const Unique<VkPipeline> pipeline(createComputePipeline(vkd, device, VK_NULL_HANDLE, &pipelineCreateInfo));
2429 
2430     // Compute to host barrier to read result.
2431     const VkBufferMemoryBarrier bufferBarrier = {
2432         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
2433         nullptr,                                 // pNext
2434         VK_ACCESS_SHADER_WRITE_BIT,              // srcAccessMask
2435         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
2436         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
2437         VK_QUEUE_FAMILY_IGNORED,                 // destQueueFamilyIndex
2438         *buffer,                                 // buffer
2439         (VkDeviceSize)0u,                        // offset
2440         (VkDeviceSize)VK_WHOLE_SIZE,             // size
2441     };
2442 
2443     // Record command buffer and submit it.
2444     VkCommandBufferBeginInfo beginInfo = {
2445         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
2446         nullptr,                                     // const void* pNext;
2447         0u,                                          // VkCommandBufferUsageFlags flags;
2448         nullptr,                                     // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
2449     };
2450 
2451     // Structures used in different test types.
2452     VkCommandBufferInheritanceInfo inheritanceInfo;
2453     VkBufferCreateInfo validNonsenseStructure;
2454     struct
2455     {
2456         VkStructureType sType;
2457         void *pNext;
2458     } invalidStructure;
2459 
2460     if (testCase == BadInheritanceInfoCase::RANDOM_PTR || testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
2461     {
2462         de::Random rnd(1602600778u);
2463         VkCommandBufferInheritanceInfo *info;
2464         auto ptrData = reinterpret_cast<uint8_t *>(&info);
2465 
2466         // Fill pointer value with pseudorandom garbage.
2467         for (size_t i = 0; i < sizeof(info); ++i)
2468             *ptrData++ = rnd.getUint8();
2469 
2470         beginInfo.pInheritanceInfo = info;
2471 
2472         // Try to trick the implementation into reading pInheritanceInfo one more way.
2473         if (testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
2474             beginInfo.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
2475     }
2476     else if (testCase == BadInheritanceInfoCase::RANDOM_DATA_PTR)
2477     {
2478         de::Random rnd(1602601141u);
2479         auto itr = reinterpret_cast<uint8_t *>(&inheritanceInfo);
2480 
2481         // Fill inheritance info data structure with random data.
2482         for (size_t i = 0; i < sizeof(inheritanceInfo); ++i)
2483             *itr++ = rnd.getUint8();
2484 
2485         beginInfo.pInheritanceInfo = &inheritanceInfo;
2486     }
2487     else if (testCase == BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE)
2488     {
2489         de::Random rnd(1602658515u);
2490         auto ptrData           = reinterpret_cast<uint8_t *>(&(invalidStructure.pNext));
2491         invalidStructure.sType = VK_STRUCTURE_TYPE_MAX_ENUM;
2492 
2493         // Fill pNext pointer with random data.
2494         for (size_t i = 0; i < sizeof(invalidStructure.pNext); ++i)
2495             *ptrData++ = rnd.getUint8();
2496 
2497         beginInfo.pInheritanceInfo = reinterpret_cast<VkCommandBufferInheritanceInfo *>(&invalidStructure);
2498     }
2499     else if (testCase == BadInheritanceInfoCase::VALID_NONSENSE_TYPE)
2500     {
2501         validNonsenseStructure.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
2502         validNonsenseStructure.pNext                 = nullptr;
2503         validNonsenseStructure.flags                 = 0u;
2504         validNonsenseStructure.size                  = 1024u;
2505         validNonsenseStructure.usage                 = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2506         validNonsenseStructure.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
2507         validNonsenseStructure.queueFamilyIndexCount = 0u;
2508         validNonsenseStructure.pQueueFamilyIndices   = nullptr;
2509 
2510         beginInfo.pInheritanceInfo = reinterpret_cast<VkCommandBufferInheritanceInfo *>(&validNonsenseStructure);
2511     }
2512     else
2513     {
2514         DE_ASSERT(false);
2515     }
2516 
2517     VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &beginInfo));
2518     {
2519         vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2520         vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2521                                   descriptorSets, 0, 0);
2522         vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
2523         vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2524                                (VkDependencyFlags)0, 0, nullptr, 1, &bufferBarrier, 0, nullptr);
2525     }
2526     endCommandBuffer(vkd, cmdBuffer);
2527     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2528 
2529     uint32_t resultCount;
2530     result.readResultContentsTo(&resultCount);
2531 
2532     // Make sure the command buffer was run.
2533     if (resultCount != 1u)
2534     {
2535         std::ostringstream msg;
2536         msg << "Invalid value found in results buffer (expected value 1u but found " << resultCount << ")";
2537         return tcu::TestStatus::fail(msg.str());
2538     }
2539 
2540     return tcu::TestStatus::pass("Pass");
2541 }
2542 
simultaneousUseSecondaryBufferTwoPrimaryBuffersTest(Context & context)2543 tcu::TestStatus simultaneousUseSecondaryBufferTwoPrimaryBuffersTest(Context &context)
2544 {
2545     const VkDevice vkDevice         = context.getDevice();
2546     const DeviceInterface &vk       = context.getDeviceInterface();
2547     const VkQueue queue             = context.getUniversalQueue();
2548     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2549     Allocator &allocator            = context.getDefaultAllocator();
2550     const ComputeInstanceResultBuffer result(vk, vkDevice, allocator, 0.0f);
2551 
2552     const VkCommandPoolCreateInfo cmdPoolParams = {
2553         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
2554         nullptr,                                         // const void* pNext;
2555         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
2556         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
2557     };
2558     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2559 
2560     // Command buffer
2561     const VkCommandBufferAllocateInfo cmdBufParams = {
2562         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2563         nullptr,                                        // const void* pNext;
2564         *cmdPool,                                       // VkCommandPool pool;
2565         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
2566         1u,                                             // uint32_t bufferCount;
2567     };
2568     // Two separate primary cmd buffers that will be executed with the same secondary cmd buffer
2569     const uint32_t numPrimCmdBufs = 2;
2570     const Unique<VkCommandBuffer> primCmdBufOne(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2571     const Unique<VkCommandBuffer> primCmdBufTwo(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
2572     VkCommandBuffer primCmdBufs[numPrimCmdBufs];
2573     primCmdBufs[0] = primCmdBufOne.get();
2574     primCmdBufs[1] = primCmdBufTwo.get();
2575 
2576     // Secondary Command buffer params
2577     const VkCommandBufferAllocateInfo secCmdBufParams = {
2578         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2579         nullptr,                                        // const void* pNext;
2580         *cmdPool,                                       // VkCommandPool pool;
2581         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
2582         1u,                                             // uint32_t bufferCount;
2583     };
2584     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2585 
2586     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
2587         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2588         nullptr,
2589         0, // flags
2590         nullptr,
2591     };
2592 
2593     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
2594         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2595         nullptr,
2596         VK_NULL_HANDLE,                    // renderPass
2597         0u,                                // subpass
2598         VK_NULL_HANDLE,                    // framebuffer
2599         VK_FALSE,                          // occlusionQueryEnable
2600         (VkQueryControlFlags)0u,           // queryFlags
2601         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2602     };
2603     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
2604         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2605         nullptr,
2606         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
2607         &secCmdBufInheritInfo,
2608     };
2609 
2610     const uint32_t offset          = (0u);
2611     const uint32_t addressableSize = 256;
2612     const uint32_t dataSize        = 8;
2613     de::MovePtr<Allocation> bufferMem;
2614     const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
2615     // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
2616     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
2617     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
2618     const Unique<VkDescriptorSet> descriptorSet(
2619         createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
2620     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
2621     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
2622 
2623     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
2624         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
2625         nullptr,                                       // pNext
2626         (VkPipelineLayoutCreateFlags)0,
2627         numDescriptorSets,          // setLayoutCount
2628         &descriptorSetLayout.get(), // pSetLayouts
2629         0u,                         // pushConstantRangeCount
2630         nullptr,                    // pPushConstantRanges
2631     };
2632     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
2633 
2634     const Unique<VkShaderModule> computeModule(createShaderModule(
2635         vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
2636 
2637     const VkPipelineShaderStageCreateInfo shaderCreateInfo = {
2638         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2639         nullptr,
2640         (VkPipelineShaderStageCreateFlags)0,
2641         VK_SHADER_STAGE_COMPUTE_BIT, // stage
2642         *computeModule,              // shader
2643         "main",
2644         nullptr, // pSpecializationInfo
2645     };
2646 
2647     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2648         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2649         nullptr,
2650         0u,               // flags
2651         shaderCreateInfo, // cs
2652         *pipelineLayout,  // layout
2653         VK_NULL_HANDLE,   // basePipelineHandle
2654         0u,               // basePipelineIndex
2655     };
2656 
2657     const Unique<VkPipeline> pipeline(createComputePipeline(vk, vkDevice, VK_NULL_HANDLE, &pipelineCreateInfo));
2658 
2659     // record secondary command buffer
2660     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
2661     {
2662         vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
2663         vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
2664                                  descriptorSets, 0, 0);
2665         vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
2666     }
2667     // end recording of secondary buffer
2668     endCommandBuffer(vk, *secCmdBuf);
2669 
2670     // record primary command buffers
2671     // Insert one instance of same secondary command buffer into two separate primary command buffers
2672     VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
2673     {
2674         vk.cmdExecuteCommands(*primCmdBufOne, 1, &secCmdBuf.get());
2675     }
2676     endCommandBuffer(vk, *primCmdBufOne);
2677 
2678     VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
2679     {
2680         vk.cmdExecuteCommands(*primCmdBufTwo, 1, &secCmdBuf.get());
2681     }
2682     endCommandBuffer(vk, *primCmdBufTwo);
2683 
2684     // create fence to wait for execution of queue
2685     const Unique<VkFence> fence(createFence(vk, vkDevice));
2686 
2687     const VkSubmitInfo submitInfo = {
2688         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
2689         nullptr,                       // pNext
2690         0u,                            // waitSemaphoreCount
2691         nullptr,                       // pWaitSemaphores
2692         nullptr,                       // pWaitDstStageMask
2693         numPrimCmdBufs,                // commandBufferCount
2694         primCmdBufs,                   // pCommandBuffers
2695         0u,                            // signalSemaphoreCount
2696         nullptr,                       // pSignalSemaphores
2697     };
2698 
2699     // submit primary buffers, the secondary should be executed too
2700     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
2701 
2702     // wait for end of execution of queue
2703     VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
2704 
2705     uint32_t resultCount;
2706     result.readResultContentsTo(&resultCount);
2707     // check if secondary buffer has been executed
2708     if (resultCount == 2)
2709         return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
2710     else
2711         return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
2712 }
2713 
recordBufferQueryPreciseWithFlagTest(Context & context)2714 tcu::TestStatus recordBufferQueryPreciseWithFlagTest(Context &context)
2715 {
2716     const VkDevice vkDevice         = context.getDevice();
2717     const DeviceInterface &vk       = context.getDeviceInterface();
2718     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2719 
2720     if (!context.getDeviceFeatures().inheritedQueries)
2721         TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
2722 
2723     const VkCommandPoolCreateInfo cmdPoolParams = {
2724         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
2725         nullptr,                                         // pNext;
2726         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
2727         queueFamilyIndex,                                // queueFamilyIndex;
2728     };
2729     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2730 
2731     // Command buffer
2732     const VkCommandBufferAllocateInfo primCmdBufParams = {
2733         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2734         nullptr,                                        // pNext;
2735         *cmdPool,                                       // pool;
2736         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
2737         1u,                                             // flags;
2738     };
2739     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
2740 
2741     // Secondary Command buffer params
2742     const VkCommandBufferAllocateInfo secCmdBufParams = {
2743         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2744         nullptr,                                        // pNext;
2745         *cmdPool,                                       // pool;
2746         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
2747         1u,                                             // flags;
2748     };
2749     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2750 
2751     const VkCommandBufferBeginInfo primBufferBeginInfo = {
2752         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2753         nullptr,                                     // pNext
2754         0u,                                          // flags
2755         nullptr,
2756     };
2757 
2758     const VkCommandBufferInheritanceInfo secBufferInheritInfo = {
2759         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2760         nullptr,
2761         VK_NULL_HANDLE,                    // renderPass
2762         0u,                                // subpass
2763         VK_NULL_HANDLE,                    // framebuffer
2764         VK_TRUE,                           // occlusionQueryEnable
2765         VK_QUERY_CONTROL_PRECISE_BIT,      // queryFlags
2766         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2767     };
2768     const VkCommandBufferBeginInfo secBufferBeginInfo = {
2769         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2770         nullptr,                                     // pNext
2771         0u,                                          // flags
2772         &secBufferInheritInfo,
2773     };
2774 
2775     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
2776         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
2777         nullptr,                                  // pNext
2778         (VkQueryPoolCreateFlags)0,                // flags
2779         VK_QUERY_TYPE_OCCLUSION,                  // queryType
2780         1u,                                       // entryCount
2781         0u,                                       // pipelineStatistics
2782     };
2783     Unique<VkQueryPool> queryPool(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
2784 
2785     VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
2786     endCommandBuffer(vk, secCmdBuf.get());
2787 
2788     VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
2789     {
2790         vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
2791         vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, VK_QUERY_CONTROL_PRECISE_BIT);
2792         {
2793             vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
2794         }
2795         vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
2796     }
2797     endCommandBuffer(vk, primCmdBuf.get());
2798 
2799     return tcu::TestStatus::pass(
2800         "Successfully recorded a secondary command buffer allowing a precise occlusion query.");
2801 }
2802 
recordBufferQueryImpreciseWithFlagTest(Context & context)2803 tcu::TestStatus recordBufferQueryImpreciseWithFlagTest(Context &context)
2804 {
2805     const VkDevice vkDevice         = context.getDevice();
2806     const DeviceInterface &vk       = context.getDeviceInterface();
2807     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2808 
2809     if (!context.getDeviceFeatures().inheritedQueries)
2810         TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
2811 
2812     const VkCommandPoolCreateInfo cmdPoolParams = {
2813         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
2814         nullptr,                                         // pNext;
2815         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
2816         queueFamilyIndex,                                // queueFamilyIndex;
2817     };
2818     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2819 
2820     // Command buffer
2821     const VkCommandBufferAllocateInfo primCmdBufParams = {
2822         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2823         nullptr,                                        // pNext;
2824         *cmdPool,                                       // pool;
2825         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
2826         1u,                                             // flags;
2827     };
2828     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
2829 
2830     // Secondary Command buffer params
2831     const VkCommandBufferAllocateInfo secCmdBufParams = {
2832         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2833         nullptr,                                        // pNext;
2834         *cmdPool,                                       // pool;
2835         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
2836         1u,                                             // flags;
2837     };
2838     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2839 
2840     const VkCommandBufferBeginInfo primBufferBeginInfo = {
2841         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2842         nullptr,                                     // pNext
2843         0u,                                          // flags
2844         nullptr,
2845     };
2846 
2847     const VkCommandBufferInheritanceInfo secBufferInheritInfo = {
2848         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2849         nullptr,
2850         VK_NULL_HANDLE,                    // renderPass
2851         0u,                                // subpass
2852         VK_NULL_HANDLE,                    // framebuffer
2853         VK_TRUE,                           // occlusionQueryEnable
2854         VK_QUERY_CONTROL_PRECISE_BIT,      // queryFlags
2855         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2856     };
2857     const VkCommandBufferBeginInfo secBufferBeginInfo = {
2858         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2859         nullptr,                                     // pNext
2860         0u,                                          // flags
2861         &secBufferInheritInfo,
2862     };
2863 
2864     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
2865         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
2866         nullptr,                                  // pNext
2867         0u,                                       // flags
2868         VK_QUERY_TYPE_OCCLUSION,                  // queryType
2869         1u,                                       // entryCount
2870         0u,                                       // pipelineStatistics
2871     };
2872     Unique<VkQueryPool> queryPool(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
2873 
2874     VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
2875     endCommandBuffer(vk, secCmdBuf.get());
2876 
2877     VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
2878     {
2879         vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
2880         vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, 0u);
2881         {
2882             vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
2883         }
2884         vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
2885     }
2886     endCommandBuffer(vk, primCmdBuf.get());
2887 
2888     return tcu::TestStatus::pass(
2889         "Successfully recorded an imprecise query with a secondary command buffer allowing a precise occlusion query.");
2890 }
2891 
recordBufferQueryImpreciseWithoutFlagTest(Context & context)2892 tcu::TestStatus recordBufferQueryImpreciseWithoutFlagTest(Context &context)
2893 {
2894     const VkDevice vkDevice         = context.getDevice();
2895     const DeviceInterface &vk       = context.getDeviceInterface();
2896     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2897 
2898     if (!context.getDeviceFeatures().inheritedQueries)
2899         TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
2900 
2901     const VkCommandPoolCreateInfo cmdPoolParams = {
2902         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
2903         nullptr,                                         // pNext;
2904         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
2905         queueFamilyIndex,                                // queueFamilyIndex;
2906     };
2907     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2908 
2909     // Command buffer
2910     const VkCommandBufferAllocateInfo primCmdBufParams = {
2911         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2912         nullptr,                                        // pNext;
2913         *cmdPool,                                       // pool;
2914         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
2915         1u,                                             // flags;
2916     };
2917     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
2918 
2919     // Secondary Command buffer params
2920     const VkCommandBufferAllocateInfo secCmdBufParams = {
2921         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
2922         nullptr,                                        // pNext;
2923         *cmdPool,                                       // pool;
2924         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
2925         1u,                                             // flags;
2926     };
2927     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
2928 
2929     const VkCommandBufferBeginInfo primBufferBeginInfo = {
2930         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2931         nullptr,                                     // pNext
2932         0u,                                          // flags
2933         nullptr,
2934     };
2935 
2936     const VkCommandBufferInheritanceInfo secBufferInheritInfo = {
2937         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2938         nullptr,
2939         VK_NULL_HANDLE,                    // renderPass
2940         0u,                                // subpass
2941         VK_NULL_HANDLE,                    // framebuffer
2942         VK_TRUE,                           // occlusionQueryEnable
2943         0u,                                // queryFlags
2944         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
2945     };
2946     const VkCommandBufferBeginInfo secBufferBeginInfo = {
2947         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
2948         nullptr,                                     // pNext
2949         0u,                                          // flags
2950         &secBufferInheritInfo,
2951     };
2952 
2953     const VkQueryPoolCreateInfo queryPoolCreateInfo = {
2954         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
2955         nullptr,                                  // pNext
2956         (VkQueryPoolCreateFlags)0,
2957         VK_QUERY_TYPE_OCCLUSION,
2958         1u,
2959         0u,
2960     };
2961     Unique<VkQueryPool> queryPool(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
2962 
2963     VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
2964     endCommandBuffer(vk, secCmdBuf.get());
2965 
2966     VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
2967     {
2968         vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
2969         vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, 0u);
2970         {
2971             vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
2972         }
2973         vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
2974     }
2975     endCommandBuffer(vk, primCmdBuf.get());
2976 
2977     return tcu::TestStatus::pass("Successfully recorded an imprecise query with a secondary command buffer not "
2978                                  "allowing a precise occlusion query.");
2979 }
2980 
2981 /******** 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) ****************/
submitBufferCountNonZero(Context & context)2982 tcu::TestStatus submitBufferCountNonZero(Context &context)
2983 {
2984     const VkDevice vkDevice         = context.getDevice();
2985     const DeviceInterface &vk       = context.getDeviceInterface();
2986     const VkQueue queue             = context.getUniversalQueue();
2987     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2988 
2989     const uint32_t BUFFER_COUNT = 5u;
2990 
2991     const VkCommandPoolCreateInfo cmdPoolParams = {
2992         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
2993         nullptr,                                    // pNext;
2994         0u,                                         // flags;
2995         queueFamilyIndex,                           // queueFamilyIndex;
2996     };
2997     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
2998 
2999     // Command buffer
3000     const VkCommandBufferAllocateInfo cmdBufParams = {
3001         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3002         nullptr,                                        // pNext;
3003         *cmdPool,                                       // pool;
3004         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3005         BUFFER_COUNT,                                   // bufferCount;
3006     };
3007     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3008     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3009 
3010     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3011         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3012         nullptr,                                     // pNext
3013         0u,                                          // flags
3014         nullptr,
3015     };
3016 
3017     std::vector<VkEventSp> events;
3018     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3019     {
3020         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3021     }
3022 
3023     VkCommandBuffer cmdBufferHandles[BUFFER_COUNT];
3024 
3025     // Record the command buffers
3026     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3027     {
3028         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3029         {
3030             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3031         }
3032         endCommandBuffer(vk, cmdBuffers[ndx].get());
3033         cmdBufferHandles[ndx] = cmdBuffers[ndx].get();
3034     }
3035 
3036     // We'll use a fence to wait for the execution of the queue
3037     const Unique<VkFence> fence(createFence(vk, vkDevice));
3038 
3039     const VkSubmitInfo submitInfo = {
3040         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3041         nullptr,                       // pNext
3042         0u,                            // waitSemaphoreCount
3043         nullptr,                       // pWaitSemaphores
3044         nullptr,                       // pWaitDstStageMask
3045         BUFFER_COUNT,                  // commandBufferCount
3046         cmdBufferHandles,              // pCommandBuffers
3047         0u,                            // signalSemaphoreCount
3048         nullptr,                       // pSignalSemaphores
3049     };
3050 
3051     // Submit the alpha command buffer to the queue
3052     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence.get()));
3053     // Wait for the queue
3054     VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
3055 
3056     // Check if the buffers were executed
3057     tcu::TestStatus testResult = tcu::TestStatus::incomplete();
3058 
3059     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3060     {
3061         if (vk.getEventStatus(vkDevice, events[ndx]->get()) != VK_EVENT_SET)
3062         {
3063             testResult = tcu::TestStatus::fail("Failed to set the event.");
3064             break;
3065         }
3066     }
3067 
3068     if (!testResult.isComplete())
3069         testResult = tcu::TestStatus::pass("All buffers were submitted and executed correctly.");
3070 
3071     return testResult;
3072 }
3073 
submitBufferCountEqualZero(Context & context)3074 tcu::TestStatus submitBufferCountEqualZero(Context &context)
3075 {
3076     const VkDevice vkDevice         = context.getDevice();
3077     const DeviceInterface &vk       = context.getDeviceInterface();
3078     const VkQueue queue             = context.getUniversalQueue();
3079     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3080 
3081     const uint32_t BUFFER_COUNT = 2u;
3082 
3083     const VkCommandPoolCreateInfo cmdPoolParams = {
3084         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
3085         nullptr,                                    // pNext;
3086         0u,                                         // flags;
3087         queueFamilyIndex,                           // queueFamilyIndex;
3088     };
3089     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3090 
3091     // Command buffer
3092     const VkCommandBufferAllocateInfo cmdBufParams = {
3093         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3094         nullptr,                                        // pNext;
3095         *cmdPool,                                       // pool;
3096         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3097         BUFFER_COUNT,                                   // bufferCount;
3098     };
3099     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3100     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3101 
3102     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3103         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3104         nullptr,                                     // pNext
3105         0u,                                          // flags
3106         nullptr,
3107     };
3108 
3109     std::vector<VkEventSp> events;
3110     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3111         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3112 
3113     // Record the command buffers
3114     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3115     {
3116         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3117         {
3118             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3119         }
3120         endCommandBuffer(vk, cmdBuffers[ndx].get());
3121     }
3122 
3123     // We'll use a fence to wait for the execution of the queue
3124     const Unique<VkFence> fenceZero(createFence(vk, vkDevice));
3125     const Unique<VkFence> fenceOne(createFence(vk, vkDevice));
3126 
3127     VkCommandBuffer cmdBuf0                = cmdBuffers[0].get();
3128     const VkSubmitInfo submitInfoCountZero = {
3129         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3130         nullptr,                       // pNext
3131         0u,                            // waitSemaphoreCount
3132         nullptr,                       // pWaitSemaphores
3133         nullptr,                       // pWaitDstStageMask
3134         1u,                            // commandBufferCount
3135         &cmdBuf0,                      // pCommandBuffers
3136         0u,                            // signalSemaphoreCount
3137         nullptr,                       // pSignalSemaphores
3138     };
3139 
3140     VkCommandBuffer cmdBuf1               = cmdBuffers[1].get();
3141     const VkSubmitInfo submitInfoCountOne = {
3142         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3143         nullptr,                       // pNext
3144         0u,                            // waitSemaphoreCount
3145         nullptr,                       // pWaitSemaphores
3146         nullptr,                       // pWaitDstStageMask
3147         1u,                            // commandBufferCount
3148         &cmdBuf1,                      // pCommandBuffers
3149         0u,                            // signalSemaphoreCount
3150         nullptr,                       // pSignalSemaphores
3151     };
3152 
3153     // Submit the command buffers to the queue
3154     // We're performing two submits to make sure that the first one has
3155     // a chance to be processed before we check the event's status
3156     VK_CHECK(vk.queueSubmit(queue, 0, &submitInfoCountZero, fenceZero.get()));
3157     VK_CHECK(vk.queueSubmit(queue, 1, &submitInfoCountOne, fenceOne.get()));
3158 
3159     const VkFence fences[] = {
3160         fenceZero.get(),
3161         fenceOne.get(),
3162     };
3163 
3164     // Wait for the queue
3165     VK_CHECK(vk.waitForFences(vkDevice, (uint32_t)DE_LENGTH_OF_ARRAY(fences), fences, VK_TRUE, INFINITE_TIMEOUT));
3166 
3167     // Check if the first buffer was executed
3168     tcu::TestStatus testResult = tcu::TestStatus::incomplete();
3169 
3170     if (vk.getEventStatus(vkDevice, events[0]->get()) == VK_EVENT_SET)
3171         testResult = tcu::TestStatus::fail("The first event was signaled.");
3172     else
3173         testResult = tcu::TestStatus::pass("The first submission was ignored.");
3174 
3175     return testResult;
3176 }
3177 
submitBufferWaitSingleSemaphore(Context & context)3178 tcu::TestStatus submitBufferWaitSingleSemaphore(Context &context)
3179 {
3180     const VkDevice vkDevice         = context.getDevice();
3181     const DeviceInterface &vk       = context.getDeviceInterface();
3182     const VkQueue queue             = context.getUniversalQueue();
3183     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3184 
3185     const VkCommandPoolCreateInfo cmdPoolParams = {
3186         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
3187         nullptr,                                         // const void* pNext;
3188         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
3189         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
3190     };
3191     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3192 
3193     // Command buffer
3194     const VkCommandBufferAllocateInfo cmdBufParams = {
3195         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3196         nullptr,                                        // const void* pNext;
3197         *cmdPool,                                       // VkCommandPool pool;
3198         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
3199         1u,                                             // uint32_t bufferCount;
3200     };
3201 
3202     // Create two command buffers
3203     const Unique<VkCommandBuffer> primCmdBuf1(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3204     const Unique<VkCommandBuffer> primCmdBuf2(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3205 
3206     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3207         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3208         nullptr,                                     // pNext
3209         0,                                           // flags
3210         nullptr                                      // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
3211     };
3212 
3213     // create two events that will be used to check if command buffers has been executed
3214     const Unique<VkEvent> event1(createEvent(vk, vkDevice));
3215     const Unique<VkEvent> event2(createEvent(vk, vkDevice));
3216 
3217     // reset events
3218     VK_CHECK(vk.resetEvent(vkDevice, *event1));
3219     VK_CHECK(vk.resetEvent(vkDevice, *event2));
3220 
3221     // record first command buffer
3222     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf1, &primCmdBufBeginInfo));
3223     {
3224         // allow execution of event during every stage of pipeline
3225         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3226 
3227         // record setting event
3228         vk.cmdSetEvent(*primCmdBuf1, *event1, stageMask);
3229     }
3230     endCommandBuffer(vk, *primCmdBuf1);
3231 
3232     // record second command buffer
3233     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf2, &primCmdBufBeginInfo));
3234     {
3235         // allow execution of event during every stage of pipeline
3236         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3237 
3238         // record setting event
3239         vk.cmdSetEvent(*primCmdBuf2, *event2, stageMask);
3240     }
3241     endCommandBuffer(vk, *primCmdBuf2);
3242 
3243     // create fence to wait for execution of queue
3244     const Unique<VkFence> fence(createFence(vk, vkDevice));
3245 
3246     // create semaphore for use in this test
3247     const Unique<VkSemaphore> semaphore(createSemaphore(vk, vkDevice));
3248 
3249     // create submit info for first buffer - signalling semaphore
3250     const VkSubmitInfo submitInfo1 = {
3251         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3252         nullptr,                       // pNext
3253         0u,                            // waitSemaphoreCount
3254         nullptr,                       // pWaitSemaphores
3255         nullptr,                       // pWaitDstStageMask
3256         1,                             // commandBufferCount
3257         &primCmdBuf1.get(),            // pCommandBuffers
3258         1u,                            // signalSemaphoreCount
3259         &semaphore.get(),              // pSignalSemaphores
3260     };
3261 
3262     // Submit the command buffer to the queue
3263     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));
3264 
3265     // wait for end of execution of queue
3266     VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
3267 
3268     // check if buffer has been executed
3269     VkResult result = vk.getEventStatus(vkDevice, *event1);
3270     if (result != VK_EVENT_SET)
3271         return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");
3272 
3273     const VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
3274 
3275     // create submit info for second buffer - waiting for semaphore
3276     const VkSubmitInfo submitInfo2 = {
3277         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3278         nullptr,                       // pNext
3279         1u,                            // waitSemaphoreCount
3280         &semaphore.get(),              // pWaitSemaphores
3281         &waitDstStageFlags,            // pWaitDstStageMask
3282         1,                             // commandBufferCount
3283         &primCmdBuf2.get(),            // pCommandBuffers
3284         0u,                            // signalSemaphoreCount
3285         nullptr,                       // pSignalSemaphores
3286     };
3287 
3288     // reset fence, so it can be used again
3289     VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
3290 
3291     // Submit the second command buffer to the queue
3292     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));
3293 
3294     // wait for end of execution of queue
3295     VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
3296 
3297     // check if second buffer has been executed
3298     // if it has been executed, it means that the semaphore was signalled - so test if passed
3299     result = vk.getEventStatus(vkDevice, *event1);
3300     if (result != VK_EVENT_SET)
3301         return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");
3302 
3303     return tcu::TestStatus::pass("Submit Buffer and Wait for Single Semaphore Test succeeded");
3304 }
3305 
submitBufferWaitManySemaphores(Context & context)3306 tcu::TestStatus submitBufferWaitManySemaphores(Context &context)
3307 {
3308     // This test will create numSemaphores semaphores, and signal them in NUM_SEMAPHORES submits to queue
3309     // After that the numSubmissions queue submissions will wait for each semaphore
3310 
3311     const uint32_t numSemaphores    = 10u; // it must be multiply of numSubmission
3312     const uint32_t numSubmissions   = 2u;
3313     const VkDevice vkDevice         = context.getDevice();
3314     const DeviceInterface &vk       = context.getDeviceInterface();
3315     const VkQueue queue             = context.getUniversalQueue();
3316     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3317 
3318     const VkCommandPoolCreateInfo cmdPoolParams = {
3319         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
3320         nullptr,                                         // const void* pNext;
3321         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
3322         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
3323     };
3324     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3325 
3326     // Command buffer
3327     const VkCommandBufferAllocateInfo cmdBufParams = {
3328         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3329         nullptr,                                        // const void* pNext;
3330         *cmdPool,                                       // VkCommandPool pool;
3331         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
3332         1u,                                             // uint32_t bufferCount;
3333     };
3334 
3335     // Create command buffer
3336     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3337 
3338     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3339         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3340         nullptr,                                     // pNext
3341         0,                                           // flags
3342         nullptr                                      // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
3343     };
3344 
3345     // create event that will be used to check if command buffers has been executed
3346     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3347 
3348     // reset event - at creation state is undefined
3349     VK_CHECK(vk.resetEvent(vkDevice, *event));
3350 
3351     // record command buffer
3352     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3353     {
3354         // allow execution of event during every stage of pipeline
3355         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3356 
3357         // record setting event
3358         vk.cmdSetEvent(*primCmdBuf, *event, stageMask);
3359     }
3360     endCommandBuffer(vk, *primCmdBuf);
3361 
3362     // create fence to wait for execution of queue
3363     const Unique<VkFence> fence(createFence(vk, vkDevice));
3364 
3365     // numSemaphores is declared const, so this array can be static
3366     // the semaphores will be destroyed automatically at end of scope
3367     Move<VkSemaphore> semaphoreArray[numSemaphores];
3368     VkSemaphore semaphores[numSemaphores];
3369 
3370     for (uint32_t idx = 0; idx < numSemaphores; ++idx)
3371     {
3372         // create semaphores for use in this test
3373         semaphoreArray[idx] = createSemaphore(vk, vkDevice);
3374         semaphores[idx]     = semaphoreArray[idx].get();
3375     }
3376 
3377     {
3378         // create submit info for buffer - signal semaphores
3379         const VkSubmitInfo submitInfo1 = {
3380             VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3381             nullptr,                       // pNext
3382             0u,                            // waitSemaphoreCount
3383             nullptr,                       // pWaitSemaphores
3384             nullptr,                       // pWaitDstStageMask
3385             1,                             // commandBufferCount
3386             &primCmdBuf.get(),             // pCommandBuffers
3387             numSemaphores,                 // signalSemaphoreCount
3388             semaphores                     // pSignalSemaphores
3389         };
3390         // Submit the command buffer to the queue
3391         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));
3392 
3393         // wait for end of execution of queue
3394         VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
3395 
3396         // check if buffer has been executed
3397         VkResult result = vk.getEventStatus(vkDevice, *event);
3398         if (result != VK_EVENT_SET)
3399             return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");
3400 
3401         // reset event, so next buffers can set it again
3402         VK_CHECK(vk.resetEvent(vkDevice, *event));
3403 
3404         // reset fence, so it can be used again
3405         VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
3406     }
3407 
3408     const uint32_t numberOfSemaphoresToBeWaitedByOneSubmission = numSemaphores / numSubmissions;
3409     const std::vector<VkPipelineStageFlags> waitDstStageFlags(numberOfSemaphoresToBeWaitedByOneSubmission,
3410                                                               VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
3411 
3412     // the following code waits for the semaphores set above - numSubmissions queues will wait for each semaphore from above
3413     for (uint32_t idxSubmission = 0; idxSubmission < numSubmissions; ++idxSubmission)
3414     {
3415 
3416         // create submit info for buffer - waiting for semaphore
3417         const VkSubmitInfo submitInfo2 = {
3418             VK_STRUCTURE_TYPE_SUBMIT_INFO,                                              // sType
3419             nullptr,                                                                    // pNext
3420             numberOfSemaphoresToBeWaitedByOneSubmission,                                // waitSemaphoreCount
3421             semaphores + (numberOfSemaphoresToBeWaitedByOneSubmission * idxSubmission), // pWaitSemaphores
3422             waitDstStageFlags.data(),                                                   // pWaitDstStageMask
3423             1,                                                                          // commandBufferCount
3424             &primCmdBuf.get(),                                                          // pCommandBuffers
3425             0u,                                                                         // signalSemaphoreCount
3426             nullptr,                                                                    // pSignalSemaphores
3427         };
3428 
3429         // Submit the second command buffer to the queue
3430         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));
3431 
3432         // wait for 1 second.
3433         VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, 1000 * 1000 * 1000));
3434 
3435         // check if second buffer has been executed
3436         // if it has been executed, it means that the semaphore was signalled - so test if passed
3437         VkResult result = vk.getEventStatus(vkDevice, *event);
3438         if (result != VK_EVENT_SET)
3439             return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");
3440 
3441         // reset fence, so it can be used again
3442         VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
3443 
3444         // reset event, so next buffers can set it again
3445         VK_CHECK(vk.resetEvent(vkDevice, *event));
3446     }
3447 
3448     return tcu::TestStatus::pass("Submit Buffer and Wait for Many Semaphores Test succeeded");
3449 }
3450 
submitBufferNullFence(Context & context)3451 tcu::TestStatus submitBufferNullFence(Context &context)
3452 {
3453     const VkDevice vkDevice         = context.getDevice();
3454     const DeviceInterface &vk       = context.getDeviceInterface();
3455     const VkQueue queue             = context.getUniversalQueue();
3456     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3457 
3458     const short BUFFER_COUNT = 2;
3459 
3460     const VkCommandPoolCreateInfo cmdPoolParams = {
3461         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
3462         nullptr,                                    // pNext;
3463         0u,                                         // flags;
3464         queueFamilyIndex,                           // queueFamilyIndex;
3465     };
3466     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3467 
3468     // Command buffer
3469     const VkCommandBufferAllocateInfo cmdBufParams = {
3470         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3471         nullptr,                                        // pNext;
3472         *cmdPool,                                       // pool;
3473         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3474         BUFFER_COUNT,                                   // bufferCount;
3475     };
3476     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3477     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3478 
3479     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3480         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3481         nullptr,                                     // pNext
3482         0u,                                          // flags
3483         nullptr,
3484     };
3485 
3486     std::vector<VkEventSp> events;
3487     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3488         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3489 
3490     // Record the command buffers
3491     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3492     {
3493         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3494         {
3495             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3496         }
3497         endCommandBuffer(vk, cmdBuffers[ndx].get());
3498     }
3499 
3500     // We'll use a fence to wait for the execution of the queue
3501     const Unique<VkFence> fence(createFence(vk, vkDevice));
3502 
3503     VkCommandBuffer cmdBuf0                = cmdBuffers[0].get();
3504     const VkSubmitInfo submitInfoNullFence = {
3505         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3506         nullptr,                       // pNext
3507         0u,                            // waitSemaphoreCount
3508         nullptr,                       // pWaitSemaphores
3509         nullptr,                       // pWaitDstStageMask
3510         1u,                            // commandBufferCount
3511         &cmdBuf0,                      // pCommandBuffers
3512         0u,                            // signalSemaphoreCount
3513         nullptr,                       // pSignalSemaphores
3514     };
3515 
3516     VkCommandBuffer cmdBuf1                   = cmdBuffers[1].get();
3517     const VkSubmitInfo submitInfoNonNullFence = {
3518         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3519         nullptr,                       // pNext
3520         0u,                            // waitSemaphoreCount
3521         nullptr,                       // pWaitSemaphores
3522         nullptr,                       // pWaitDstStageMask
3523         1u,                            // commandBufferCount
3524         &cmdBuf1,                      // pCommandBuffers
3525         0u,                            // signalSemaphoreCount
3526         nullptr,                       // pSignalSemaphores
3527     };
3528 
3529     // Perform two submissions - one with no fence, the other one with a valid
3530     // fence Hoping submitting the other buffer will give the first one time to
3531     // execute
3532     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNullFence, VK_NULL_HANDLE));
3533     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullFence, fence.get()));
3534 
3535     // Wait for the queue
3536     VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
3537 
3538     tcu::TestStatus testResult = tcu::TestStatus::incomplete();
3539 
3540     //Fence guaranteed that all buffers submited before fence were executed
3541     if (vk.getEventStatus(vkDevice, events[0]->get()) != VK_EVENT_SET ||
3542         vk.getEventStatus(vkDevice, events[1]->get()) != VK_EVENT_SET)
3543     {
3544         testResult = tcu::TestStatus::fail("One of the buffers was not executed.");
3545     }
3546     else
3547     {
3548         testResult = tcu::TestStatus::pass("Buffers have been submitted and executed correctly.");
3549     }
3550 
3551     vk.queueWaitIdle(queue);
3552     return testResult;
3553 }
3554 
submitTwoBuffersOneBufferNullWithFence(Context & context)3555 tcu::TestStatus submitTwoBuffersOneBufferNullWithFence(Context &context)
3556 {
3557     const VkDevice vkDevice         = context.getDevice();
3558     const DeviceInterface &vk       = context.getDeviceInterface();
3559     const VkQueue queue             = context.getUniversalQueue();
3560     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3561     const uint32_t BUFFER_COUNT     = 2u;
3562 
3563     const VkCommandPoolCreateInfo cmdPoolParams = {
3564         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3565         nullptr,                                         // pNext;
3566         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3567         queueFamilyIndex,                                // queueFamilyIndex;
3568     };
3569     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3570 
3571     const VkCommandBufferAllocateInfo cmdBufParams = {
3572         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3573         nullptr,                                        // pNext;
3574         *cmdPool,                                       // pool;
3575         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3576         BUFFER_COUNT,                                   // bufferCount;
3577     };
3578 
3579     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
3580     allocateCommandBuffers(vk, vkDevice, &cmdBufParams, cmdBuffers);
3581 
3582     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
3583         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3584         nullptr,                                     // pNext
3585         0u,                                          // flags
3586         nullptr,                                     // pInheritanceInfo
3587     };
3588 
3589     std::vector<VkEventSp> events;
3590     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3591         events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
3592 
3593     // Record the command buffers
3594     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
3595     {
3596         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &cmdBufBeginInfo));
3597         {
3598             vk.cmdSetEvent(cmdBuffers[ndx].get(), events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3599         }
3600         VK_CHECK(vk.endCommandBuffer(cmdBuffers[ndx].get()));
3601     }
3602 
3603     // First command buffer
3604     VkCommandBuffer cmdBuf0                   = cmdBuffers[0].get();
3605     const VkSubmitInfo submitInfoNonNullFirst = {
3606         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3607         nullptr,                       // pNext
3608         0u,                            // waitSemaphoreCount
3609         nullptr,                       // pWaitSemaphores
3610         nullptr,                       // pWaitDstStageMask
3611         1u,                            // commandBufferCount
3612         &cmdBuf0,                      // pCommandBuffers
3613         0u,                            // signalSemaphoreCount
3614         nullptr,                       // pSignalSemaphores
3615     };
3616 
3617     // Second command buffer
3618     VkCommandBuffer cmdBuf1                    = cmdBuffers[1].get();
3619     const VkSubmitInfo submitInfoNonNullSecond = {
3620         VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
3621         nullptr,                       // pNext
3622         0u,                            // waitSemaphoreCount
3623         nullptr,                       // pWaitSemaphores
3624         nullptr,                       // pWaitDstStageMask
3625         1u,                            // commandBufferCount
3626         &cmdBuf1,                      // pCommandBuffers
3627         0u,                            // signalSemaphoreCount
3628         nullptr,                       // pSignalSemaphores
3629     };
3630 
3631     // Fence will be submitted with the null queue
3632     const Unique<VkFence> fence(createFence(vk, vkDevice));
3633 
3634     // Perform two separate queueSubmit calls on the same queue followed
3635     // by a third call with no submitInfos and with a valid fence
3636     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullFirst, VK_NULL_HANDLE));
3637     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullSecond, VK_NULL_HANDLE));
3638     VK_CHECK(vk.queueSubmit(queue, 0u, nullptr, fence.get()));
3639 
3640     // Wait for the queue
3641     VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
3642 
3643     return tcu::TestStatus::pass("Buffers have been submitted correctly");
3644 }
3645 
3646 /******** 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) *******/
executeSecondaryBufferTest(Context & context)3647 tcu::TestStatus executeSecondaryBufferTest(Context &context)
3648 {
3649     const VkDevice vkDevice         = context.getDevice();
3650     const DeviceInterface &vk       = context.getDeviceInterface();
3651     const VkQueue queue             = context.getUniversalQueue();
3652     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3653 
3654     const VkCommandPoolCreateInfo cmdPoolParams = {
3655         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3656         nullptr,                                         // pNext;
3657         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3658         queueFamilyIndex,                                // queueFamilyIndex;
3659     };
3660     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3661 
3662     // Command buffer
3663     const VkCommandBufferAllocateInfo cmdBufParams = {
3664         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3665         nullptr,                                        // pNext;
3666         *cmdPool,                                       // commandPool;
3667         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3668         1u,                                             // bufferCount;
3669     };
3670     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3671 
3672     // Secondary Command buffer
3673     const VkCommandBufferAllocateInfo secCmdBufParams = {
3674         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3675         nullptr,                                        // pNext;
3676         *cmdPool,                                       // commandPool;
3677         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
3678         1u,                                             // bufferCount;
3679     };
3680     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
3681 
3682     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3683         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3684         nullptr,                                     // pNext
3685         0u,                                          // flags
3686         nullptr,
3687     };
3688 
3689     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
3690         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3691         nullptr,
3692         VK_NULL_HANDLE,                    // renderPass
3693         0u,                                // subpass
3694         VK_NULL_HANDLE,                    // framebuffer
3695         VK_FALSE,                          // occlusionQueryEnable
3696         (VkQueryControlFlags)0u,           // queryFlags
3697         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3698     };
3699     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
3700         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3701         nullptr,                                     // pNext
3702         0u,                                          // flags
3703         &secCmdBufInheritInfo,
3704     };
3705 
3706     // create event that will be used to check if secondary command buffer has been executed
3707     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3708 
3709     // reset event
3710     VK_CHECK(vk.resetEvent(vkDevice, *event));
3711 
3712     // record secondary command buffer
3713     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
3714     {
3715         // allow execution of event during every stage of pipeline
3716         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3717         // record setting event
3718         vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
3719     }
3720     // end recording of the secondary buffer
3721     endCommandBuffer(vk, *secCmdBuf);
3722 
3723     // record primary command buffer
3724     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3725     {
3726         // execute secondary buffer
3727         vk.cmdExecuteCommands(*primCmdBuf, 1u, &secCmdBuf.get());
3728     }
3729     endCommandBuffer(vk, *primCmdBuf);
3730 
3731     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
3732 
3733     // check if secondary buffer has been executed
3734     VkResult result = vk.getEventStatus(vkDevice, *event);
3735     if (result == VK_EVENT_SET)
3736         return tcu::TestStatus::pass("executeSecondaryBufferTest succeeded");
3737 
3738     return tcu::TestStatus::fail("executeSecondaryBufferTest FAILED");
3739 }
3740 
executeNestedBufferTest(Context & context)3741 tcu::TestStatus executeNestedBufferTest(Context &context)
3742 {
3743     const VkDevice vkDevice         = context.getDevice();
3744     const DeviceInterface &vk       = context.getDeviceInterface();
3745     const VkQueue queue             = context.getUniversalQueue();
3746     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3747 
3748     const VkCommandPoolCreateInfo cmdPoolParams = {
3749         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3750         nullptr,                                         // pNext;
3751         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3752         queueFamilyIndex,                                // queueFamilyIndex;
3753     };
3754     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3755 
3756     // Command buffer
3757     const VkCommandBufferAllocateInfo cmdBufParams = {
3758         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3759         nullptr,                                        // pNext;
3760         *cmdPool,                                       // commandPool;
3761         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3762         1u,                                             // bufferCount;
3763     };
3764     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3765 
3766     // Secondary Command buffer
3767     const VkCommandBufferAllocateInfo secCmdBufParams = {
3768         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3769         nullptr,                                        // pNext;
3770         *cmdPool,                                       // commandPool;
3771         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
3772         1u,                                             // bufferCount;
3773     };
3774     const Unique<VkCommandBuffer> secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
3775 
3776     // Nested secondary Command buffer
3777     const VkCommandBufferAllocateInfo nestedCmdBufParams = {
3778         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3779         nullptr,                                        // pNext;
3780         *cmdPool,                                       // commandPool;
3781         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // level;
3782         1u,                                             // bufferCount;
3783     };
3784     const Unique<VkCommandBuffer> nestedCmdBuf(allocateCommandBuffer(vk, vkDevice, &nestedCmdBufParams));
3785 
3786     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3787         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3788         nullptr,                                     // pNext
3789         0u,                                          // flags
3790         nullptr,
3791     };
3792 
3793     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
3794         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3795         nullptr,
3796         VK_NULL_HANDLE,                    // renderPass
3797         0u,                                // subpass
3798         VK_NULL_HANDLE,                    // framebuffer
3799         VK_FALSE,                          // occlusionQueryEnable
3800         (VkQueryControlFlags)0u,           // queryFlags
3801         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3802     };
3803     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
3804         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3805         nullptr,                                     // pNext
3806         0u,                                          // flags
3807         &secCmdBufInheritInfo,
3808     };
3809 
3810     const VkCommandBufferInheritanceInfo nestedCmdBufInheritInfo = {
3811         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3812         nullptr,
3813         VK_NULL_HANDLE,                    // renderPass
3814         0u,                                // subpass
3815         VK_NULL_HANDLE,                    // framebuffer
3816         VK_FALSE,                          // occlusionQueryEnable
3817         (VkQueryControlFlags)0u,           // queryFlags
3818         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3819     };
3820     const VkCommandBufferBeginInfo nestedCmdBufBeginInfo = {
3821         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3822         nullptr,                                     // pNext
3823         0u,                                          // flags
3824         &nestedCmdBufInheritInfo,
3825     };
3826 
3827     // create event that will be used to check if nested command buffer has been executed
3828     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3829 
3830     // reset event
3831     VK_CHECK(vk.resetEvent(vkDevice, *event));
3832 
3833     // record nested command buffer
3834     VK_CHECK(vk.beginCommandBuffer(*nestedCmdBuf, &nestedCmdBufBeginInfo));
3835     {
3836         // allow execution of event during every stage of pipeline
3837         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3838         // record setting event
3839         vk.cmdSetEvent(*nestedCmdBuf, *event, stageMask);
3840     }
3841     // end recording of the secondary buffer
3842     endCommandBuffer(vk, *nestedCmdBuf);
3843 
3844     // record secondary command buffer
3845     VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
3846     {
3847         // execute nested buffer
3848         vk.cmdExecuteCommands(*secCmdBuf, 1u, &nestedCmdBuf.get());
3849     }
3850     // end recording of the secondary buffer
3851     endCommandBuffer(vk, *secCmdBuf);
3852 
3853     // record primary command buffer
3854     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3855     {
3856         // execute secondary buffer
3857         vk.cmdExecuteCommands(*primCmdBuf, 1u, &secCmdBuf.get());
3858     }
3859     endCommandBuffer(vk, *primCmdBuf);
3860 
3861     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
3862 
3863     // check if secondary buffer has been executed
3864     VkResult result = vk.getEventStatus(vkDevice, *event);
3865     if (result == VK_EVENT_SET)
3866         return tcu::TestStatus::pass("executeNestedBufferTest succeeded");
3867 
3868     return tcu::TestStatus::fail("executeNestedBufferTest FAILED");
3869 }
3870 
executeMultipleLevelsNestedBufferTest(Context & context)3871 tcu::TestStatus executeMultipleLevelsNestedBufferTest(Context &context)
3872 {
3873     const uint32_t BUFFER_COUNT     = 2u;
3874     const VkDevice vkDevice         = context.getDevice();
3875     const DeviceInterface &vk       = context.getDeviceInterface();
3876     const VkQueue queue             = context.getUniversalQueue();
3877     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3878 
3879     const VkCommandPoolCreateInfo cmdPoolParams = {
3880         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType;
3881         nullptr,                                         // pNext;
3882         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
3883         queueFamilyIndex,                                // queueFamilyIndex;
3884     };
3885     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3886 
3887     // Command buffer
3888     const VkCommandBufferAllocateInfo cmdBufParams = {
3889         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
3890         nullptr,                                        // pNext;
3891         *cmdPool,                                       // commandPool;
3892         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level;
3893         1u,                                             // bufferCount;
3894     };
3895     const Unique<VkCommandBuffer> primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
3896 
3897     // Secondary Command buffers
3898     const VkCommandBufferAllocateInfo secCmdBufParams = {
3899         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3900         nullptr,                                        // const void* pNext;
3901         *cmdPool,                                       // VkCommandPool pool;
3902         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
3903         BUFFER_COUNT,                                   // uint32_t bufferCount;
3904     };
3905     Move<VkCommandBuffer> nestedBuffers[BUFFER_COUNT];
3906     allocateCommandBuffers(vk, vkDevice, &secCmdBufParams, nestedBuffers);
3907 
3908     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
3909         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3910         nullptr,                                     // pNext
3911         0u,                                          // flags
3912         nullptr,
3913     };
3914 
3915     const VkCommandBufferInheritanceInfo nestedCmdBufInheritInfo = {
3916         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
3917         nullptr,
3918         VK_NULL_HANDLE,                    // renderPass
3919         0u,                                // subpass
3920         VK_NULL_HANDLE,                    // framebuffer
3921         VK_FALSE,                          // occlusionQueryEnable
3922         (VkQueryControlFlags)0u,           // queryFlags
3923         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
3924     };
3925     const VkCommandBufferBeginInfo nestedCmdBufBeginInfo = {
3926         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
3927         nullptr,                                     // pNext
3928         0u,                                          // flags
3929         &nestedCmdBufInheritInfo,
3930     };
3931 
3932     // create event that will be used to check if secondary command buffer has been executed
3933     const Unique<VkEvent> event(createEvent(vk, vkDevice));
3934 
3935     // reset event
3936     VK_CHECK(vk.resetEvent(vkDevice, *event));
3937 
3938     // record nested secondary command buffers
3939     VK_CHECK(vk.beginCommandBuffer(*(nestedBuffers[0]), &nestedCmdBufBeginInfo));
3940     {
3941         // allow execution of event during every stage of pipeline
3942         VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
3943         // record setting event
3944         vk.cmdSetEvent(*(nestedBuffers[0]), *event, stageMask);
3945     }
3946     // end recording of the secondary buffer
3947     endCommandBuffer(vk, *(nestedBuffers[0]));
3948 
3949     for (uint32_t ndx = 1; ndx < BUFFER_COUNT; ndx++)
3950     {
3951         VK_CHECK(vk.beginCommandBuffer(*(nestedBuffers[ndx]), &nestedCmdBufBeginInfo));
3952         {
3953             // execute nested buffer
3954             vk.cmdExecuteCommands(*(nestedBuffers[ndx]), 1u, &(nestedBuffers[ndx - 1]).get());
3955         }
3956         // end recording of the secondary buffer
3957         endCommandBuffer(vk, *(nestedBuffers[ndx]));
3958     }
3959 
3960     // record primary command buffer
3961     VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
3962     {
3963         // execute secondary buffer
3964         vk.cmdExecuteCommands(*primCmdBuf, 1u, &(nestedBuffers[BUFFER_COUNT - 1]).get());
3965     }
3966     endCommandBuffer(vk, *primCmdBuf);
3967 
3968     submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
3969 
3970     // check if secondary buffer has been executed
3971     VkResult result = vk.getEventStatus(vkDevice, *event);
3972     if (result == VK_EVENT_SET)
3973         return tcu::TestStatus::pass("executeMultipleLevelsNestedBufferTest succeeded");
3974 
3975     return tcu::TestStatus::fail("executeMultipleLevelsNestedBufferTest FAILED");
3976 }
3977 
executeSecondaryBufferTwiceTest(Context & context)3978 tcu::TestStatus executeSecondaryBufferTwiceTest(Context &context)
3979 {
3980     const uint32_t BUFFER_COUNT     = 10u;
3981     const VkDevice vkDevice         = context.getDevice();
3982     const DeviceInterface &vk       = context.getDeviceInterface();
3983     const VkQueue queue             = context.getUniversalQueue();
3984     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3985 
3986     const VkCommandPoolCreateInfo cmdPoolParams = {
3987         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
3988         nullptr,                                         // const void* pNext;
3989         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
3990         queueFamilyIndex,                                // uint32_t queueFamilyIndex;
3991     };
3992     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
3993 
3994     // Command buffer
3995     const VkCommandBufferAllocateInfo cmdBufParams = {
3996         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3997         nullptr,                                        // const void* pNext;
3998         *cmdPool,                                       // VkCommandPool pool;
3999         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
4000         1u,                                             // uint32_t bufferCount;
4001     };
4002     const Unique<VkCommandBuffer> primCmdBufOne(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
4003     const Unique<VkCommandBuffer> primCmdBufTwo(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
4004 
4005     // Secondary Command buffers params
4006     const VkCommandBufferAllocateInfo secCmdBufParams = {
4007         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
4008         nullptr,                                        // const void* pNext;
4009         *cmdPool,                                       // VkCommandPool pool;
4010         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
4011         BUFFER_COUNT,                                   // uint32_t bufferCount;
4012     };
4013     Move<VkCommandBuffer> cmdBuffers[BUFFER_COUNT];
4014     allocateCommandBuffers(vk, vkDevice, &secCmdBufParams, cmdBuffers);
4015 
4016     const VkCommandBufferBeginInfo primCmdBufBeginInfo = {
4017         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
4018         nullptr,
4019         0, // flags
4020         nullptr,
4021     };
4022 
4023     const VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
4024         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
4025         nullptr,
4026         VK_NULL_HANDLE,                    // renderPass
4027         0u,                                // subpass
4028         VK_NULL_HANDLE,                    // framebuffer
4029         VK_FALSE,                          // occlusionQueryEnable
4030         (VkQueryControlFlags)0u,           // queryFlags
4031         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
4032     };
4033     const VkCommandBufferBeginInfo secCmdBufBeginInfo = {
4034         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
4035         nullptr,
4036         VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // flags
4037         &secCmdBufInheritInfo,
4038     };
4039 
4040     // create event that will be used to check if secondary command buffer has been executed
4041     const Unique<VkEvent> eventOne(createEvent(vk, vkDevice));
4042 
4043     // reset event
4044     VK_CHECK(vk.resetEvent(vkDevice, *eventOne));
4045 
4046     VkCommandBuffer cmdBufferHandles[BUFFER_COUNT];
4047 
4048     for (uint32_t ndx = 0; ndx < BUFFER_COUNT; ++ndx)
4049     {
4050         // record secondary command buffer
4051         VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx].get(), &secCmdBufBeginInfo));
4052         {
4053             // set event
4054             vk.cmdSetEvent(cmdBuffers[ndx].get(), *eventOne, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
4055         }
4056         // end recording of secondary buffers
4057         endCommandBuffer(vk, cmdBuffers[ndx].get());
4058         cmdBufferHandles[ndx] = cmdBuffers[ndx].get();
4059     }
4060 
4061     // record primary command buffer one
4062     VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
4063     {
4064         // execute one secondary buffer
4065         vk.cmdExecuteCommands(*primCmdBufOne, 1, cmdBufferHandles);
4066     }
4067     endCommandBuffer(vk, *primCmdBufOne);
4068 
4069     // record primary command buffer two
4070     VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
4071     {
4072         // execute one secondary buffer with all buffers
4073         vk.cmdExecuteCommands(*primCmdBufTwo, BUFFER_COUNT, cmdBufferHandles);
4074     }
4075     endCommandBuffer(vk, *primCmdBufTwo);
4076 
4077     // create fence to wait for execution of queue
4078     const Unique<VkFence> fenceOne(createFence(vk, vkDevice));
4079     const Unique<VkFence> fenceTwo(createFence(vk, vkDevice));
4080 
4081     const uint64_t semaphoreWaitValue             = 1ull;
4082     const VkPipelineStageFlags semaphoreWaitStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
4083     const auto semaphore                          = createSemaphoreType(vk, vkDevice, VK_SEMAPHORE_TYPE_TIMELINE);
4084 
4085     // Use timeline semaphore to wait for signal from the host.
4086     const VkTimelineSemaphoreSubmitInfo timelineWaitSubmitInfo = {
4087         VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, // VkStructureType sType;
4088         nullptr,                                          // const void* pNext;
4089         1u,                                               // uint32_t waitSemaphoreValueCount;
4090         &semaphoreWaitValue,                              // const uint64_t* pWaitSemaphoreValues;
4091         0u,                                               // uint32_t signalSemaphoreValueCount;
4092         nullptr,                                          // const uint64_t* pSignalSemaphoreValues;
4093     };
4094 
4095     const VkSubmitInfo submitInfo = {
4096         VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
4097         &timelineWaitSubmitInfo,       // const void* pNext;
4098         1u,                            // uint32_t waitSemaphoreCount;
4099         &semaphore.get(),              // const VkSemaphore* pWaitSemaphores;
4100         &semaphoreWaitStage,           // const VkPipelineStageFlags* pWaitDstStageMask;
4101         1u,                            // uint32_t commandBufferCount;
4102         &primCmdBufOne.get(),          // const VkCommandBuffer* pCommandBuffers;
4103         0u,                            // uint32_t signalSemaphoreCount;
4104         nullptr,                       // const VkSemaphore* pSignalSemaphores;
4105     };
4106     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fenceOne));
4107 
4108     const VkSubmitInfo submitInfo2 = {
4109         VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
4110         &timelineWaitSubmitInfo,       // const void* pNext;
4111         1u,                            // uint32_t waitSemaphoreCount;
4112         &semaphore.get(),              // const VkSemaphore* pWaitSemaphores;
4113         &semaphoreWaitStage,           // const VkPipelineStageFlags* pWaitDstStageMask;
4114         1u,                            // uint32_t commandBufferCount;
4115         &primCmdBufTwo.get(),          // const VkCommandBuffer* pCommandBuffers;
4116         0u,                            // uint32_t signalSemaphoreCount;
4117         nullptr,                       // const VkSemaphore* pSignalSemaphores;
4118     };
4119 
4120     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fenceTwo));
4121 
4122     // Signal from host
4123     const vk::VkSemaphoreSignalInfo signalInfo = {
4124         vk::VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType;
4125         nullptr,                                     // const void* pNext;
4126         semaphore.get(),                             // VkSemaphore semaphore;
4127         semaphoreWaitValue,                          // uint64_t value;
4128     };
4129 
4130     VK_CHECK(vk.signalSemaphore(vkDevice, &signalInfo));
4131 
4132     // wait for end of execution of fenceOne
4133     VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, INFINITE_TIMEOUT));
4134 
4135     // wait for end of execution of fenceTwo
4136     VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceTwo.get(), 0u, INFINITE_TIMEOUT));
4137 
4138     TCU_CHECK(vk.getEventStatus(vkDevice, *eventOne) == vk::VK_EVENT_SET);
4139 
4140     return tcu::TestStatus::pass("executeSecondaryBufferTwiceTest succeeded");
4141 }
4142 
4143 /******** 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) **/
orderBindPipelineTest(Context & context)4144 tcu::TestStatus orderBindPipelineTest(Context &context)
4145 {
4146     const DeviceInterface &vk       = context.getDeviceInterface();
4147     const VkDevice device           = context.getDevice();
4148     const VkQueue queue             = context.getUniversalQueue();
4149     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
4150     Allocator &allocator            = context.getDefaultAllocator();
4151     const ComputeInstanceResultBuffer result(vk, device, allocator);
4152 
4153     enum
4154     {
4155         ADDRESSABLE_SIZE = 256, // allocate a lot more than required
4156     };
4157 
4158     const tcu::Vec4 colorA1 = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
4159     const tcu::Vec4 colorA2 = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
4160     const tcu::Vec4 colorB1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
4161     const tcu::Vec4 colorB2 = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
4162 
4163     const uint32_t dataOffsetA = (0u);
4164     const uint32_t dataOffsetB = (0u);
4165     const uint32_t viewOffsetA = (0u);
4166     const uint32_t viewOffsetB = (0u);
4167     const uint32_t bufferSizeA = dataOffsetA + ADDRESSABLE_SIZE;
4168     const uint32_t bufferSizeB = dataOffsetB + ADDRESSABLE_SIZE;
4169 
4170     de::MovePtr<Allocation> bufferMemA;
4171     const Unique<VkBuffer> bufferA(
4172         createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA, context));
4173 
4174     de::MovePtr<Allocation> bufferMemB;
4175     const Unique<VkBuffer> bufferB(
4176         createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB, context));
4177 
4178     const Unique<VkDescriptorSetLayout> descriptorSetLayout(createDescriptorSetLayout(context));
4179     const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(context));
4180     const Unique<VkDescriptorSet> descriptorSet(createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA,
4181                                                                     viewOffsetA, *bufferB, viewOffsetB,
4182                                                                     result.getBuffer(), context));
4183     const VkDescriptorSet descriptorSets[] = {*descriptorSet};
4184     const int numDescriptorSets            = DE_LENGTH_OF_ARRAY(descriptorSets);
4185 
4186     const VkPipelineLayoutCreateInfo layoutCreateInfo = {
4187         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
4188         nullptr,                                       // pNext
4189         (VkPipelineLayoutCreateFlags)0,
4190         numDescriptorSets,          // setLayoutCount
4191         &descriptorSetLayout.get(), // pSetLayouts
4192         0u,                         // pushConstantRangeCount
4193         nullptr,                    // pPushConstantRanges
4194     };
4195     Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, device, &layoutCreateInfo));
4196 
4197     const Unique<VkShaderModule> computeModuleGood(createShaderModule(
4198         vk, device, context.getBinaryCollection().get("compute_good"), (VkShaderModuleCreateFlags)0u));
4199     const Unique<VkShaderModule> computeModuleBad(createShaderModule(
4200         vk, device, context.getBinaryCollection().get("compute_bad"), (VkShaderModuleCreateFlags)0u));
4201 
4202     const VkPipelineShaderStageCreateInfo shaderCreateInfoGood = {
4203         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4204         nullptr,
4205         (VkPipelineShaderStageCreateFlags)0,
4206         VK_SHADER_STAGE_COMPUTE_BIT, // stage
4207         *computeModuleGood,          // shader
4208         "main",
4209         nullptr, // pSpecializationInfo
4210     };
4211 
4212     const VkPipelineShaderStageCreateInfo shaderCreateInfoBad = {
4213         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4214         nullptr,
4215         (vk::VkPipelineShaderStageCreateFlags)0,
4216         vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
4217         *computeModuleBad,               // shader
4218         "main",
4219         nullptr, // pSpecializationInfo
4220     };
4221 
4222     const VkComputePipelineCreateInfo createInfoGood = {
4223         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
4224         nullptr,
4225         0u,                   // flags
4226         shaderCreateInfoGood, // cs
4227         *pipelineLayout,      // layout
4228         VK_NULL_HANDLE,       // basePipelineHandle
4229         0u,                   // basePipelineIndex
4230     };
4231 
4232     const VkComputePipelineCreateInfo createInfoBad = {
4233         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
4234         nullptr,
4235         0u,                  // flags
4236         shaderCreateInfoBad, // cs
4237         *pipelineLayout,     // descriptorSetLayout.get()
4238         VK_NULL_HANDLE,      // basePipelineHandle
4239         0u,                  // basePipelineIndex
4240     };
4241 
4242     const Unique<VkPipeline> pipelineGood(createComputePipeline(vk, device, VK_NULL_HANDLE, &createInfoGood));
4243     const Unique<VkPipeline> pipelineBad(createComputePipeline(vk, device, VK_NULL_HANDLE, &createInfoBad));
4244 
4245     const VkAccessFlags inputBit                 = (VK_ACCESS_UNIFORM_READ_BIT);
4246     const VkBufferMemoryBarrier bufferBarriers[] = {{
4247                                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, nullptr,
4248                                                         VK_ACCESS_HOST_WRITE_BIT,  // srcAccessMask
4249                                                         inputBit,                  // dstAccessMask
4250                                                         VK_QUEUE_FAMILY_IGNORED,   // srcQueueFamilyIndex
4251                                                         VK_QUEUE_FAMILY_IGNORED,   // destQueueFamilyIndex
4252                                                         *bufferA,                  // buffer
4253                                                         (VkDeviceSize)0u,          // offset
4254                                                         (VkDeviceSize)bufferSizeA, // size
4255                                                     },
4256                                                     {
4257                                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, nullptr,
4258                                                         VK_ACCESS_HOST_WRITE_BIT,  // srcAccessMask
4259                                                         inputBit,                  // dstAccessMask
4260                                                         VK_QUEUE_FAMILY_IGNORED,   // srcQueueFamilyIndex
4261                                                         VK_QUEUE_FAMILY_IGNORED,   // destQueueFamilyIndex
4262                                                         *bufferB,                  // buffer
4263                                                         (VkDeviceSize)0u,          // offset
4264                                                         (VkDeviceSize)bufferSizeB, // size
4265                                                     }};
4266 
4267     const uint32_t numSrcBuffers = 1u;
4268 
4269     const uint32_t *const dynamicOffsets                = (nullptr);
4270     const uint32_t numDynamicOffsets                    = (0);
4271     const int numPreBarriers                            = numSrcBuffers;
4272     const vk::VkBufferMemoryBarrier *const postBarriers = result.getResultReadBarrier();
4273     const int numPostBarriers                           = 1;
4274     const tcu::Vec4 refQuadrantValue14                  = (colorA2);
4275     const tcu::Vec4 refQuadrantValue23                  = (colorA1);
4276     const tcu::Vec4 references[4]                       = {
4277         refQuadrantValue14,
4278         refQuadrantValue23,
4279         refQuadrantValue23,
4280         refQuadrantValue14,
4281     };
4282     tcu::Vec4 results[4];
4283 
4284     // submit and wait begin
4285 
4286     const tcu::UVec3 numWorkGroups = tcu::UVec3(4, 1u, 1);
4287 
4288     const VkCommandPoolCreateInfo cmdPoolCreateInfo = {
4289         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
4290         nullptr,                                    // pNext
4291         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // flags
4292         queueFamilyIndex,                           // queueFamilyIndex
4293     };
4294     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolCreateInfo));
4295     const VkCommandBufferAllocateInfo cmdBufCreateInfo = {
4296         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
4297         nullptr,                                        // pNext
4298         *cmdPool,                                       // commandPool
4299         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level
4300         1u,                                             // bufferCount;
4301     };
4302 
4303     const VkCommandBufferBeginInfo cmdBufBeginInfo = {
4304         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
4305         nullptr,                                     // pNext
4306         0u,                                          // flags
4307         nullptr,
4308     };
4309 
4310     const Unique<VkCommandBuffer> cmd(allocateCommandBuffer(vk, device, &cmdBufCreateInfo));
4311 
4312     VK_CHECK(vk.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
4313 
4314     vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineBad);
4315     vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineGood);
4316     vk.cmdBindDescriptorSets(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets,
4317                              descriptorSets, numDynamicOffsets, dynamicOffsets);
4318 
4319     if (numPreBarriers)
4320         vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
4321                               (VkDependencyFlags)0, 0, nullptr, numPreBarriers, bufferBarriers, 0, nullptr);
4322 
4323     vk.cmdDispatch(*cmd, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
4324     vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
4325                           0, nullptr, numPostBarriers, postBarriers, 0, nullptr);
4326     endCommandBuffer(vk, *cmd);
4327 
4328     // run
4329     // submit second primary buffer, the secondary should be executed too
4330     submitCommandsAndWait(vk, device, queue, cmd.get());
4331 
4332     // submit and wait end
4333     result.readResultContentsTo(&results);
4334 
4335     // verify
4336     if (results[0] == references[0] && results[1] == references[1] && results[2] == references[2] &&
4337         results[3] == references[3])
4338     {
4339         return tcu::TestStatus::pass("Pass");
4340     }
4341     else if (results[0] == tcu::Vec4(-1.0f) && results[1] == tcu::Vec4(-1.0f) && results[2] == tcu::Vec4(-1.0f) &&
4342              results[3] == tcu::Vec4(-1.0f))
4343     {
4344         context.getTestContext().getLog()
4345             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
4346         return tcu::TestStatus::fail("Result buffer was not written to");
4347     }
4348     else
4349     {
4350         context.getTestContext().getLog()
4351             << tcu::TestLog::Message << "Error expected [" << references[0] << ", " << references[1] << ", "
4352             << references[2] << ", " << references[3] << "], got [" << results[0] << ", " << results[1] << ", "
4353             << results[2] << ", " << results[3] << "]" << tcu::TestLog::EndMessage;
4354         return tcu::TestStatus::fail("Invalid result values");
4355     }
4356 }
4357 
4358 enum StateTransitionTest
4359 {
4360     STT_RECORDING_TO_INITIAL = 0,
4361     STT_EXECUTABLE_TO_INITIAL,
4362     STT_RECORDING_TO_INVALID,
4363     STT_EXECUTABLE_TO_INVALID,
4364 };
4365 
executeStateTransitionTest(Context & context,StateTransitionTest type)4366 tcu::TestStatus executeStateTransitionTest(Context &context, StateTransitionTest type)
4367 {
4368     const VkDevice vkDevice         = context.getDevice();
4369     const DeviceInterface &vk       = context.getDeviceInterface();
4370     const VkQueue queue             = context.getUniversalQueue();
4371     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
4372 
4373 #ifdef CTS_USES_VULKANSC
4374     if (context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
4375         TCU_THROW(NotSupportedError, "commandPoolResetCommandBuffer not supported by this implementation");
4376 #endif // CTS_USES_VULKANSC
4377 
4378     const Unique<VkCommandPool> cmdPool(
4379         createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
4380     const Unique<VkCommandBuffer> cmdBuffer(
4381         allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4382     const Unique<VkEvent> globalEvent(createEvent(vk, vkDevice));
4383 
4384     VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));
4385 
4386     switch (type)
4387     {
4388     case STT_RECORDING_TO_INITIAL:
4389     {
4390         beginCommandBuffer(vk, *cmdBuffer, 0u);
4391         vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4392         break;
4393         // command buffer is still in recording state
4394     }
4395     case STT_EXECUTABLE_TO_INITIAL:
4396     {
4397         beginCommandBuffer(vk, *cmdBuffer, 0u);
4398         vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4399         endCommandBuffer(vk, *cmdBuffer);
4400         break;
4401         // command buffer is still in executable state
4402     }
4403     case STT_RECORDING_TO_INVALID:
4404     {
4405         VkSubpassDescription subpassDescription;
4406         deMemset(&subpassDescription, 0, sizeof(VkSubpassDescription));
4407         subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
4408 
4409         VkRenderPassCreateInfo renderPassCreateInfo{
4410             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, &subpassDescription, 0, nullptr};
4411 
4412         // Error here - renderpass and framebuffer were created localy
4413         Move<VkRenderPass> renderPass = createRenderPass(vk, vkDevice, &renderPassCreateInfo);
4414 
4415         VkFramebufferCreateInfo framebufferCreateInfo{
4416             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, *renderPass, 0, nullptr, 16, 16, 1};
4417         Move<VkFramebuffer> framebuffer = createFramebuffer(vk, vkDevice, &framebufferCreateInfo);
4418 
4419         VkRenderPassBeginInfo renderPassBeginInfo = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
4420                                                      nullptr,
4421                                                      *renderPass,
4422                                                      *framebuffer,
4423                                                      {{0, 0}, {16, 16}},
4424                                                      0,
4425                                                      nullptr};
4426 
4427         beginCommandBuffer(vk, *cmdBuffer, 0u);
4428         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
4429         vk.cmdEndRenderPass(*cmdBuffer);
4430 
4431         // not executing endCommandBuffer(vk, *cmdBuffer);
4432         // command buffer is still in recording state
4433         break;
4434         // renderpass and framebuffer are destroyed; command buffer should be now in invalid state
4435     }
4436     case STT_EXECUTABLE_TO_INVALID:
4437     {
4438         // create event that will be used to check if command buffer has been executed
4439         const Unique<VkEvent> localEvent(createEvent(vk, vkDevice));
4440         VK_CHECK(vk.resetEvent(vkDevice, *localEvent));
4441 
4442         beginCommandBuffer(vk, *cmdBuffer, 0u);
4443         vk.cmdSetEvent(*cmdBuffer, *localEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4444         endCommandBuffer(vk, *cmdBuffer);
4445         // command buffer is in executable state
4446         break;
4447         // localEvent is destroyed; command buffer should be now in invalid state
4448     }
4449     }
4450 
4451     VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));
4452 
4453     VK_CHECK(vk.resetCommandBuffer(*cmdBuffer, 0u));
4454     // command buffer should now be back in initial state
4455 
4456     // verify commandBuffer
4457     beginCommandBuffer(vk, *cmdBuffer, 0u);
4458     vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
4459     endCommandBuffer(vk, *cmdBuffer);
4460     submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
4461 
4462     // check if buffer has been executed
4463     VkResult result = vk.getEventStatus(vkDevice, *globalEvent);
4464     if (result != VK_EVENT_SET)
4465         return tcu::TestStatus::fail("Submit failed");
4466 
4467     return tcu::TestStatus::pass("Pass");
4468 }
4469 
4470 // Shaders
genComputeSource(SourceCollections & programCollection)4471 void genComputeSource(SourceCollections &programCollection)
4472 {
4473     const char *const versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
4474     std::ostringstream bufGood;
4475 
4476     bufGood << versionDecl << "\n"
4477             << ""
4478             << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
4479             << "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
4480             << "{\n"
4481             << "    highp vec4 colorA;\n"
4482             << "    highp vec4 colorB;\n"
4483             << "} b_instance;\n"
4484             << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
4485             << "{\n"
4486             << "    highp vec4 read_colors[4];\n"
4487             << "} b_out;\n"
4488             << "void main(void)\n"
4489             << "{\n"
4490             << "    highp int quadrant_id = int(gl_WorkGroupID.x);\n"
4491             << "    highp vec4 result_color;\n"
4492             << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
4493             << "        result_color = b_instance.colorA;\n"
4494             << "    else\n"
4495             << "        result_color = b_instance.colorB;\n"
4496             << "    b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
4497             << "}\n";
4498 
4499     programCollection.glslSources.add("compute_good") << glu::ComputeSource(bufGood.str());
4500 
4501     std::ostringstream bufBad;
4502 
4503     bufBad << versionDecl << "\n"
4504            << ""
4505            << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
4506            << "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
4507            << "{\n"
4508            << "    highp vec4 colorA;\n"
4509            << "    highp vec4 colorB;\n"
4510            << "} b_instance;\n"
4511            << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
4512            << "{\n"
4513            << "    highp vec4 read_colors[4];\n"
4514            << "} b_out;\n"
4515            << "void main(void)\n"
4516            << "{\n"
4517            << "    highp int quadrant_id = int(gl_WorkGroupID.x);\n"
4518            << "    highp vec4 result_color;\n"
4519            << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
4520            << "        result_color = b_instance.colorA;\n"
4521            << "    else\n"
4522            << "        result_color = b_instance.colorB;\n"
4523            << "    b_out.read_colors[gl_WorkGroupID.x] = vec4(0.0, 0.0, 0.0, 0.0);\n"
4524            << "}\n";
4525 
4526     programCollection.glslSources.add("compute_bad") << glu::ComputeSource(bufBad.str());
4527 }
4528 
genComputeIncrementSource(SourceCollections & programCollection)4529 void genComputeIncrementSource(SourceCollections &programCollection)
4530 {
4531     const char *const versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
4532     std::ostringstream bufIncrement;
4533 
4534     bufIncrement << versionDecl << "\n"
4535                  << ""
4536                  << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
4537                  << "layout(set = 0, binding = 0, std140) buffer InOutBuf\n"
4538                  << "{\n"
4539                  << "    coherent uint count;\n"
4540                  << "} b_in_out;\n"
4541                  << "void main(void)\n"
4542                  << "{\n"
4543                  << "    atomicAdd(b_in_out.count, 1u);\n"
4544                  << "}\n";
4545 
4546     programCollection.glslSources.add("compute_increment") << glu::ComputeSource(bufIncrement.str());
4547 }
4548 
genComputeIncrementSourceBadInheritance(SourceCollections & programCollection,BadInheritanceInfoCase testCase)4549 void genComputeIncrementSourceBadInheritance(SourceCollections &programCollection, BadInheritanceInfoCase testCase)
4550 {
4551     DE_UNREF(testCase);
4552     return genComputeIncrementSource(programCollection);
4553 }
4554 
checkEventSupport(Context & context)4555 void checkEventSupport(Context &context)
4556 {
4557 #ifndef CTS_USES_VULKANSC
4558     if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
4559         !context.getPortabilitySubsetFeatures().events)
4560         TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4561 #else
4562     DE_UNREF(context);
4563 #endif // CTS_USES_VULKANSC
4564 }
4565 
checkCommandBufferSimultaneousUseSupport(Context & context)4566 void checkCommandBufferSimultaneousUseSupport(Context &context)
4567 {
4568 #ifdef CTS_USES_VULKANSC
4569     if (context.getDeviceVulkanSC10Properties().commandBufferSimultaneousUse == VK_FALSE)
4570         TCU_THROW(NotSupportedError, "commandBufferSimultaneousUse is not supported");
4571 #else
4572     DE_UNREF(context);
4573 #endif // CTS_USES_VULKANSC
4574 }
4575 
checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(Context & context)4576 void checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(Context &context)
4577 {
4578 #ifdef CTS_USES_VULKANSC
4579     if (context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
4580         TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
4581 #else
4582     DE_UNREF(context);
4583 #endif // CTS_USES_VULKANSC
4584 }
4585 
checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1(Context & context,bool value)4586 void checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1(Context &context, bool value)
4587 {
4588     DE_UNREF(value);
4589 #ifdef CTS_USES_VULKANSC
4590     if (context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
4591         TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
4592 #else
4593     DE_UNREF(context);
4594 #endif // CTS_USES_VULKANSC
4595 }
4596 
checkEventAndSecondaryCommandBufferNullFramebufferSupport(Context & context)4597 void checkEventAndSecondaryCommandBufferNullFramebufferSupport(Context &context)
4598 {
4599     checkEventSupport(context);
4600     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(context);
4601 }
4602 
checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context & context)4603 void checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context &context)
4604 {
4605     checkCommandBufferSimultaneousUseSupport(context);
4606     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(context);
4607 }
4608 
checkEventAndTimelineSemaphoreAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context & context)4609 void checkEventAndTimelineSemaphoreAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context &context)
4610 {
4611     checkEventSupport(context);
4612     context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
4613 
4614     checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(context);
4615 }
4616 
checkNestedCommandBufferSupport(Context & context)4617 void checkNestedCommandBufferSupport(Context &context)
4618 {
4619     checkEventAndSecondaryCommandBufferNullFramebufferSupport(context);
4620     context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
4621 
4622 #ifndef CTS_USES_VULKANSC
4623     const auto &features = context.getNestedCommandBufferFeaturesEXT();
4624     if (!features.nestedCommandBuffer)
4625 #endif // CTS_USES_VULKANSC
4626         TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
4627 }
4628 
checkNestedCommandBufferDepthSupport(Context & context)4629 void checkNestedCommandBufferDepthSupport(Context &context)
4630 {
4631     checkNestedCommandBufferSupport(context);
4632 
4633 #ifndef CTS_USES_VULKANSC
4634     const auto &properties = context.getNestedCommandBufferPropertiesEXT();
4635     if (properties.maxCommandBufferNestingLevel <= 1)
4636 #endif // CTS_USES_VULKANSC
4637         TCU_THROW(NotSupportedError, "nestedCommandBuffer with nesting level greater than 1 is not supported");
4638 }
4639 
checkNestedCommandBufferRenderPassContinueSupport(Context & context,bool value)4640 void checkNestedCommandBufferRenderPassContinueSupport(Context &context, bool value)
4641 {
4642     checkNestedCommandBufferSupport(context);
4643 
4644     DE_UNREF(value);
4645 #ifndef CTS_USES_VULKANSC
4646     const auto &features = context.getNestedCommandBufferFeaturesEXT();
4647     if (!features.nestedCommandBufferRendering)
4648 #endif // CTS_USES_VULKANSC
4649         TCU_THROW(NotSupportedError, "nestedCommandBufferRendering is not supported");
4650 }
4651 
checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport(Context & context)4652 void checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport(Context &context)
4653 {
4654     checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(context);
4655     checkNestedCommandBufferSupport(context);
4656 #ifndef CTS_USES_VULKANSC
4657     const auto &features = context.getNestedCommandBufferFeaturesEXT();
4658     if (!features.nestedCommandBufferSimultaneousUse)
4659 #endif // CTS_USES_VULKANSC
4660         TCU_THROW(NotSupportedError, "nestedCommandBufferSimultaneousUse is not supported");
4661 }
4662 
4663 #ifndef CTS_USES_VULKANSC
checkEventSupport(Context & context,const VkCommandBufferLevel)4664 void checkEventSupport(Context &context, const VkCommandBufferLevel)
4665 {
4666     checkEventSupport(context);
4667 }
4668 #endif // CTS_USES_VULKANSC
4669 
4670 struct ManyDrawsParams
4671 {
4672     VkCommandBufferLevel level;
4673     VkExtent3D imageExtent;
4674     uint32_t seed;
4675 
ManyDrawsParamsvkt::api::__anonad5542ac0111::ManyDrawsParams4676     ManyDrawsParams(VkCommandBufferLevel level_, const VkExtent3D &extent_, uint32_t seed_)
4677         : level(level_)
4678         , imageExtent(extent_)
4679         , seed(seed_)
4680     {
4681     }
4682 };
4683 
4684 struct ManyDrawsVertex
4685 {
4686     using Color = tcu::Vector<uint8_t, 4>;
4687 
4688     tcu::Vec2 coords;
4689     Color color;
4690 
ManyDrawsVertexvkt::api::__anonad5542ac0111::ManyDrawsVertex4691     ManyDrawsVertex(const tcu::Vec2 &coords_, const Color &color_) : coords(coords_), color(color_)
4692     {
4693     }
4694 };
4695 
getSupportedDepthStencilFormat(const InstanceInterface & vki,VkPhysicalDevice physDev)4696 VkFormat getSupportedDepthStencilFormat(const InstanceInterface &vki, VkPhysicalDevice physDev)
4697 {
4698     const VkFormat formatList[] = {VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
4699     const VkFormatFeatureFlags requirements =
4700         (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
4701 
4702     for (int i = 0; i < DE_LENGTH_OF_ARRAY(formatList); ++i)
4703     {
4704         const auto properties = getPhysicalDeviceFormatProperties(vki, physDev, formatList[i]);
4705         if ((properties.optimalTilingFeatures & requirements) == requirements)
4706             return formatList[i];
4707     }
4708 
4709     TCU_THROW(NotSupportedError, "No suitable depth/stencil format support");
4710     return VK_FORMAT_UNDEFINED;
4711 }
4712 
4713 class ManyDrawsCase : public TestCase
4714 {
4715 public:
4716     ManyDrawsCase(tcu::TestContext &testCtx, const std::string &name, const ManyDrawsParams &params);
~ManyDrawsCase(void)4717     virtual ~ManyDrawsCase(void)
4718     {
4719     }
4720 
4721     virtual void checkSupport(Context &context) const;
4722     virtual void initPrograms(vk::SourceCollections &programCollection) const;
4723     virtual TestInstance *createInstance(Context &context) const;
4724 
getColorFormat(void)4725     static VkFormat getColorFormat(void)
4726     {
4727         return VK_FORMAT_R8G8B8A8_UINT;
4728     }
4729 
4730 protected:
4731     ManyDrawsParams m_params;
4732 };
4733 
4734 class ManyDrawsInstance : public TestInstance
4735 {
4736 public:
4737     ManyDrawsInstance(Context &context, const ManyDrawsParams &params);
~ManyDrawsInstance(void)4738     virtual ~ManyDrawsInstance(void)
4739     {
4740     }
4741 
4742     virtual tcu::TestStatus iterate(void);
4743 
4744 protected:
4745     ManyDrawsParams m_params;
4746 };
4747 
4748 using BufferPtr = de::MovePtr<BufferWithMemory>;
4749 using ImagePtr  = de::MovePtr<ImageWithMemory>;
4750 
4751 struct ManyDrawsVertexBuffers
4752 {
4753     BufferPtr stagingBuffer;
4754     BufferPtr vertexBuffer;
4755 };
4756 
4757 struct ManyDrawsAllocatedData
4758 {
4759     ManyDrawsVertexBuffers frontBuffers;
4760     ManyDrawsVertexBuffers backBuffers;
4761     ImagePtr colorAttachment;
4762     ImagePtr dsAttachment;
4763     BufferPtr colorCheckBuffer;
4764     BufferPtr stencilCheckBuffer;
4765 
calcNumPixelsvkt::api::__anonad5542ac0111::ManyDrawsAllocatedData4766     static uint32_t calcNumPixels(const VkExtent3D &extent)
4767     {
4768         DE_ASSERT(extent.depth == 1u);
4769         return (extent.width * extent.height);
4770     }
calcNumVerticesvkt::api::__anonad5542ac0111::ManyDrawsAllocatedData4771     static uint32_t calcNumVertices(const VkExtent3D &extent)
4772     {
4773         // One triangle (3 vertices) per output image pixel.
4774         return (calcNumPixels(extent) * 3u);
4775     }
4776 
calcVertexBufferSizevkt::api::__anonad5542ac0111::ManyDrawsAllocatedData4777     static VkDeviceSize calcVertexBufferSize(const VkExtent3D &extent)
4778     {
4779         return calcNumVertices(extent) * sizeof(ManyDrawsVertex);
4780     }
4781 
makeVertexBuffersvkt::api::__anonad5542ac0111::ManyDrawsAllocatedData4782     static void makeVertexBuffers(const DeviceInterface &vkd, VkDevice device, Allocator &alloc, VkDeviceSize size,
4783                                   ManyDrawsVertexBuffers &buffers)
4784     {
4785         const auto stagingBufferInfo = makeBufferCreateInfo(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
4786         const auto vertexBufferInfo =
4787             makeBufferCreateInfo(size, (VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
4788 
4789         buffers.stagingBuffer =
4790             BufferPtr(new BufferWithMemory(vkd, device, alloc, stagingBufferInfo, MemoryRequirement::HostVisible));
4791         buffers.vertexBuffer =
4792             BufferPtr(new BufferWithMemory(vkd, device, alloc, vertexBufferInfo, MemoryRequirement::Any));
4793     }
4794 
ManyDrawsAllocatedDatavkt::api::__anonad5542ac0111::ManyDrawsAllocatedData4795     ManyDrawsAllocatedData(const DeviceInterface &vkd, VkDevice device, Allocator &alloc, const VkExtent3D &imageExtent,
4796                            VkFormat colorFormat, VkFormat dsFormat)
4797     {
4798         const auto numPixels        = calcNumPixels(imageExtent);
4799         const auto vertexBufferSize = calcVertexBufferSize(imageExtent);
4800 
4801         makeVertexBuffers(vkd, device, alloc, vertexBufferSize, frontBuffers);
4802         makeVertexBuffers(vkd, device, alloc, vertexBufferSize, backBuffers);
4803 
4804         const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
4805         const auto dsUsage    = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
4806 
4807         const VkImageCreateInfo colorAttachmentInfo = {
4808             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
4809             nullptr,                             // const void* pNext;
4810             0u,                                  // VkImageCreateFlags flags;
4811             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
4812             colorFormat,                         // VkFormat format;
4813             imageExtent,                         // VkExtent3D extent;
4814             1u,                                  // uint32_t mipLevels;
4815             1u,                                  // uint32_t arrayLayers;
4816             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
4817             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
4818             colorUsage,                          // VkImageUsageFlags usage;
4819             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
4820             0u,                                  // uint32_t queueFamilyIndexCount;
4821             nullptr,                             // const uint32_t* pQueueFamilyIndices;
4822             VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
4823         };
4824         colorAttachment =
4825             ImagePtr(new ImageWithMemory(vkd, device, alloc, colorAttachmentInfo, MemoryRequirement::Any));
4826 
4827         const VkImageCreateInfo dsAttachmentInfo = {
4828             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
4829             nullptr,                             // const void* pNext;
4830             0u,                                  // VkImageCreateFlags flags;
4831             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
4832             dsFormat,                            // VkFormat format;
4833             imageExtent,                         // VkExtent3D extent;
4834             1u,                                  // uint32_t mipLevels;
4835             1u,                                  // uint32_t arrayLayers;
4836             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
4837             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
4838             dsUsage,                             // VkImageUsageFlags usage;
4839             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
4840             0u,                                  // uint32_t queueFamilyIndexCount;
4841             nullptr,                             // const uint32_t* pQueueFamilyIndices;
4842             VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
4843         };
4844         dsAttachment = ImagePtr(new ImageWithMemory(vkd, device, alloc, dsAttachmentInfo, MemoryRequirement::Any));
4845 
4846         const auto colorCheckBufferSize =
4847             static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(mapVkFormat(colorFormat)));
4848         const auto colorCheckBufferInfo = makeBufferCreateInfo(colorCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4849 
4850         colorCheckBuffer =
4851             BufferPtr(new BufferWithMemory(vkd, device, alloc, colorCheckBufferInfo, MemoryRequirement::HostVisible));
4852 
4853         const auto stencilFormat = tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
4854         const auto stencilCheckBufferSize = static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(stencilFormat));
4855         const auto stencilCheckBufferInfo =
4856             makeBufferCreateInfo(stencilCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
4857 
4858         stencilCheckBuffer =
4859             BufferPtr(new BufferWithMemory(vkd, device, alloc, stencilCheckBufferInfo, MemoryRequirement::HostVisible));
4860     }
4861 };
4862 
ManyDrawsCase(tcu::TestContext & testCtx,const std::string & name,const ManyDrawsParams & params)4863 ManyDrawsCase::ManyDrawsCase(tcu::TestContext &testCtx, const std::string &name, const ManyDrawsParams &params)
4864     : TestCase(testCtx, name)
4865     , m_params(params)
4866 {
4867 }
4868 
checkSupport(Context & context) const4869 void ManyDrawsCase::checkSupport(Context &context) const
4870 {
4871     const auto &vki     = context.getInstanceInterface();
4872     const auto physDev  = context.getPhysicalDevice();
4873     const auto &vkd     = context.getDeviceInterface();
4874     const auto device   = context.getDevice();
4875     auto &alloc         = context.getDefaultAllocator();
4876     const auto dsFormat = getSupportedDepthStencilFormat(vki, physDev);
4877 
4878     try
4879     {
4880         ManyDrawsAllocatedData allocatedData(vkd, device, alloc, m_params.imageExtent, getColorFormat(), dsFormat);
4881     }
4882     catch (const vk::Error &err)
4883     {
4884         const auto result = err.getError();
4885         if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY)
4886             TCU_THROW(NotSupportedError, "Not enough memory to run this test");
4887         throw;
4888     }
4889 }
4890 
initPrograms(vk::SourceCollections & programCollection) const4891 void ManyDrawsCase::initPrograms(vk::SourceCollections &programCollection) const
4892 {
4893     std::ostringstream vert;
4894     vert << "#version 450\n"
4895          << "\n"
4896          << "layout(location=0) in vec2 inCoords;\n"
4897          << "layout(location=1) in uvec4 inColor;\n"
4898          << "\n"
4899          << "layout(location=0) out flat uvec4 outColor;\n"
4900          << "\n"
4901          << "void main()\n"
4902          << "{\n"
4903          << "    gl_Position = vec4(inCoords, 0.0, 1.0);\n"
4904          << "    outColor = inColor;\n"
4905          << "}\n";
4906 
4907     std::ostringstream frag;
4908     frag << "#version 450\n"
4909          << "\n"
4910          << "layout(location=0) in flat uvec4 inColor;\n"
4911          << "layout(location=0) out uvec4 outColor;\n"
4912          << "\n"
4913          << "void main()\n"
4914          << "{\n"
4915          << "    outColor = inColor;\n"
4916          << "}\n";
4917 
4918     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
4919     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
4920 }
4921 
createInstance(Context & context) const4922 TestInstance *ManyDrawsCase::createInstance(Context &context) const
4923 {
4924     return new ManyDrawsInstance(context, m_params);
4925 }
4926 
ManyDrawsInstance(Context & context,const ManyDrawsParams & params)4927 ManyDrawsInstance::ManyDrawsInstance(Context &context, const ManyDrawsParams &params)
4928     : TestInstance(context)
4929     , m_params(params)
4930 {
4931 }
4932 
copyAndFlush(const DeviceInterface & vkd,VkDevice device,BufferWithMemory & buffer,const std::vector<ManyDrawsVertex> & vertices)4933 void copyAndFlush(const DeviceInterface &vkd, VkDevice device, BufferWithMemory &buffer,
4934                   const std::vector<ManyDrawsVertex> &vertices)
4935 {
4936     auto &alloc   = buffer.getAllocation();
4937     void *hostPtr = alloc.getHostPtr();
4938 
4939     deMemcpy(hostPtr, vertices.data(), de::dataSize(vertices));
4940     flushAlloc(vkd, device, alloc);
4941 }
4942 
iterate(void)4943 tcu::TestStatus ManyDrawsInstance::iterate(void)
4944 {
4945     const auto &vki    = m_context.getInstanceInterface();
4946     const auto physDev = m_context.getPhysicalDevice();
4947     const auto &vkd    = m_context.getDeviceInterface();
4948     const auto device  = m_context.getDevice();
4949     auto &alloc        = m_context.getDefaultAllocator();
4950     const auto qIndex  = m_context.getUniversalQueueFamilyIndex();
4951     const auto queue   = m_context.getUniversalQueue();
4952 
4953     const auto colorFormat        = ManyDrawsCase::getColorFormat();
4954     const auto dsFormat           = getSupportedDepthStencilFormat(vki, physDev);
4955     const auto vertexBufferSize   = ManyDrawsAllocatedData::calcVertexBufferSize(m_params.imageExtent);
4956     const auto vertexBufferOffset = static_cast<VkDeviceSize>(0);
4957     const auto numPixels          = ManyDrawsAllocatedData::calcNumPixels(m_params.imageExtent);
4958     const auto numVertices        = ManyDrawsAllocatedData::calcNumVertices(m_params.imageExtent);
4959     const auto alphaValue         = std::numeric_limits<uint8_t>::max();
4960     const auto pixelWidth         = 2.0f / static_cast<float>(m_params.imageExtent.width);  // Normalized size.
4961     const auto pixelWidthHalf     = pixelWidth / 2.0f;                                      // Normalized size.
4962     const auto pixelHeight        = 2.0f / static_cast<float>(m_params.imageExtent.height); // Normalized size.
4963     const auto useSecondary       = (m_params.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);
4964 
4965     // Allocate all needed data up front.
4966     ManyDrawsAllocatedData testData(vkd, device, alloc, m_params.imageExtent, colorFormat, dsFormat);
4967 
4968     // Generate random colors.
4969     de::Random rnd(m_params.seed);
4970     std::vector<ManyDrawsVertex::Color> colors;
4971 
4972     colors.reserve(numPixels);
4973     for (uint32_t i = 0; i < numPixels; ++i)
4974     {
4975 #if 0
4976         const uint8_t red = ((i      ) & 0xFFu);
4977         const uint8_t green = ((i >>  8) & 0xFFu);
4978         const uint8_t blue = ((i >> 16) & 0xFFu);
4979         colors.push_back(ManyDrawsVertex::Color(red, green, blue, alphaValue));
4980 #else
4981         colors.push_back(ManyDrawsVertex::Color(rnd.getUint8(), rnd.getUint8(), rnd.getUint8(), alphaValue));
4982 #endif
4983     }
4984 
4985     // Fill vertex data. One triangle per pixel, front and back.
4986     std::vector<ManyDrawsVertex> frontVector;
4987     std::vector<ManyDrawsVertex> backVector;
4988     frontVector.reserve(numVertices);
4989     backVector.reserve(numVertices);
4990 
4991     for (uint32_t y = 0; y < m_params.imageExtent.height; ++y)
4992         for (uint32_t x = 0; x < m_params.imageExtent.width; ++x)
4993         {
4994             float x_left   = static_cast<float>(x) * pixelWidth - 1.0f;
4995             float x_mid    = x_left + pixelWidthHalf;
4996             float x_right  = x_left + pixelWidth;
4997             float y_top    = static_cast<float>(y) * pixelHeight - 1.0f;
4998             float y_bottom = y_top + pixelHeight;
4999 
5000             // Triangles in the "back" mesh will have different colors.
5001             const auto colorIdx    = y * m_params.imageExtent.width + x;
5002             const auto &frontColor = colors[colorIdx];
5003             const auto &backColor  = colors[colors.size() - 1u - colorIdx];
5004 
5005             const tcu::Vec2 triangle[3u] = {
5006                 tcu::Vec2(x_left, y_top),
5007                 tcu::Vec2(x_right, y_top),
5008                 tcu::Vec2(x_mid, y_bottom),
5009             };
5010 
5011             frontVector.emplace_back(triangle[0], frontColor);
5012             frontVector.emplace_back(triangle[1], frontColor);
5013             frontVector.emplace_back(triangle[2], frontColor);
5014 
5015             backVector.emplace_back(triangle[0], backColor);
5016             backVector.emplace_back(triangle[1], backColor);
5017             backVector.emplace_back(triangle[2], backColor);
5018         }
5019 
5020     // Copy vertex data to staging buffers.
5021     copyAndFlush(vkd, device, *testData.frontBuffers.stagingBuffer, frontVector);
5022     copyAndFlush(vkd, device, *testData.backBuffers.stagingBuffer, backVector);
5023 
5024     // Color attachment view.
5025     const auto colorResourceRange  = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
5026     const auto colorAttachmentView = makeImageView(vkd, device, testData.colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D,
5027                                                    colorFormat, colorResourceRange);
5028 
5029     // Depth/stencil attachment view.
5030     const auto dsResourceRange =
5031         makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
5032     const auto dsAttachmentView =
5033         makeImageView(vkd, device, testData.dsAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsResourceRange);
5034 
5035     const VkImageView attachmentArray[] = {colorAttachmentView.get(), dsAttachmentView.get()};
5036     const auto numAttachments           = static_cast<uint32_t>(DE_LENGTH_OF_ARRAY(attachmentArray));
5037 
5038     const auto renderPass  = makeRenderPass(vkd, device, colorFormat, dsFormat);
5039     const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), numAttachments, attachmentArray,
5040                                              m_params.imageExtent.width, m_params.imageExtent.height);
5041 
5042     const auto vertModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
5043     const auto fragModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
5044 
5045     const std::vector<VkViewport> viewports(1u, makeViewport(m_params.imageExtent));
5046     const std::vector<VkRect2D> scissors(1u, makeRect2D(m_params.imageExtent));
5047 
5048     const auto descriptorSetLayout = DescriptorSetLayoutBuilder().build(vkd, device);
5049     const auto pipelineLayout      = makePipelineLayout(vkd, device, descriptorSetLayout.get());
5050 
5051     const VkVertexInputBindingDescription bindings[] = {
5052         makeVertexInputBindingDescription(0u, static_cast<uint32_t>(sizeof(ManyDrawsVertex)),
5053                                           VK_VERTEX_INPUT_RATE_VERTEX),
5054     };
5055 
5056     const VkVertexInputAttributeDescription attributes[] = {
5057         makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32_SFLOAT,
5058                                             static_cast<uint32_t>(offsetof(ManyDrawsVertex, coords))),
5059         makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R8G8B8A8_UINT,
5060                                             static_cast<uint32_t>(offsetof(ManyDrawsVertex, color))),
5061     };
5062 
5063     const VkPipelineVertexInputStateCreateInfo inputState = {
5064         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
5065         nullptr,                                                   // const void* pNext;
5066         0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
5067         static_cast<uint32_t>(DE_LENGTH_OF_ARRAY(bindings)),       // uint32_t vertexBindingDescriptionCount;
5068         bindings, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
5069         static_cast<uint32_t>(DE_LENGTH_OF_ARRAY(attributes)), // uint32_t vertexAttributeDescriptionCount;
5070         attributes, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
5071     };
5072 
5073     // Stencil state: this is key for checking and obtaining the right results. The stencil buffer will be cleared to 0. The first
5074     // set of draws ("front" set of triangles) will pass the test and increment the stencil value to 1. The second set of draws
5075     // ("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
5076     // still increment the stencil value to 2.
5077     //
5078     // At the end of the test, if every draw command was executed correctly in the expected order, the color buffer will have the
5079     // colors of the front set, and the stencil buffer will be full of 2s.
5080     const auto stencilOpState = makeStencilOpState(VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP,
5081                                                    VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xFFu, 0xFFu, 0u);
5082 
5083     const VkPipelineDepthStencilStateCreateInfo dsState = {
5084         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                          sType
5085         nullptr,                                                    // const void*                              pNext
5086         0u,                                                         // VkPipelineDepthStencilStateCreateFlags   flags
5087         VK_FALSE,            // VkBool32                                 depthTestEnable
5088         VK_FALSE,            // VkBool32                                 depthWriteEnable
5089         VK_COMPARE_OP_NEVER, // VkCompareOp                              depthCompareOp
5090         VK_FALSE,            // VkBool32                                 depthBoundsTestEnable
5091         VK_TRUE,             // VkBool32                                 stencilTestEnable
5092         stencilOpState,      // VkStencilOpState                         front
5093         stencilOpState,      // VkStencilOpState                         back
5094         0.0f,                // float                                    minDepthBounds
5095         1.0f,                // float                                    maxDepthBounds
5096     };
5097 
5098     const auto pipeline =
5099         makeGraphicsPipeline(vkd, device, pipelineLayout.get(), vertModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE,
5100                              VK_NULL_HANDLE, fragModule.get(), renderPass.get(), viewports, scissors,
5101                              VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &inputState, nullptr, nullptr, &dsState);
5102 
5103     // Command pool and buffers.
5104     using CmdBufferPtr    = Move<VkCommandBuffer>;
5105     const auto cmdPool    = makeCommandPool(vkd, device, qIndex);
5106     const auto secCmdPool = makeCommandPool(vkd, device, qIndex);
5107 
5108     CmdBufferPtr primaryCmdBufferPtr;
5109     CmdBufferPtr secondaryCmdBufferPtr;
5110     VkCommandBuffer primaryCmdBuffer;
5111     VkCommandBuffer secondaryCmdBuffer;
5112     VkCommandBuffer drawsCmdBuffer;
5113 
5114     primaryCmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5115     primaryCmdBuffer    = primaryCmdBufferPtr.get();
5116     drawsCmdBuffer      = primaryCmdBuffer;
5117     beginCommandBuffer(vkd, primaryCmdBuffer);
5118 
5119     // Clear values.
5120     std::vector<VkClearValue> clearValues(2u);
5121     clearValues[0] = makeClearValueColorU32(0u, 0u, 0u, 0u);
5122     clearValues[1] = makeClearValueDepthStencil(1.0f, 0u);
5123 
5124     // Copy staging buffers to vertex buffers.
5125     const auto copyRegion = makeBufferCopy(0ull, 0ull, vertexBufferSize);
5126     vkd.cmdCopyBuffer(primaryCmdBuffer, testData.frontBuffers.stagingBuffer->get(),
5127                       testData.frontBuffers.vertexBuffer->get(), 1u, &copyRegion);
5128     vkd.cmdCopyBuffer(primaryCmdBuffer, testData.backBuffers.stagingBuffer->get(),
5129                       testData.backBuffers.vertexBuffer->get(), 1u, &copyRegion);
5130 
5131     // Use barrier for vertex reads.
5132     const auto vertexBarier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
5133     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 1u,
5134                            &vertexBarier, 0u, nullptr, 0u, nullptr);
5135 
5136     // Change depth/stencil attachment layout.
5137     const auto dsBarrier = makeImageMemoryBarrier(
5138         0, (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT),
5139         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, testData.dsAttachment->get(),
5140         dsResourceRange);
5141     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
5142                            (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), 0u,
5143                            0u, nullptr, 0u, nullptr, 1u, &dsBarrier);
5144 
5145     beginRenderPass(vkd, primaryCmdBuffer, renderPass.get(), framebuffer.get(), scissors[0],
5146                     static_cast<uint32_t>(clearValues.size()), clearValues.data(),
5147                     (useSecondary ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE));
5148 
5149     if (useSecondary)
5150     {
5151         secondaryCmdBufferPtr = allocateCommandBuffer(vkd, device, secCmdPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5152         secondaryCmdBuffer    = secondaryCmdBufferPtr.get();
5153         drawsCmdBuffer        = secondaryCmdBuffer;
5154 
5155         const VkCommandBufferInheritanceInfo inheritanceInfo = {
5156             VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
5157             nullptr,                                           // const void* pNext;
5158             renderPass.get(),                                  // VkRenderPass renderPass;
5159             0u,                                                // uint32_t subpass;
5160             framebuffer.get(),                                 // VkFramebuffer framebuffer;
5161             0u,                                                // VkBool32 occlusionQueryEnable;
5162             0u,                                                // VkQueryControlFlags queryFlags;
5163             0u,                                                // VkQueryPipelineStatisticFlags pipelineStatistics;
5164         };
5165 
5166         const VkCommandBufferUsageFlags usageFlags =
5167             (VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
5168         const VkCommandBufferBeginInfo beginInfo = {
5169             VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
5170             usageFlags,       // VkCommandBufferUsageFlags flags;
5171             &inheritanceInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
5172         };
5173 
5174         VK_CHECK(vkd.beginCommandBuffer(secondaryCmdBuffer, &beginInfo));
5175     }
5176 
5177     // Bind pipeline.
5178     vkd.cmdBindPipeline(drawsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
5179 
5180     // Draw triangles in front.
5181     vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.frontBuffers.vertexBuffer->get(), &vertexBufferOffset);
5182     for (uint32_t i = 0; i < numPixels; ++i)
5183         vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i * 3u, 0u);
5184 
5185     // Draw triangles in the "back". This should have no effect due to the stencil test.
5186     vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.backBuffers.vertexBuffer->get(), &vertexBufferOffset);
5187     for (uint32_t i = 0; i < numPixels; ++i)
5188         vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i * 3u, 0u);
5189 
5190     if (useSecondary)
5191     {
5192         endCommandBuffer(vkd, secondaryCmdBuffer);
5193         vkd.cmdExecuteCommands(primaryCmdBuffer, 1u, &secondaryCmdBuffer);
5194     }
5195 
5196     endRenderPass(vkd, primaryCmdBuffer);
5197 
5198     // Copy color and depth/stencil attachments to verification buffers.
5199     const auto colorAttachmentBarrier = makeImageMemoryBarrier(
5200         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5201         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.colorAttachment->get(), colorResourceRange);
5202     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
5203                            VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorAttachmentBarrier);
5204 
5205     const auto colorResourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
5206     const auto colorCopyRegion     = makeBufferImageCopy(m_params.imageExtent, colorResourceLayers);
5207     vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.colorAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5208                              testData.colorCheckBuffer->get(), 1u, &colorCopyRegion);
5209 
5210     const auto stencilAttachmentBarrier =
5211         makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
5212                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5213                                testData.dsAttachment->get(), dsResourceRange);
5214     vkd.cmdPipelineBarrier(primaryCmdBuffer,
5215                            (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT),
5216                            VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &stencilAttachmentBarrier);
5217 
5218     const auto stencilResourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u);
5219     const auto stencilCopyRegion     = makeBufferImageCopy(m_params.imageExtent, stencilResourceLayers);
5220     vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.dsAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5221                              testData.stencilCheckBuffer->get(), 1u, &stencilCopyRegion);
5222 
5223     const auto verificationBuffersBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5224     vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u,
5225                            &verificationBuffersBarrier, 0u, nullptr, 0u, nullptr);
5226 
5227     endCommandBuffer(vkd, primaryCmdBuffer);
5228     submitCommandsAndWait(vkd, device, queue, primaryCmdBuffer);
5229 
5230     // Check buffer contents.
5231     auto &colorCheckBufferAlloc = testData.colorCheckBuffer->getAllocation();
5232     void *colorCheckBufferData  = colorCheckBufferAlloc.getHostPtr();
5233     invalidateAlloc(vkd, device, colorCheckBufferAlloc);
5234 
5235     auto &stencilCheckBufferAlloc = testData.stencilCheckBuffer->getAllocation();
5236     void *stencilCheckBufferData  = stencilCheckBufferAlloc.getHostPtr();
5237     invalidateAlloc(vkd, device, stencilCheckBufferAlloc);
5238 
5239     const auto iWidth           = static_cast<int>(m_params.imageExtent.width);
5240     const auto iHeight          = static_cast<int>(m_params.imageExtent.height);
5241     const auto colorTcuFormat   = mapVkFormat(colorFormat);
5242     const auto stencilTcuFormat = tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
5243 
5244     tcu::TextureLevel referenceLevel(colorTcuFormat, iWidth, iHeight);
5245     tcu::PixelBufferAccess referenceAccess = referenceLevel.getAccess();
5246     tcu::TextureLevel colorErrorLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
5247     tcu::PixelBufferAccess colorErrorAccess = colorErrorLevel.getAccess();
5248     tcu::TextureLevel stencilErrorLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
5249     tcu::PixelBufferAccess stencilErrorAccess = stencilErrorLevel.getAccess();
5250     tcu::ConstPixelBufferAccess colorAccess(colorTcuFormat, iWidth, iHeight, 1, colorCheckBufferData);
5251     tcu::ConstPixelBufferAccess stencilAccess(stencilTcuFormat, iWidth, iHeight, 1, stencilCheckBufferData);
5252     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
5253     const tcu::Vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
5254     const int expectedStencil = 2;
5255     bool colorFail            = false;
5256     bool stencilFail          = false;
5257 
5258     for (int y = 0; y < iHeight; ++y)
5259         for (int x = 0; x < iWidth; ++x)
5260         {
5261             const tcu::UVec4 colorValue = colorAccess.getPixelUint(x, y);
5262             const auto expectedPixel    = colors[y * iWidth + x];
5263             const tcu::UVec4 expectedValue(expectedPixel.x(), expectedPixel.y(), expectedPixel.z(), expectedPixel.w());
5264             const bool colorMismatch = (colorValue != expectedValue);
5265 
5266             const auto stencilValue    = stencilAccess.getPixStencil(x, y);
5267             const bool stencilMismatch = (stencilValue != expectedStencil);
5268 
5269             referenceAccess.setPixel(expectedValue, x, y);
5270             colorErrorAccess.setPixel((colorMismatch ? red : green), x, y);
5271             stencilErrorAccess.setPixel((stencilMismatch ? red : green), x, y);
5272 
5273             if (stencilMismatch)
5274                 stencilFail = true;
5275 
5276             if (colorMismatch)
5277                 colorFail = true;
5278         }
5279 
5280     if (colorFail || stencilFail)
5281     {
5282         auto &log = m_context.getTestContext().getLog();
5283         log << tcu::TestLog::ImageSet("Result", "") << tcu::TestLog::Image("ColorOutput", "", colorAccess)
5284             << tcu::TestLog::Image("ColorReference", "", referenceAccess)
5285             << tcu::TestLog::Image("ColorError", "", colorErrorAccess)
5286             << tcu::TestLog::Image("StencilError", "", stencilErrorAccess) << tcu::TestLog::EndImageSet;
5287         TCU_FAIL("Mismatched output and reference color or stencil; please check test log --");
5288     }
5289 
5290     return tcu::TestStatus::pass("Pass");
5291 }
5292 
initManyIndirectDrawsPrograms(SourceCollections & dst)5293 void initManyIndirectDrawsPrograms(SourceCollections &dst)
5294 {
5295     std::ostringstream vert;
5296     vert << "#version 460\n"
5297          << "layout (location=0) in vec4 inPos;\n"
5298          << "void main (void) {\n"
5299          << "    gl_PointSize = 1.0;\n"
5300          << "    gl_Position = inPos;\n"
5301          << "}\n";
5302     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
5303 
5304     std::ostringstream frag;
5305     frag << "#version 460\n"
5306          << "layout (location=0) out vec4 outColor;\n"
5307          << "void main (void) {\n"
5308          << "    outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
5309          << "}\n";
5310     dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
5311 }
5312 
manyIndirectDrawsTest(Context & context)5313 tcu::TestStatus manyIndirectDrawsTest(Context &context)
5314 {
5315     const auto &ctx = context.getContextCommonData();
5316     const tcu::IVec3 fbExtent(64, 64, 1);
5317     const auto vkExtent   = makeExtent3D(fbExtent);
5318     const auto floatExt   = fbExtent.cast<float>();
5319     const auto pixelCount = vkExtent.width * vkExtent.height;
5320     const auto fbFormat   = VK_FORMAT_R8G8B8A8_UNORM;
5321     const auto tcuFormat  = mapVkFormat(fbFormat);
5322     const auto fbUsage    = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
5323     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
5324     const tcu::Vec4 geomColor(0.0f, 0.0f, 1.0f, 1.0f); // Must match fragment shader.
5325     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
5326     const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
5327 
5328     // Color buffer with verification buffer.
5329     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
5330 
5331     // Vertices for each point.
5332     std::vector<tcu::Vec4> vertices;
5333     vertices.reserve(pixelCount);
5334     for (int y = 0; y < fbExtent.y(); ++y)
5335         for (int x = 0; x < fbExtent.x(); ++x)
5336         {
5337             const auto xCoord = ((static_cast<float>(x) + 0.5f) / floatExt.x()) * 2.0f - 1.0f;
5338             const auto yCoord = ((static_cast<float>(y) + 0.5f) / floatExt.y()) * 2.0f - 1.0f;
5339             vertices.push_back(tcu::Vec4(xCoord, yCoord, 0.0f, 1.0f));
5340         };
5341 
5342     // Vertex buffer
5343     const auto vbSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
5344     const auto vbInfo = makeBufferCreateInfo(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
5345     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vbInfo, MemoryRequirement::HostVisible);
5346     const auto vbAlloc  = vertexBuffer.getAllocation();
5347     void *vbData        = vbAlloc.getHostPtr();
5348     const auto vbOffset = static_cast<VkDeviceSize>(0);
5349 
5350     deMemcpy(vbData, de::dataOrNull(vertices), de::dataSize(vertices));
5351     flushAlloc(ctx.vkd, ctx.device, vbAlloc);
5352 
5353     std::vector<VkDrawIndirectCommand> indirectCommands;
5354     indirectCommands.reserve(pixelCount);
5355     const auto indirectCmdSize = static_cast<uint32_t>(sizeof(decltype(indirectCommands)::value_type));
5356 
5357     for (uint32_t i = 0u; i < pixelCount; ++i)
5358     {
5359         indirectCommands.push_back({
5360             1u, // uint32_t vertexCount;
5361             1u, // uint32_t instanceCount;
5362             i,  // uint32_t firstVertex;
5363             0u, // uint32_t firstInstance;
5364         });
5365     }
5366 
5367     // Indirect draw buffer.
5368     const auto ibSize = static_cast<VkDeviceSize>(de::dataSize(indirectCommands));
5369     const auto ibInfo = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
5370     BufferWithMemory indirectBuffer(ctx.vkd, ctx.device, ctx.allocator, ibInfo, MemoryRequirement::HostVisible);
5371     const auto ibAlloc = indirectBuffer.getAllocation();
5372     void *ibData       = ibAlloc.getHostPtr();
5373 
5374     deMemcpy(ibData, de::dataOrNull(indirectCommands), de::dataSize(indirectCommands));
5375     flushAlloc(ctx.vkd, ctx.device, ibAlloc);
5376 
5377     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
5378     const auto renderPass     = makeRenderPass(ctx.vkd, ctx.device, fbFormat);
5379     const auto framebuffer =
5380         makeFramebuffer(ctx.vkd, ctx.device, *renderPass, colorBuffer.getImageView(), vkExtent.width, vkExtent.height);
5381 
5382     // Modules.
5383     const auto &binaries  = context.getBinaryCollection();
5384     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
5385     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
5386 
5387     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
5388     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
5389 
5390     // Other default values work for the current setup, including the vertex input data format.
5391     const auto pipeline = makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout, *vertModule, VK_NULL_HANDLE,
5392                                                VK_NULL_HANDLE, VK_NULL_HANDLE, *fragModule, *renderPass, viewports,
5393                                                scissors, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
5394 
5395     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
5396     const auto cmdBuffer = *cmd.cmdBuffer;
5397     const auto secCmdBuffer =
5398         allocateCommandBuffer(ctx.vkd, ctx.device, *cmd.cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5399 
5400     beginSecondaryCommandBuffer(ctx.vkd, *secCmdBuffer, *renderPass, *framebuffer);
5401     ctx.vkd.cmdBindVertexBuffers(*secCmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
5402     ctx.vkd.cmdBindPipeline(*secCmdBuffer, bindPoint, *pipeline);
5403     for (uint32_t i = 0; i < pixelCount; ++i)
5404         ctx.vkd.cmdDrawIndirect(*secCmdBuffer, indirectBuffer.get(), static_cast<VkDeviceSize>(i * indirectCmdSize), 1u,
5405                                 indirectCmdSize);
5406     endCommandBuffer(ctx.vkd, *secCmdBuffer);
5407 
5408     beginCommandBuffer(ctx.vkd, cmdBuffer);
5409     beginRenderPass(ctx.vkd, cmdBuffer, *renderPass, *framebuffer, scissors.at(0u), clearColor,
5410                     VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
5411     ctx.vkd.cmdExecuteCommands(cmdBuffer, 1u, &(*secCmdBuffer));
5412     endRenderPass(ctx.vkd, cmdBuffer);
5413     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1),
5414                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
5415                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
5416                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
5417     endCommandBuffer(ctx.vkd, cmdBuffer);
5418     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
5419 
5420     // Verify color output.
5421     invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
5422     tcu::PixelBufferAccess resultAccess(tcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
5423 
5424     tcu::TextureLevel referenceLevel(tcuFormat, fbExtent.x(), fbExtent.y());
5425     auto referenceAccess = referenceLevel.getAccess();
5426     tcu::clear(referenceAccess, geomColor);
5427 
5428     auto &log = context.getTestContext().getLog();
5429     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold,
5430                                     tcu::COMPARE_LOG_ON_ERROR))
5431         return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
5432 
5433     return tcu::TestStatus::pass("Pass");
5434 }
5435 
5436 constexpr uint32_t kIndirectDispatchValueOffset = 1000000u;
5437 
initManyIndirectDispatchesPrograms(SourceCollections & dst)5438 void initManyIndirectDispatchesPrograms(SourceCollections &dst)
5439 {
5440     std::ostringstream comp;
5441     comp << "#version 460\n"
5442          << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
5443          << "layout (push_constant, std430) uniform PushConstantBlock { uint index; } pc;\n"
5444          << "layout (set=0, binding=0, std430) buffer OutputBlock { uint data[]; } outputValues;\n"
5445          << "void main (void) {\n"
5446          << "    outputValues.data[pc.index] += pc.index + " << kIndirectDispatchValueOffset << "u;\n"
5447          << "}\n";
5448     dst.glslSources.add("comp") << glu::ComputeSource(comp.str());
5449 }
5450 
checkManyIndirectDispatchesSupport(Context & context)5451 void checkManyIndirectDispatchesSupport(Context &context)
5452 {
5453     // The device must have support for a compute queue.
5454     // getComputeQueue() will throw NotSupportedError if the device doesn't have one.
5455     context.getComputeQueue();
5456 }
5457 
manyIndirectDispatchesTest(Context & context)5458 tcu::TestStatus manyIndirectDispatchesTest(Context &context)
5459 {
5460     const auto &ctx       = context.getContextCommonData();
5461     const auto descType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
5462     const auto bindPoint  = VK_PIPELINE_BIND_POINT_COMPUTE;
5463     const auto dataStages = VK_SHADER_STAGE_COMPUTE_BIT;
5464     const auto valueCount = 4096u;
5465     const auto qfIndex    = context.getComputeQueueFamilyIndex();
5466     const auto queue      = context.getComputeQueue();
5467 
5468     // Host-side buffer values.
5469     std::vector<uint32_t> bufferValues(valueCount, 0u);
5470 
5471     // Storage buffer.
5472     const auto sbSize = static_cast<VkDeviceSize>(de::dataSize(bufferValues));
5473     const auto sbInfo = makeBufferCreateInfo(sbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
5474     BufferWithMemory storageBuffer(ctx.vkd, ctx.device, ctx.allocator, sbInfo, MemoryRequirement::HostVisible);
5475     const auto sbAlloc  = storageBuffer.getAllocation();
5476     void *sbData        = sbAlloc.getHostPtr();
5477     const auto sbOffset = static_cast<VkDeviceSize>(0);
5478 
5479     deMemcpy(sbData, de::dataOrNull(bufferValues), de::dataSize(bufferValues));
5480     flushAlloc(ctx.vkd, ctx.device, sbAlloc);
5481 
5482     // Indirect dispatch buffer. We'll pretend to have 4096 indirect commands but all of them will launch 1 group with 1 invocation.
5483     const VkDispatchIndirectCommand defaultCommand{1u, 1u, 1u};
5484     const std::vector<VkDispatchIndirectCommand> indirectCommands(valueCount, defaultCommand);
5485 
5486     const auto ibSize = static_cast<VkDeviceSize>(de::dataSize(indirectCommands));
5487     const auto ibInfo = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
5488     BufferWithMemory indirectBuffer(ctx.vkd, ctx.device, ctx.allocator, ibInfo, MemoryRequirement::HostVisible);
5489     const auto ibAlloc = indirectBuffer.getAllocation();
5490     void *ibData       = ibAlloc.getHostPtr();
5491 
5492     deMemcpy(ibData, de::dataOrNull(indirectCommands), de::dataSize(indirectCommands));
5493     flushAlloc(ctx.vkd, ctx.device, ibAlloc);
5494 
5495     // Descriptor pool, set, layout, etc.
5496     DescriptorPoolBuilder poolBuilder;
5497     poolBuilder.addType(descType);
5498     const auto descriptorPool =
5499         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
5500 
5501     DescriptorSetLayoutBuilder layoutBuilder;
5502     layoutBuilder.addSingleBinding(descType, dataStages);
5503     const auto setLayout     = layoutBuilder.build(ctx.vkd, ctx.device);
5504     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
5505 
5506     DescriptorSetUpdateBuilder updateBuilder;
5507     const auto dbDescInfo = makeDescriptorBufferInfo(storageBuffer.get(), sbOffset, sbSize);
5508     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &dbDescInfo);
5509     updateBuilder.update(ctx.vkd, ctx.device);
5510 
5511     // Push constants.
5512     const auto pcSize  = static_cast<uint32_t>(sizeof(uint32_t));
5513     const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
5514 
5515     // Layout and pipeline.
5516     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, *setLayout, &pcRange);
5517     const auto &binaries      = context.getBinaryCollection();
5518     const auto compModule     = createShaderModule(ctx.vkd, ctx.device, binaries.get("comp"));
5519     const auto pipeline       = makeComputePipeline(ctx.vkd, ctx.device, *pipelineLayout, *compModule);
5520 
5521     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, qfIndex);
5522     const auto cmdBuffer = *cmd.cmdBuffer;
5523     const auto secCmdBufferPtr =
5524         allocateCommandBuffer(ctx.vkd, ctx.device, *cmd.cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5525     const auto secCmdBuffer = *secCmdBufferPtr;
5526 
5527     beginSecondaryCommandBuffer(ctx.vkd, secCmdBuffer);
5528     ctx.vkd.cmdBindPipeline(secCmdBuffer, bindPoint, *pipeline);
5529     ctx.vkd.cmdBindDescriptorSets(secCmdBuffer, bindPoint, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
5530     for (uint32_t i = 0; i < valueCount; ++i)
5531     {
5532         ctx.vkd.cmdPushConstants(secCmdBuffer, *pipelineLayout, dataStages, 0u, pcSize, &i);
5533         const auto dispatchOffset = static_cast<VkDeviceSize>(i * sizeof(VkDispatchIndirectCommand));
5534         ctx.vkd.cmdDispatchIndirect(secCmdBuffer, indirectBuffer.get(), dispatchOffset);
5535     }
5536     endCommandBuffer(ctx.vkd, secCmdBuffer);
5537 
5538     beginCommandBuffer(ctx.vkd, cmdBuffer);
5539     ctx.vkd.cmdExecuteCommands(cmdBuffer, 1u, &secCmdBuffer);
5540     {
5541         const auto compute2Host = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5542         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
5543                                  &compute2Host);
5544     }
5545     endCommandBuffer(ctx.vkd, cmdBuffer);
5546     submitCommandsAndWait(ctx.vkd, ctx.device, queue, cmdBuffer);
5547 
5548     // Verify values.
5549     std::vector<uint32_t> outputValues(valueCount, 0u);
5550     invalidateAlloc(ctx.vkd, ctx.device, sbAlloc);
5551     deMemcpy(outputValues.data(), sbData, de::dataSize(outputValues));
5552 
5553     for (uint32_t i = 0u; i < valueCount; ++i)
5554     {
5555         const auto refValue = bufferValues[i] + i + kIndirectDispatchValueOffset;
5556         if (outputValues[i] != refValue)
5557         {
5558             std::ostringstream msg;
5559             msg << "Unexpected value found at position " << i << ": expected " << refValue << " but found "
5560                 << outputValues[i];
5561             TCU_FAIL(msg.str());
5562         }
5563     }
5564 
5565     return tcu::TestStatus::pass("Pass");
5566 }
5567 
5568 struct IndirectDispatchAlignmentParams
5569 {
5570     uint32_t memOffset;
5571     uint32_t dispatchOffset;
5572 };
5573 
5574 class IndirectDispatchAlignmentInstance : public vkt::TestInstance
5575 {
5576 public:
IndirectDispatchAlignmentInstance(Context & context,const IndirectDispatchAlignmentParams & params)5577     IndirectDispatchAlignmentInstance(Context &context, const IndirectDispatchAlignmentParams &params)
5578         : vkt::TestInstance(context)
5579         , m_params(params)
5580     {
5581     }
~IndirectDispatchAlignmentInstance(void)5582     virtual ~IndirectDispatchAlignmentInstance(void)
5583     {
5584     }
5585 
5586     tcu::TestStatus iterate(void) override;
5587 
5588 protected:
5589     const IndirectDispatchAlignmentParams m_params;
5590 };
5591 
5592 class IndirectDispatchAlignmentCase : public vkt::TestCase
5593 {
5594 public:
IndirectDispatchAlignmentCase(tcu::TestContext & testCtx,const std::string & name,const IndirectDispatchAlignmentParams & params)5595     IndirectDispatchAlignmentCase(tcu::TestContext &testCtx, const std::string &name,
5596                                   const IndirectDispatchAlignmentParams &params)
5597         : vkt::TestCase(testCtx, name)
5598         , m_params(params)
5599     {
5600     }
~IndirectDispatchAlignmentCase(void)5601     virtual ~IndirectDispatchAlignmentCase(void)
5602     {
5603     }
5604 
5605     void initPrograms(vk::SourceCollections &programCollection) const override;
5606     TestInstance *createInstance(Context &context) const override;
5607     void checkSupport(Context &context) const override;
5608 
5609 protected:
5610     const IndirectDispatchAlignmentParams m_params;
5611 };
5612 
checkSupport(Context & context) const5613 void IndirectDispatchAlignmentCase::checkSupport(Context &context) const
5614 {
5615     // Will throw NotSupportedError if not found.
5616     context.getComputeQueue();
5617 }
5618 
initPrograms(vk::SourceCollections & programCollection) const5619 void IndirectDispatchAlignmentCase::initPrograms(vk::SourceCollections &programCollection) const
5620 {
5621     std::ostringstream comp;
5622     comp << "#version 460\n"
5623          << "layout (local_size_x=64, local_size_y=1, local_size_z=1) in;\n"
5624          << "layout (set=0, binding=0, std430) buffer OutputBlock { uint data[64]; } outputValues;\n"
5625          << "void main (void) {\n"
5626          << "    outputValues.data[gl_LocalInvocationIndex] += gl_LocalInvocationIndex + "
5627          << kIndirectDispatchValueOffset << "u;\n"
5628          << "}\n";
5629     programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
5630 }
5631 
createInstance(Context & context) const5632 TestInstance *IndirectDispatchAlignmentCase::createInstance(Context &context) const
5633 {
5634     return new IndirectDispatchAlignmentInstance(context, m_params);
5635 }
5636 
iterate(void)5637 tcu::TestStatus IndirectDispatchAlignmentInstance::iterate(void)
5638 {
5639     const auto &ctx       = m_context.getContextCommonData();
5640     const auto descType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
5641     const auto bindPoint  = VK_PIPELINE_BIND_POINT_COMPUTE;
5642     const auto dataStages = VK_SHADER_STAGE_COMPUTE_BIT;
5643     const auto valueCount = 64u; // Must match compute shader.
5644     const auto qfIndex    = m_context.getComputeQueueFamilyIndex();
5645     const auto queue      = m_context.getComputeQueue();
5646     auto &log             = m_context.getTestContext().getLog();
5647 
5648     // Host-side buffer values.
5649     std::vector<uint32_t> bufferValues(valueCount, 0u);
5650 
5651     // Storage buffer.
5652     const auto sbSize = static_cast<VkDeviceSize>(de::dataSize(bufferValues));
5653     const auto sbInfo = makeBufferCreateInfo(sbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
5654     BufferWithMemory storageBuffer(ctx.vkd, ctx.device, ctx.allocator, sbInfo, MemoryRequirement::HostVisible);
5655     const auto sbAlloc  = storageBuffer.getAllocation();
5656     void *sbData        = sbAlloc.getHostPtr();
5657     const auto sbOffset = static_cast<VkDeviceSize>(0);
5658 
5659     deMemcpy(sbData, de::dataOrNull(bufferValues), de::dataSize(bufferValues));
5660     flushAlloc(ctx.vkd, ctx.device, sbAlloc);
5661 
5662     // Indirect dispatch buffer contents.
5663     const VkDispatchIndirectCommand defaultCommand{1u, 1u, 1u};
5664     const std::vector<VkDispatchIndirectCommand> indirectCommands(1u, defaultCommand);
5665 
5666     // Note the calculated indirect buffer size takes into account the dispatche offset.
5667     const auto ibSize         = static_cast<VkDeviceSize>(m_params.dispatchOffset + de::dataSize(indirectCommands));
5668     const auto ibInfo         = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
5669     const auto indirectBuffer = makeBuffer(ctx.vkd, ctx.device, ibInfo);
5670 
5671     // Allocate more memory if needed and bind with an offset.
5672     const auto memReqs   = getBufferMemoryRequirements(ctx.vkd, ctx.device, *indirectBuffer);
5673     const auto memOffset = de::roundUp(static_cast<VkDeviceSize>(m_params.memOffset), memReqs.alignment);
5674 
5675     log << tcu::TestLog::Message << "Test parameters: memoryOffset=" << m_params.memOffset
5676         << " dispatchOffset=" << m_params.dispatchOffset << tcu::TestLog::EndMessage;
5677     log << tcu::TestLog::Message << "Buffer memory requirements: size=" << memReqs.size
5678         << " alignment=" << memReqs.alignment << tcu::TestLog::EndMessage;
5679     log << tcu::TestLog::Message << "Used memory offset: " << memOffset << tcu::TestLog::EndMessage;
5680 
5681     const VkMemoryRequirements allocationRequirements = {
5682         memOffset + memReqs.size, // VkDeviceSize size;
5683         memReqs.alignment,        // VkDeviceSize alignment;
5684         memReqs.memoryTypeBits,   // uint32_t memoryTypeBits;
5685     };
5686     const auto ibMemory = ctx.allocator.allocate(allocationRequirements, MemoryRequirement::HostVisible);
5687     ctx.vkd.bindBufferMemory(ctx.device, *indirectBuffer, ibMemory->getMemory(), memOffset);
5688 
5689     // Copy data to the buffer taking into account the dispatch offset.
5690     char *ibData = reinterpret_cast<char *>(ibMemory->getHostPtr()) + static_cast<size_t>(memOffset);
5691     deMemcpy(ibData + m_params.dispatchOffset, de::dataOrNull(indirectCommands), de::dataSize(indirectCommands));
5692     flushAlloc(ctx.vkd, ctx.device, *ibMemory);
5693 
5694     // Descriptor pool, set, layout, etc.
5695     DescriptorPoolBuilder poolBuilder;
5696     poolBuilder.addType(descType);
5697     const auto descriptorPool =
5698         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
5699 
5700     DescriptorSetLayoutBuilder layoutBuilder;
5701     layoutBuilder.addSingleBinding(descType, dataStages);
5702     const auto setLayout     = layoutBuilder.build(ctx.vkd, ctx.device);
5703     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
5704 
5705     DescriptorSetUpdateBuilder updateBuilder;
5706     const auto dbDescInfo = makeDescriptorBufferInfo(storageBuffer.get(), sbOffset, sbSize);
5707     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &dbDescInfo);
5708     updateBuilder.update(ctx.vkd, ctx.device);
5709 
5710     // Layout and pipeline.
5711     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, *setLayout);
5712     const auto &binaries      = m_context.getBinaryCollection();
5713     const auto compModule     = createShaderModule(ctx.vkd, ctx.device, binaries.get("comp"));
5714     const auto pipeline       = makeComputePipeline(ctx.vkd, ctx.device, *pipelineLayout, *compModule);
5715 
5716     // To make it more interesting, we'll also use secondary command buffers.
5717     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, qfIndex);
5718     const auto cmdBuffer = *cmd.cmdBuffer;
5719     const auto secCmdBufferPtr =
5720         allocateCommandBuffer(ctx.vkd, ctx.device, *cmd.cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5721     const auto secCmdBuffer = *secCmdBufferPtr;
5722 
5723     beginSecondaryCommandBuffer(ctx.vkd, secCmdBuffer);
5724     ctx.vkd.cmdBindPipeline(secCmdBuffer, bindPoint, *pipeline);
5725     ctx.vkd.cmdBindDescriptorSets(secCmdBuffer, bindPoint, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
5726     const auto dispatchOffset = m_params.dispatchOffset;
5727     ctx.vkd.cmdDispatchIndirect(secCmdBuffer, indirectBuffer.get(), dispatchOffset);
5728     endCommandBuffer(ctx.vkd, secCmdBuffer);
5729 
5730     beginCommandBuffer(ctx.vkd, cmdBuffer);
5731     ctx.vkd.cmdExecuteCommands(cmdBuffer, 1u, &secCmdBuffer);
5732     {
5733         const auto compute2Host = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
5734         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
5735                                  &compute2Host);
5736     }
5737     endCommandBuffer(ctx.vkd, cmdBuffer);
5738     submitCommandsAndWait(ctx.vkd, ctx.device, queue, cmdBuffer);
5739 
5740     // Verify values.
5741     std::vector<uint32_t> outputValues(valueCount, 0u);
5742     invalidateAlloc(ctx.vkd, ctx.device, sbAlloc);
5743     deMemcpy(outputValues.data(), sbData, de::dataSize(outputValues));
5744 
5745     for (uint32_t i = 0u; i < valueCount; ++i)
5746     {
5747         const auto refValue = bufferValues[i] + i + kIndirectDispatchValueOffset;
5748         if (outputValues[i] != refValue)
5749         {
5750             std::ostringstream msg;
5751             msg << "Unexpected value found at position " << i << ": expected " << refValue << " but found "
5752                 << outputValues[i];
5753             TCU_FAIL(msg.str());
5754         }
5755     }
5756 
5757     return tcu::TestStatus::pass("Pass");
5758 }
5759 
5760 } // namespace
5761 
createCommandBuffersTests(tcu::TestContext & testCtx)5762 tcu::TestCaseGroup *createCommandBuffersTests(tcu::TestContext &testCtx)
5763 {
5764     de::MovePtr<tcu::TestCaseGroup> commandBuffersTests(new tcu::TestCaseGroup(testCtx, "command_buffers"));
5765 
5766     /* 19.1. Command Pools (5.1 in VK 1.0 Spec) */
5767     addFunctionCase(commandBuffersTests.get(), "pool_create_null_params", createPoolNullParamsTest);
5768 #ifndef CTS_USES_VULKANSC
5769     // VkAllocationCallbacks must be NULL in Vulkan SC
5770     addFunctionCase(commandBuffersTests.get(), "pool_create_non_null_allocator", createPoolNonNullAllocatorTest);
5771 #endif // CTS_USES_VULKANSC
5772     addFunctionCase(commandBuffersTests.get(), "pool_create_transient_bit", createPoolTransientBitTest);
5773     addFunctionCase(commandBuffersTests.get(), "pool_create_reset_bit", createPoolResetBitTest);
5774 #ifndef CTS_USES_VULKANSC
5775     addFunctionCase(commandBuffersTests.get(), "pool_reset_release_res", resetPoolReleaseResourcesBitTest);
5776 #endif // CTS_USES_VULKANSC
5777     addFunctionCase(commandBuffersTests.get(), "pool_reset_no_flags_res", resetPoolNoFlagsTest);
5778 #ifndef CTS_USES_VULKANSC
5779     addFunctionCase(commandBuffersTests.get(), "pool_reset_reuse", checkEventSupport, resetPoolReuseTest);
5780 #endif // CTS_USES_VULKANSC
5781     /* 19.2. Command Buffer Lifetime (5.2 in VK 1.0 Spec) */
5782     addFunctionCase(commandBuffersTests.get(), "allocate_single_primary", allocatePrimaryBufferTest);
5783     addFunctionCase(commandBuffersTests.get(), "allocate_many_primary", allocateManyPrimaryBuffersTest);
5784     addFunctionCase(commandBuffersTests.get(), "allocate_single_secondary", allocateSecondaryBufferTest);
5785     addFunctionCase(commandBuffersTests.get(), "allocate_many_secondary", allocateManySecondaryBuffersTest);
5786     addFunctionCase(commandBuffersTests.get(), "execute_small_primary", checkEventSupport, executePrimaryBufferTest);
5787     addFunctionCase(commandBuffersTests.get(), "execute_large_primary", checkEventSupport,
5788                     executeLargePrimaryBufferTest);
5789     addFunctionCase(commandBuffersTests.get(), "reset_implicit", checkEventSupport, resetBufferImplicitlyTest);
5790 #ifndef CTS_USES_VULKANSC
5791     addFunctionCase(commandBuffersTests.get(), "trim_command_pool", checkEventSupport, trimCommandPoolTest,
5792                     VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5793     addFunctionCase(commandBuffersTests.get(), "trim_command_pool_secondary", checkEventSupport, trimCommandPoolTest,
5794                     VK_COMMAND_BUFFER_LEVEL_SECONDARY);
5795 #endif // CTS_USES_VULKANSC
5796     /* 19.3. Command Buffer Recording (5.3 in VK 1.0 Spec) */
5797     addFunctionCase(commandBuffersTests.get(), "record_single_primary", checkEventSupport,
5798                     recordSinglePrimaryBufferTest);
5799     addFunctionCase(commandBuffersTests.get(), "record_many_primary", checkEventSupport, recordLargePrimaryBufferTest);
5800     addFunctionCase(commandBuffersTests.get(), "record_single_secondary",
5801                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, recordSingleSecondaryBufferTest);
5802     addFunctionCase(commandBuffersTests.get(), "record_many_secondary",
5803                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, recordLargeSecondaryBufferTest);
5804     {
5805         uint32_t seed          = 1614182419u;
5806         const auto smallExtent = makeExtent3D(128u, 128u, 1u);
5807         const auto largeExtent = makeExtent3D(512u, 256u, 1u);
5808 
5809         commandBuffersTests->addChild(
5810             new ManyDrawsCase(testCtx, "record_many_draws_primary_1",
5811                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY, smallExtent, seed++)));
5812         commandBuffersTests->addChild(
5813             new ManyDrawsCase(testCtx, "record_many_draws_primary_2",
5814                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY, largeExtent, seed++)));
5815         commandBuffersTests->addChild(
5816             new ManyDrawsCase(testCtx, "record_many_draws_secondary_1",
5817                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY, smallExtent, seed++)));
5818         commandBuffersTests->addChild(
5819             new ManyDrawsCase(testCtx, "record_many_draws_secondary_2",
5820                               ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY, largeExtent, seed++)));
5821     }
5822     addFunctionCase(commandBuffersTests.get(), "submit_twice_primary", checkEventSupport, submitPrimaryBufferTwiceTest);
5823     addFunctionCase(commandBuffersTests.get(), "submit_twice_secondary",
5824                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, submitSecondaryBufferTwiceTest);
5825     addFunctionCase(commandBuffersTests.get(), "record_one_time_submit_primary", checkEventSupport,
5826                     oneTimeSubmitFlagPrimaryBufferTest);
5827     addFunctionCase(commandBuffersTests.get(), "record_one_time_submit_secondary",
5828                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, oneTimeSubmitFlagSecondaryBufferTest);
5829     addFunctionCase(commandBuffersTests.get(), "render_pass_continue", renderPassContinueTest, true);
5830     addFunctionCase(commandBuffersTests.get(), "nested_render_pass_continue",
5831                     checkNestedCommandBufferRenderPassContinueSupport, renderPassContinueNestedTest, true);
5832     addFunctionCase(commandBuffersTests.get(), "render_pass_continue_no_fb",
5833                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1, renderPassContinueTest, false);
5834     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_secondary_one_primary",
5835                                 checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport,
5836                                 genComputeIncrementSource, simultaneousUseSecondaryBufferOnePrimaryBufferTest);
5837     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_secondary_two_primary",
5838                                 checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport,
5839                                 genComputeIncrementSource, simultaneousUseSecondaryBufferTwoPrimaryBuffersTest);
5840     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_nested",
5841                                 checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport,
5842                                 genComputeIncrementSource, simultaneousUseNestedSecondaryBufferTest);
5843     addFunctionCaseWithPrograms(commandBuffersTests.get(), "record_simul_use_twice_nested",
5844                                 checkSimultaneousUseAndNestedCommandBufferNullFramebufferSupport,
5845                                 genComputeIncrementSource, simultaneousUseNestedSecondaryBufferTwiceTest);
5846     addFunctionCase(commandBuffersTests.get(), "record_query_precise_w_flag",
5847                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport, recordBufferQueryPreciseWithFlagTest);
5848     addFunctionCase(commandBuffersTests.get(), "record_query_imprecise_w_flag",
5849                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport,
5850                     recordBufferQueryImpreciseWithFlagTest);
5851     addFunctionCase(commandBuffersTests.get(), "record_query_imprecise_wo_flag",
5852                     checkSecondaryCommandBufferNullOrImagelessFramebufferSupport,
5853                     recordBufferQueryImpreciseWithoutFlagTest);
5854     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_random",
5855                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5856                                 BadInheritanceInfoCase::RANDOM_PTR);
5857     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_random_cont",
5858                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5859                                 BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION);
5860     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_random_data",
5861                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5862                                 BadInheritanceInfoCase::RANDOM_DATA_PTR);
5863     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_invalid_type",
5864                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5865                                 BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE);
5866     addFunctionCaseWithPrograms(commandBuffersTests.get(), "bad_inheritance_info_valid_nonsense_type",
5867                                 genComputeIncrementSourceBadInheritance, badInheritanceInfoTest,
5868                                 BadInheritanceInfoCase::VALID_NONSENSE_TYPE);
5869     /* 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) */
5870     addFunctionCase(commandBuffersTests.get(), "submit_count_non_zero", checkEventSupport, submitBufferCountNonZero);
5871     addFunctionCase(commandBuffersTests.get(), "submit_count_equal_zero", checkEventSupport,
5872                     submitBufferCountEqualZero);
5873     addFunctionCase(commandBuffersTests.get(), "submit_wait_single_semaphore", checkEventSupport,
5874                     submitBufferWaitSingleSemaphore);
5875     addFunctionCase(commandBuffersTests.get(), "submit_wait_many_semaphores", checkEventSupport,
5876                     submitBufferWaitManySemaphores);
5877     addFunctionCase(commandBuffersTests.get(), "submit_null_fence", checkEventSupport, submitBufferNullFence);
5878     addFunctionCase(commandBuffersTests.get(), "submit_two_buffers_one_buffer_null_with_fence", checkEventSupport,
5879                     submitTwoBuffersOneBufferNullWithFence);
5880     /* 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) */
5881     addFunctionCase(commandBuffersTests.get(), "secondary_execute",
5882                     checkEventAndSecondaryCommandBufferNullFramebufferSupport, executeSecondaryBufferTest);
5883     addFunctionCase(commandBuffersTests.get(), "secondary_execute_twice",
5884                     checkEventAndTimelineSemaphoreAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport,
5885                     executeSecondaryBufferTwiceTest);
5886     /* 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) */
5887     addFunctionCaseWithPrograms(commandBuffersTests.get(), "order_bind_pipeline", genComputeSource,
5888                                 orderBindPipelineTest);
5889     /* Verify untested transitions between command buffer states */
5890     addFunctionCase(commandBuffersTests.get(), "recording_to_ininitial", executeStateTransitionTest,
5891                     STT_RECORDING_TO_INITIAL);
5892     addFunctionCase(commandBuffersTests.get(), "executable_to_ininitial", executeStateTransitionTest,
5893                     STT_EXECUTABLE_TO_INITIAL);
5894     addFunctionCase(commandBuffersTests.get(), "recording_to_invalid", executeStateTransitionTest,
5895                     STT_RECORDING_TO_INVALID);
5896     addFunctionCase(commandBuffersTests.get(), "executable_to_invalid", executeStateTransitionTest,
5897                     STT_EXECUTABLE_TO_INVALID);
5898     addFunctionCaseWithPrograms(commandBuffersTests.get(), "many_indirect_draws_on_secondary",
5899                                 initManyIndirectDrawsPrograms, manyIndirectDrawsTest);
5900     addFunctionCaseWithPrograms(commandBuffersTests.get(), "many_indirect_disps_on_secondary",
5901                                 checkManyIndirectDispatchesSupport, initManyIndirectDispatchesPrograms,
5902                                 manyIndirectDispatchesTest);
5903 
5904     addFunctionCase(commandBuffersTests.get(), "nested_execute", checkNestedCommandBufferSupport,
5905                     executeNestedBufferTest);
5906     addFunctionCase(commandBuffersTests.get(), "nested_execute_multiple_levels", checkNestedCommandBufferDepthSupport,
5907                     executeMultipleLevelsNestedBufferTest);
5908 
5909     // Test indirect dispatches with different offsets.
5910     {
5911         auto testGroup = commandBuffersTests.get();
5912 
5913         const std::vector<uint32_t> offsetsToTest{0u, 4u, 8u, 12u, 16u, 20u, 24u, 28u};
5914 
5915         for (const auto memOffset : offsetsToTest)
5916             for (const auto dispatchOffset : offsetsToTest)
5917             {
5918                 IndirectDispatchAlignmentParams params{memOffset, dispatchOffset};
5919                 const std::string testName = "indirect_compute_dispatch_offsets_" + std::to_string(memOffset) + "_" +
5920                                              std::to_string(dispatchOffset);
5921                 testGroup->addChild(new IndirectDispatchAlignmentCase(testCtx, testName, params));
5922             }
5923     }
5924 
5925     return commandBuffersTests.release();
5926 }
5927 
5928 } // namespace api
5929 } // namespace vkt
5930