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 ¶ms);
~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 ¶ms);
~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 ¶ms)
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 ¶ms)
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, ©Region);
5128 vkd.cmdCopyBuffer(primaryCmdBuffer, testData.backBuffers.stagingBuffer->get(),
5129 testData.backBuffers.vertexBuffer->get(), 1u, ©Region);
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 ¶ms)
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 ¶ms)
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