1/*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 *
5 * based in part on anv and radv which are:
6 * Copyright © 2015 Intel Corporation
7 * Copyright © 2016 Red Hat.
8 * Copyright © 2016 Bas Nieuwenhuizen
9 */
10
11#include "vn_command_buffer.h"
12
13#include "venus-protocol/vn_protocol_driver_command_buffer.h"
14#include "venus-protocol/vn_protocol_driver_command_pool.h"
15
16#include "vn_device.h"
17#include "vn_image.h"
18#include "vn_render_pass.h"
19
20#define VN_CMD_ENQUEUE(cmd_name, commandBuffer, ...)                         \
21   do {                                                                      \
22      struct vn_command_buffer *_cmd =                                       \
23         vn_command_buffer_from_handle(commandBuffer);                       \
24      size_t _cmd_size = vn_sizeof_##cmd_name(commandBuffer, ##__VA_ARGS__); \
25                                                                             \
26      if (vn_cs_encoder_reserve(&_cmd->cs, _cmd_size))                       \
27         vn_encode_##cmd_name(&_cmd->cs, 0, commandBuffer, ##__VA_ARGS__);   \
28      else                                                                   \
29         _cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;                      \
30   } while (0)
31
32static bool
33vn_image_memory_barrier_has_present_src(
34   const VkImageMemoryBarrier *img_barriers, uint32_t count)
35{
36   for (uint32_t i = 0; i < count; i++) {
37      if (img_barriers[i].oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ||
38          img_barriers[i].newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
39         return true;
40   }
41   return false;
42}
43
44static VkImageMemoryBarrier *
45vn_cmd_get_image_memory_barriers(struct vn_command_buffer *cmd,
46                                 uint32_t count)
47{
48   /* avoid shrinking in case of non efficient reallocation implementation */
49   if (count > cmd->builder.image_barrier_count) {
50      size_t size = sizeof(VkImageMemoryBarrier) * count;
51      VkImageMemoryBarrier *img_barriers =
52         vk_realloc(&cmd->allocator, cmd->builder.image_barriers, size,
53                    VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
54      if (!img_barriers)
55         return NULL;
56
57      /* update upon successful reallocation */
58      cmd->builder.image_barrier_count = count;
59      cmd->builder.image_barriers = img_barriers;
60   }
61
62   return cmd->builder.image_barriers;
63}
64
65/* About VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, the spec says
66 *
67 *    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR must only be used for presenting a
68 *    presentable image for display. A swapchain's image must be transitioned
69 *    to this layout before calling vkQueuePresentKHR, and must be
70 *    transitioned away from this layout after calling vkAcquireNextImageKHR.
71 *
72 * That allows us to treat the layout internally as
73 *
74 *  - VK_IMAGE_LAYOUT_GENERAL
75 *  - VK_QUEUE_FAMILY_FOREIGN_EXT has the ownership, if the image is not a
76 *    prime blit source
77 *
78 * while staying performant.
79 *
80 * About queue family ownerships, the spec says
81 *
82 *    A queue family can take ownership of an image subresource or buffer
83 *    range of a resource created with VK_SHARING_MODE_EXCLUSIVE, without an
84 *    ownership transfer, in the same way as for a resource that was just
85 *    created; however, taking ownership in this way has the effect that the
86 *    contents of the image subresource or buffer range are undefined.
87 *
88 * It is unclear if that is applicable to external resources, which supposedly
89 * have the same semantics
90 *
91 *    Binding a resource to a memory object shared between multiple Vulkan
92 *    instances or other APIs does not change the ownership of the underlying
93 *    memory. The first entity to access the resource implicitly acquires
94 *    ownership. Accessing a resource backed by memory that is owned by a
95 *    particular instance or API has the same semantics as accessing a
96 *    VK_SHARING_MODE_EXCLUSIVE resource[...]
97 *
98 * We should get the spec clarified, or get rid of this completely broken code
99 * (TODO).
100 *
101 * Assuming a queue family can acquire the ownership implicitly when the
102 * contents are not needed, we do not need to worry about
103 * VK_IMAGE_LAYOUT_UNDEFINED.  We can use VK_IMAGE_LAYOUT_PRESENT_SRC_KHR as
104 * the sole signal to trigger queue family ownership transfers.
105 *
106 * When the image has VK_SHARING_MODE_CONCURRENT, we can, and are required to,
107 * use VK_QUEUE_FAMILY_IGNORED as the other queue family whether we are
108 * transitioning to or from VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.
109 *
110 * When the image has VK_SHARING_MODE_EXCLUSIVE, we have to work out who the
111 * other queue family is.  It is easier when the barrier does not also define
112 * a queue family ownership transfer (i.e., srcQueueFamilyIndex equals to
113 * dstQueueFamilyIndex).  The other queue family must be the queue family the
114 * command buffer was allocated for.
115 *
116 * When the barrier also defines a queue family ownership transfer, it is
117 * submitted both to the source queue family to release the ownership and to
118 * the destination queue family to acquire the ownership.  Depending on
119 * whether the barrier transitions to or from VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
120 * we are only interested in the ownership release or acquire respectively and
121 * should be careful to avoid double releases/acquires.
122 *
123 * I haven't followed all transition paths mentally to verify the correctness.
124 * I likely also violate some VUs or miss some cases below.  They are
125 * hopefully fixable and are left as TODOs.
126 */
127static void
128vn_cmd_fix_image_memory_barrier(const struct vn_command_buffer *cmd,
129                                const VkImageMemoryBarrier *src_barrier,
130                                VkImageMemoryBarrier *out_barrier)
131{
132   const struct vn_image *img = vn_image_from_handle(src_barrier->image);
133
134   *out_barrier = *src_barrier;
135
136   /* no fix needed */
137   if (out_barrier->oldLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
138       out_barrier->newLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
139      return;
140
141   assert(img->wsi.is_wsi);
142
143   if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
144      return;
145
146   /* prime blit src or no layout transition */
147   if (img->wsi.is_prime_blit_src ||
148       out_barrier->oldLayout == out_barrier->newLayout) {
149      if (out_barrier->oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
150         out_barrier->oldLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
151      if (out_barrier->newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
152         out_barrier->newLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
153      return;
154   }
155
156   if (out_barrier->oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
157      out_barrier->oldLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
158
159      /* no availability operation needed */
160      out_barrier->srcAccessMask = 0;
161
162      const uint32_t dst_qfi = out_barrier->dstQueueFamilyIndex;
163      if (img->sharing_mode == VK_SHARING_MODE_CONCURRENT) {
164         out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
165         out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
166      } else if (dst_qfi == out_barrier->srcQueueFamilyIndex ||
167                 dst_qfi == cmd->queue_family_index) {
168         out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
169         out_barrier->dstQueueFamilyIndex = cmd->queue_family_index;
170      } else {
171         /* The barrier also defines a queue family ownership transfer, and
172          * this is the one that gets submitted to the source queue family to
173          * release the ownership.  Skip both the transfer and the transition.
174          */
175         out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
176         out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
177         out_barrier->newLayout = out_barrier->oldLayout;
178      }
179   } else {
180      out_barrier->newLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
181
182      /* no visibility operation needed */
183      out_barrier->dstAccessMask = 0;
184
185      const uint32_t src_qfi = out_barrier->srcQueueFamilyIndex;
186      if (img->sharing_mode == VK_SHARING_MODE_CONCURRENT) {
187         out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
188         out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
189      } else if (src_qfi == out_barrier->dstQueueFamilyIndex ||
190                 src_qfi == cmd->queue_family_index) {
191         out_barrier->srcQueueFamilyIndex = cmd->queue_family_index;
192         out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
193      } else {
194         /* The barrier also defines a queue family ownership transfer, and
195          * this is the one that gets submitted to the destination queue
196          * family to acquire the ownership.  Skip both the transfer and the
197          * transition.
198          */
199         out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
200         out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
201         out_barrier->oldLayout = out_barrier->newLayout;
202      }
203   }
204}
205
206static const VkImageMemoryBarrier *
207vn_cmd_wait_events_fix_image_memory_barriers(
208   struct vn_command_buffer *cmd,
209   const VkImageMemoryBarrier *src_barriers,
210   uint32_t count,
211   uint32_t *out_transfer_count)
212{
213   *out_transfer_count = 0;
214
215   if (cmd->builder.render_pass ||
216       !vn_image_memory_barrier_has_present_src(src_barriers, count))
217      return src_barriers;
218
219   VkImageMemoryBarrier *img_barriers =
220      vn_cmd_get_image_memory_barriers(cmd, count * 2);
221   if (!img_barriers) {
222      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
223      return src_barriers;
224   }
225
226   /* vkCmdWaitEvents cannot be used for queue family ownership transfers.
227    * Nothing appears to be said about the submission order of image memory
228    * barriers in the same array.  We take the liberty to move queue family
229    * ownership transfers to the tail.
230    */
231   VkImageMemoryBarrier *transfer_barriers = img_barriers + count;
232   uint32_t transfer_count = 0;
233   uint32_t valid_count = 0;
234   for (uint32_t i = 0; i < count; i++) {
235      VkImageMemoryBarrier *img_barrier = &img_barriers[valid_count];
236      vn_cmd_fix_image_memory_barrier(cmd, &src_barriers[i], img_barrier);
237
238      if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
239         valid_count++;
240         continue;
241      }
242
243      if (img_barrier->srcQueueFamilyIndex ==
244          img_barrier->dstQueueFamilyIndex) {
245         valid_count++;
246      } else {
247         transfer_barriers[transfer_count++] = *img_barrier;
248      }
249   }
250
251   assert(valid_count + transfer_count == count);
252   if (transfer_count) {
253      /* copy back to the tail */
254      memcpy(&img_barriers[valid_count], transfer_barriers,
255             sizeof(*transfer_barriers) * transfer_count);
256      *out_transfer_count = transfer_count;
257   }
258
259   return img_barriers;
260}
261
262static const VkImageMemoryBarrier *
263vn_cmd_pipeline_barrier_fix_image_memory_barriers(
264   struct vn_command_buffer *cmd,
265   const VkImageMemoryBarrier *src_barriers,
266   uint32_t count)
267{
268   if (cmd->builder.render_pass ||
269       !vn_image_memory_barrier_has_present_src(src_barriers, count))
270      return src_barriers;
271
272   VkImageMemoryBarrier *img_barriers =
273      vn_cmd_get_image_memory_barriers(cmd, count);
274   if (!img_barriers) {
275      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
276      return src_barriers;
277   }
278
279   for (uint32_t i = 0; i < count; i++) {
280      vn_cmd_fix_image_memory_barrier(cmd, &src_barriers[i],
281                                      &img_barriers[i]);
282   }
283
284   return img_barriers;
285}
286
287static void
288vn_cmd_encode_memory_barriers(struct vn_command_buffer *cmd,
289                              VkPipelineStageFlags src_stage_mask,
290                              VkPipelineStageFlags dst_stage_mask,
291                              uint32_t buf_barrier_count,
292                              const VkBufferMemoryBarrier *buf_barriers,
293                              uint32_t img_barrier_count,
294                              const VkImageMemoryBarrier *img_barriers)
295{
296   const VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd);
297
298   VN_CMD_ENQUEUE(vkCmdPipelineBarrier, cmd_handle, src_stage_mask,
299                  dst_stage_mask, 0, 0, NULL, buf_barrier_count, buf_barriers,
300                  img_barrier_count, img_barriers);
301}
302
303static void
304vn_present_src_attachment_to_image_memory_barrier(
305   const struct vn_image *img,
306   const struct vn_present_src_attachment *att,
307   VkImageMemoryBarrier *img_barrier)
308{
309   *img_barrier = (VkImageMemoryBarrier)
310   {
311      .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
312      .srcAccessMask = att->src_access_mask,
313      .dstAccessMask = att->dst_access_mask,
314      .oldLayout = att->acquire ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
315                                : VN_PRESENT_SRC_INTERNAL_LAYOUT,
316      .newLayout = att->acquire ? VN_PRESENT_SRC_INTERNAL_LAYOUT
317                                : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
318      .image = vn_image_to_handle((struct vn_image *)img),
319      .subresourceRange = {
320         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
321         .levelCount = 1,
322         .layerCount = 1,
323      },
324   };
325}
326
327static void
328vn_cmd_transfer_present_src_images(
329   struct vn_command_buffer *cmd,
330   const struct vn_image *const *images,
331   const struct vn_present_src_attachment *atts,
332   uint32_t count)
333{
334   VkImageMemoryBarrier *img_barriers =
335      vn_cmd_get_image_memory_barriers(cmd, count);
336   if (!img_barriers) {
337      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
338      return;
339   }
340
341   VkPipelineStageFlags src_stage_mask = 0;
342   VkPipelineStageFlags dst_stage_mask = 0;
343   for (uint32_t i = 0; i < count; i++) {
344      src_stage_mask |= atts[i].src_stage_mask;
345      dst_stage_mask |= atts[i].dst_stage_mask;
346
347      vn_present_src_attachment_to_image_memory_barrier(images[i], &atts[i],
348                                                        &img_barriers[i]);
349      vn_cmd_fix_image_memory_barrier(cmd, &img_barriers[i],
350                                      &img_barriers[i]);
351   }
352
353   if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
354      return;
355
356   vn_cmd_encode_memory_barriers(cmd, src_stage_mask, dst_stage_mask, 0, NULL,
357                                 count, img_barriers);
358}
359
360static void
361vn_cmd_begin_render_pass(struct vn_command_buffer *cmd,
362                         const struct vn_render_pass *pass,
363                         const struct vn_framebuffer *fb,
364                         const VkRenderPassBeginInfo *begin_info)
365{
366   cmd->builder.render_pass = pass;
367   cmd->builder.framebuffer = fb;
368
369   if (!pass->present_src_count ||
370       cmd->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
371      return;
372
373   /* find fb attachments */
374   const VkImageView *views;
375   ASSERTED uint32_t view_count;
376   if (fb->image_view_count) {
377      views = fb->image_views;
378      view_count = fb->image_view_count;
379   } else {
380      const VkRenderPassAttachmentBeginInfo *imageless_info =
381         vk_find_struct_const(begin_info->pNext,
382                              RENDER_PASS_ATTACHMENT_BEGIN_INFO);
383      assert(imageless_info);
384      views = imageless_info->pAttachments;
385      view_count = imageless_info->attachmentCount;
386   }
387
388   const struct vn_image **images =
389      vk_alloc(&cmd->allocator, sizeof(*images) * pass->present_src_count,
390               VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
391   if (!images) {
392      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
393      return;
394   }
395
396   for (uint32_t i = 0; i < pass->present_src_count; i++) {
397      const uint32_t index = pass->present_src_attachments[i].index;
398      assert(index < view_count);
399      images[i] = vn_image_view_from_handle(views[index])->image;
400   }
401
402   if (pass->acquire_count) {
403      vn_cmd_transfer_present_src_images(
404         cmd, images, pass->present_src_attachments, pass->acquire_count);
405   }
406
407   cmd->builder.present_src_images = images;
408}
409
410static void
411vn_cmd_end_render_pass(struct vn_command_buffer *cmd)
412{
413   const struct vn_render_pass *pass = cmd->builder.render_pass;
414
415   cmd->builder.render_pass = NULL;
416   cmd->builder.framebuffer = NULL;
417
418   if (!pass->present_src_count || !cmd->builder.present_src_images)
419      return;
420
421   const struct vn_image **images = cmd->builder.present_src_images;
422   cmd->builder.present_src_images = NULL;
423
424   if (pass->release_count) {
425      vn_cmd_transfer_present_src_images(
426         cmd, images + pass->acquire_count,
427         pass->present_src_attachments + pass->acquire_count,
428         pass->release_count);
429   }
430
431   vk_free(&cmd->allocator, images);
432}
433
434/* command pool commands */
435
436VkResult
437vn_CreateCommandPool(VkDevice device,
438                     const VkCommandPoolCreateInfo *pCreateInfo,
439                     const VkAllocationCallbacks *pAllocator,
440                     VkCommandPool *pCommandPool)
441{
442   VN_TRACE_FUNC();
443   struct vn_device *dev = vn_device_from_handle(device);
444   const VkAllocationCallbacks *alloc =
445      pAllocator ? pAllocator : &dev->base.base.alloc;
446
447   struct vn_command_pool *pool =
448      vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN,
449                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
450   if (!pool)
451      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
452
453   vn_object_base_init(&pool->base, VK_OBJECT_TYPE_COMMAND_POOL, &dev->base);
454
455   pool->allocator = *alloc;
456   pool->queue_family_index = pCreateInfo->queueFamilyIndex;
457   list_inithead(&pool->command_buffers);
458
459   VkCommandPool pool_handle = vn_command_pool_to_handle(pool);
460   vn_async_vkCreateCommandPool(dev->instance, device, pCreateInfo, NULL,
461                                &pool_handle);
462
463   *pCommandPool = pool_handle;
464
465   return VK_SUCCESS;
466}
467
468void
469vn_DestroyCommandPool(VkDevice device,
470                      VkCommandPool commandPool,
471                      const VkAllocationCallbacks *pAllocator)
472{
473   VN_TRACE_FUNC();
474   struct vn_device *dev = vn_device_from_handle(device);
475   struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool);
476   const VkAllocationCallbacks *alloc;
477
478   if (!pool)
479      return;
480
481   alloc = pAllocator ? pAllocator : &pool->allocator;
482
483   /* We must emit vkDestroyCommandPool before freeing the command buffers in
484    * pool->command_buffers.  Otherwise, another thread might reuse their
485    * object ids while they still refer to the command buffers in the
486    * renderer.
487    */
488   vn_async_vkDestroyCommandPool(dev->instance, device, commandPool, NULL);
489
490   list_for_each_entry_safe(struct vn_command_buffer, cmd,
491                            &pool->command_buffers, head) {
492      vn_cs_encoder_fini(&cmd->cs);
493      vn_object_base_fini(&cmd->base);
494      vk_free(alloc, cmd);
495   }
496
497   vn_object_base_fini(&pool->base);
498   vk_free(alloc, pool);
499}
500
501VkResult
502vn_ResetCommandPool(VkDevice device,
503                    VkCommandPool commandPool,
504                    VkCommandPoolResetFlags flags)
505{
506   VN_TRACE_FUNC();
507   struct vn_device *dev = vn_device_from_handle(device);
508   struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool);
509
510   list_for_each_entry_safe(struct vn_command_buffer, cmd,
511                            &pool->command_buffers, head) {
512      vn_cs_encoder_reset(&cmd->cs);
513      cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
514   }
515
516   vn_async_vkResetCommandPool(dev->instance, device, commandPool, flags);
517
518   return VK_SUCCESS;
519}
520
521void
522vn_TrimCommandPool(VkDevice device,
523                   VkCommandPool commandPool,
524                   VkCommandPoolTrimFlags flags)
525{
526   VN_TRACE_FUNC();
527   struct vn_device *dev = vn_device_from_handle(device);
528
529   vn_async_vkTrimCommandPool(dev->instance, device, commandPool, flags);
530}
531
532/* command buffer commands */
533
534VkResult
535vn_AllocateCommandBuffers(VkDevice device,
536                          const VkCommandBufferAllocateInfo *pAllocateInfo,
537                          VkCommandBuffer *pCommandBuffers)
538{
539   VN_TRACE_FUNC();
540   struct vn_device *dev = vn_device_from_handle(device);
541   struct vn_command_pool *pool =
542      vn_command_pool_from_handle(pAllocateInfo->commandPool);
543   const VkAllocationCallbacks *alloc = &pool->allocator;
544
545   for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
546      struct vn_command_buffer *cmd =
547         vk_zalloc(alloc, sizeof(*cmd), VN_DEFAULT_ALIGN,
548                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
549      if (!cmd) {
550         for (uint32_t j = 0; j < i; j++) {
551            cmd = vn_command_buffer_from_handle(pCommandBuffers[j]);
552            vn_cs_encoder_fini(&cmd->cs);
553            list_del(&cmd->head);
554            vn_object_base_fini(&cmd->base);
555            vk_free(alloc, cmd);
556         }
557         memset(pCommandBuffers, 0,
558                sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount);
559         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
560      }
561
562      vn_object_base_init(&cmd->base, VK_OBJECT_TYPE_COMMAND_BUFFER,
563                          &dev->base);
564      cmd->device = dev;
565      cmd->allocator = pool->allocator;
566      cmd->level = pAllocateInfo->level;
567      cmd->queue_family_index = pool->queue_family_index;
568
569      list_addtail(&cmd->head, &pool->command_buffers);
570
571      cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
572      vn_cs_encoder_init(&cmd->cs, dev->instance,
573                         VN_CS_ENCODER_STORAGE_SHMEM_POOL, 16 * 1024);
574
575      VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd);
576      pCommandBuffers[i] = cmd_handle;
577   }
578
579   vn_async_vkAllocateCommandBuffers(dev->instance, device, pAllocateInfo,
580                                     pCommandBuffers);
581
582   return VK_SUCCESS;
583}
584
585void
586vn_FreeCommandBuffers(VkDevice device,
587                      VkCommandPool commandPool,
588                      uint32_t commandBufferCount,
589                      const VkCommandBuffer *pCommandBuffers)
590{
591   VN_TRACE_FUNC();
592   struct vn_device *dev = vn_device_from_handle(device);
593   struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool);
594   const VkAllocationCallbacks *alloc = &pool->allocator;
595
596   vn_async_vkFreeCommandBuffers(dev->instance, device, commandPool,
597                                 commandBufferCount, pCommandBuffers);
598
599   for (uint32_t i = 0; i < commandBufferCount; i++) {
600      struct vn_command_buffer *cmd =
601         vn_command_buffer_from_handle(pCommandBuffers[i]);
602
603      if (!cmd)
604         continue;
605
606      if (cmd->builder.image_barriers)
607         vk_free(alloc, cmd->builder.image_barriers);
608
609      vn_cs_encoder_fini(&cmd->cs);
610      list_del(&cmd->head);
611
612      vn_object_base_fini(&cmd->base);
613      vk_free(alloc, cmd);
614   }
615}
616
617VkResult
618vn_ResetCommandBuffer(VkCommandBuffer commandBuffer,
619                      VkCommandBufferResetFlags flags)
620{
621   VN_TRACE_FUNC();
622   struct vn_command_buffer *cmd =
623      vn_command_buffer_from_handle(commandBuffer);
624
625   vn_cs_encoder_reset(&cmd->cs);
626   cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
627   cmd->draw_cmd_batched = 0;
628
629   vn_async_vkResetCommandBuffer(cmd->device->instance, commandBuffer, flags);
630
631   return VK_SUCCESS;
632}
633
634struct vn_command_buffer_begin_info {
635   VkCommandBufferBeginInfo begin;
636   VkCommandBufferInheritanceInfo inheritance;
637   VkCommandBufferInheritanceConditionalRenderingInfoEXT conditional_rendering;
638
639   bool has_inherited_pass;
640};
641
642static const VkCommandBufferBeginInfo *
643vn_fix_command_buffer_begin_info(struct vn_command_buffer *cmd,
644                                 const VkCommandBufferBeginInfo *begin_info,
645                                 struct vn_command_buffer_begin_info *local)
646{
647   local->has_inherited_pass = false;
648
649   if (!begin_info->pInheritanceInfo)
650      return begin_info;
651
652   const bool is_cmd_secondary =
653      cmd->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY;
654   const bool has_continue =
655      begin_info->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
656   const bool has_renderpass =
657      is_cmd_secondary &&
658      begin_info->pInheritanceInfo->renderPass != VK_NULL_HANDLE;
659
660   /* Can early-return if dynamic rendering is used and no structures need to
661    * be dropped from the pNext chain of VkCommandBufferInheritanceInfo.
662    */
663   if (is_cmd_secondary && has_continue && !has_renderpass)
664      return begin_info;
665
666   local->begin = *begin_info;
667
668   if (!is_cmd_secondary) {
669      local->begin.pInheritanceInfo = NULL;
670      return &local->begin;
671   }
672
673   local->inheritance = *begin_info->pInheritanceInfo;
674   local->begin.pInheritanceInfo = &local->inheritance;
675
676   if (!has_continue) {
677      local->inheritance.framebuffer = VK_NULL_HANDLE;
678      local->inheritance.renderPass = VK_NULL_HANDLE;
679      local->inheritance.subpass = 0;
680   } else {
681      /* With early-returns above, it must be an inherited pass. */
682      local->has_inherited_pass = true;
683   }
684
685   /* Per spec, about VkCommandBufferInheritanceRenderingInfo:
686    *
687    * If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE, or
688    * VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT is not specified in
689    * VkCommandBufferBeginInfo::flags, parameters of this structure are
690    * ignored.
691    */
692   VkBaseOutStructure *head = NULL;
693   VkBaseOutStructure *tail = NULL;
694   vk_foreach_struct_const(src, local->inheritance.pNext) {
695      void *pnext = NULL;
696      switch (src->sType) {
697      case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT:
698         memcpy(
699            &local->conditional_rendering, src,
700            sizeof(VkCommandBufferInheritanceConditionalRenderingInfoEXT));
701         pnext = &local->conditional_rendering;
702         break;
703      case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO:
704      default:
705         break;
706      }
707
708      if (pnext) {
709         if (!head)
710            head = pnext;
711         else
712            tail->pNext = pnext;
713
714         tail = pnext;
715      }
716   }
717   local->inheritance.pNext = head;
718
719   return &local->begin;
720}
721
722VkResult
723vn_BeginCommandBuffer(VkCommandBuffer commandBuffer,
724                      const VkCommandBufferBeginInfo *pBeginInfo)
725{
726   VN_TRACE_FUNC();
727   struct vn_command_buffer *cmd =
728      vn_command_buffer_from_handle(commandBuffer);
729   struct vn_instance *instance = cmd->device->instance;
730   size_t cmd_size;
731
732   vn_cs_encoder_reset(&cmd->cs);
733   cmd->draw_cmd_batched = 0;
734
735   struct vn_command_buffer_begin_info local_begin_info;
736   pBeginInfo =
737      vn_fix_command_buffer_begin_info(cmd, pBeginInfo, &local_begin_info);
738
739   cmd_size = vn_sizeof_vkBeginCommandBuffer(commandBuffer, pBeginInfo);
740   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) {
741      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
742      return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
743   }
744
745   vn_encode_vkBeginCommandBuffer(&cmd->cs, 0, commandBuffer, pBeginInfo);
746
747   cmd->state = VN_COMMAND_BUFFER_STATE_RECORDING;
748
749   if (local_begin_info.has_inherited_pass) {
750      const VkCommandBufferInheritanceInfo *inheritance_info =
751         pBeginInfo->pInheritanceInfo;
752      vn_cmd_begin_render_pass(
753         cmd, vn_render_pass_from_handle(inheritance_info->renderPass),
754         vn_framebuffer_from_handle(inheritance_info->framebuffer), NULL);
755   }
756
757   return VK_SUCCESS;
758}
759
760static void
761vn_cmd_submit(struct vn_command_buffer *cmd)
762{
763   struct vn_instance *instance = cmd->device->instance;
764
765   if (cmd->state != VN_COMMAND_BUFFER_STATE_RECORDING)
766      return;
767
768   vn_cs_encoder_commit(&cmd->cs);
769   if (vn_cs_encoder_get_fatal(&cmd->cs)) {
770      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
771      vn_cs_encoder_reset(&cmd->cs);
772      return;
773   }
774
775   if (unlikely(!instance->renderer->info.supports_blob_id_0))
776      vn_instance_wait_roundtrip(instance, cmd->cs.current_buffer_roundtrip);
777
778   if (vn_instance_ring_submit(instance, &cmd->cs) != VK_SUCCESS) {
779      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
780      return;
781   }
782
783   vn_cs_encoder_reset(&cmd->cs);
784   cmd->draw_cmd_batched = 0;
785}
786
787static inline void
788vn_cmd_count_draw_and_submit_on_batch_limit(struct vn_command_buffer *cmd)
789{
790   if (++cmd->draw_cmd_batched >= vn_env.draw_cmd_batch_limit)
791      vn_cmd_submit(cmd);
792}
793
794VkResult
795vn_EndCommandBuffer(VkCommandBuffer commandBuffer)
796{
797   VN_TRACE_FUNC();
798   struct vn_command_buffer *cmd =
799      vn_command_buffer_from_handle(commandBuffer);
800   struct vn_instance *instance = cmd->device->instance;
801   size_t cmd_size;
802
803   if (cmd->state != VN_COMMAND_BUFFER_STATE_RECORDING)
804      return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
805
806   cmd_size = vn_sizeof_vkEndCommandBuffer(commandBuffer);
807   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) {
808      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
809      return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
810   }
811
812   vn_encode_vkEndCommandBuffer(&cmd->cs, 0, commandBuffer);
813
814   vn_cmd_submit(cmd);
815   if (cmd->state == VN_COMMAND_BUFFER_STATE_INVALID)
816      return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
817
818   cmd->state = VN_COMMAND_BUFFER_STATE_EXECUTABLE;
819
820   return VK_SUCCESS;
821}
822
823void
824vn_CmdBindPipeline(VkCommandBuffer commandBuffer,
825                   VkPipelineBindPoint pipelineBindPoint,
826                   VkPipeline pipeline)
827{
828   VN_CMD_ENQUEUE(vkCmdBindPipeline, commandBuffer, pipelineBindPoint,
829                  pipeline);
830}
831
832void
833vn_CmdSetViewport(VkCommandBuffer commandBuffer,
834                  uint32_t firstViewport,
835                  uint32_t viewportCount,
836                  const VkViewport *pViewports)
837{
838   VN_CMD_ENQUEUE(vkCmdSetViewport, commandBuffer, firstViewport,
839                  viewportCount, pViewports);
840}
841
842void
843vn_CmdSetScissor(VkCommandBuffer commandBuffer,
844                 uint32_t firstScissor,
845                 uint32_t scissorCount,
846                 const VkRect2D *pScissors)
847{
848   VN_CMD_ENQUEUE(vkCmdSetScissor, commandBuffer, firstScissor, scissorCount,
849                  pScissors);
850}
851
852void
853vn_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)
854{
855   VN_CMD_ENQUEUE(vkCmdSetLineWidth, commandBuffer, lineWidth);
856}
857
858void
859vn_CmdSetDepthBias(VkCommandBuffer commandBuffer,
860                   float depthBiasConstantFactor,
861                   float depthBiasClamp,
862                   float depthBiasSlopeFactor)
863{
864   VN_CMD_ENQUEUE(vkCmdSetDepthBias, commandBuffer, depthBiasConstantFactor,
865                  depthBiasClamp, depthBiasSlopeFactor);
866}
867
868void
869vn_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
870                        const float blendConstants[4])
871{
872   VN_CMD_ENQUEUE(vkCmdSetBlendConstants, commandBuffer, blendConstants);
873}
874
875void
876vn_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
877                     float minDepthBounds,
878                     float maxDepthBounds)
879{
880   VN_CMD_ENQUEUE(vkCmdSetDepthBounds, commandBuffer, minDepthBounds,
881                  maxDepthBounds);
882}
883
884void
885vn_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
886                            VkStencilFaceFlags faceMask,
887                            uint32_t compareMask)
888{
889   VN_CMD_ENQUEUE(vkCmdSetStencilCompareMask, commandBuffer, faceMask,
890                  compareMask);
891}
892
893void
894vn_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
895                          VkStencilFaceFlags faceMask,
896                          uint32_t writeMask)
897{
898   VN_CMD_ENQUEUE(vkCmdSetStencilWriteMask, commandBuffer, faceMask,
899                  writeMask);
900}
901
902void
903vn_CmdSetStencilReference(VkCommandBuffer commandBuffer,
904                          VkStencilFaceFlags faceMask,
905                          uint32_t reference)
906{
907   VN_CMD_ENQUEUE(vkCmdSetStencilReference, commandBuffer, faceMask,
908                  reference);
909}
910
911void
912vn_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
913                         VkPipelineBindPoint pipelineBindPoint,
914                         VkPipelineLayout layout,
915                         uint32_t firstSet,
916                         uint32_t descriptorSetCount,
917                         const VkDescriptorSet *pDescriptorSets,
918                         uint32_t dynamicOffsetCount,
919                         const uint32_t *pDynamicOffsets)
920{
921   VN_CMD_ENQUEUE(vkCmdBindDescriptorSets, commandBuffer, pipelineBindPoint,
922                  layout, firstSet, descriptorSetCount, pDescriptorSets,
923                  dynamicOffsetCount, pDynamicOffsets);
924}
925
926void
927vn_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
928                      VkBuffer buffer,
929                      VkDeviceSize offset,
930                      VkIndexType indexType)
931{
932   VN_CMD_ENQUEUE(vkCmdBindIndexBuffer, commandBuffer, buffer, offset,
933                  indexType);
934}
935
936void
937vn_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
938                        uint32_t firstBinding,
939                        uint32_t bindingCount,
940                        const VkBuffer *pBuffers,
941                        const VkDeviceSize *pOffsets)
942{
943   VN_CMD_ENQUEUE(vkCmdBindVertexBuffers, commandBuffer, firstBinding,
944                  bindingCount, pBuffers, pOffsets);
945}
946
947void
948vn_CmdDraw(VkCommandBuffer commandBuffer,
949           uint32_t vertexCount,
950           uint32_t instanceCount,
951           uint32_t firstVertex,
952           uint32_t firstInstance)
953{
954   VN_CMD_ENQUEUE(vkCmdDraw, commandBuffer, vertexCount, instanceCount,
955                  firstVertex, firstInstance);
956
957   vn_cmd_count_draw_and_submit_on_batch_limit(
958      vn_command_buffer_from_handle(commandBuffer));
959}
960
961void
962vn_CmdBeginRendering(VkCommandBuffer commandBuffer,
963                     const VkRenderingInfo *pRenderingInfo)
964{
965   VN_CMD_ENQUEUE(vkCmdBeginRendering, commandBuffer, pRenderingInfo);
966}
967
968void
969vn_CmdEndRendering(VkCommandBuffer commandBuffer)
970{
971   VN_CMD_ENQUEUE(vkCmdEndRendering, commandBuffer);
972}
973
974void
975vn_CmdDrawIndexed(VkCommandBuffer commandBuffer,
976                  uint32_t indexCount,
977                  uint32_t instanceCount,
978                  uint32_t firstIndex,
979                  int32_t vertexOffset,
980                  uint32_t firstInstance)
981{
982   VN_CMD_ENQUEUE(vkCmdDrawIndexed, commandBuffer, indexCount, instanceCount,
983                  firstIndex, vertexOffset, firstInstance);
984
985   vn_cmd_count_draw_and_submit_on_batch_limit(
986      vn_command_buffer_from_handle(commandBuffer));
987}
988
989void
990vn_CmdDrawIndirect(VkCommandBuffer commandBuffer,
991                   VkBuffer buffer,
992                   VkDeviceSize offset,
993                   uint32_t drawCount,
994                   uint32_t stride)
995{
996   VN_CMD_ENQUEUE(vkCmdDrawIndirect, commandBuffer, buffer, offset, drawCount,
997                  stride);
998
999   vn_cmd_count_draw_and_submit_on_batch_limit(
1000      vn_command_buffer_from_handle(commandBuffer));
1001}
1002
1003void
1004vn_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
1005                          VkBuffer buffer,
1006                          VkDeviceSize offset,
1007                          uint32_t drawCount,
1008                          uint32_t stride)
1009{
1010   VN_CMD_ENQUEUE(vkCmdDrawIndexedIndirect, commandBuffer, buffer, offset,
1011                  drawCount, stride);
1012
1013   vn_cmd_count_draw_and_submit_on_batch_limit(
1014      vn_command_buffer_from_handle(commandBuffer));
1015}
1016
1017void
1018vn_CmdDrawIndirectCount(VkCommandBuffer commandBuffer,
1019                        VkBuffer buffer,
1020                        VkDeviceSize offset,
1021                        VkBuffer countBuffer,
1022                        VkDeviceSize countBufferOffset,
1023                        uint32_t maxDrawCount,
1024                        uint32_t stride)
1025{
1026   VN_CMD_ENQUEUE(vkCmdDrawIndirectCount, commandBuffer, buffer, offset,
1027                  countBuffer, countBufferOffset, maxDrawCount, stride);
1028
1029   vn_cmd_count_draw_and_submit_on_batch_limit(
1030      vn_command_buffer_from_handle(commandBuffer));
1031}
1032
1033void
1034vn_CmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer,
1035                               VkBuffer buffer,
1036                               VkDeviceSize offset,
1037                               VkBuffer countBuffer,
1038                               VkDeviceSize countBufferOffset,
1039                               uint32_t maxDrawCount,
1040                               uint32_t stride)
1041{
1042   VN_CMD_ENQUEUE(vkCmdDrawIndexedIndirectCount, commandBuffer, buffer,
1043                  offset, countBuffer, countBufferOffset, maxDrawCount,
1044                  stride);
1045
1046   vn_cmd_count_draw_and_submit_on_batch_limit(
1047      vn_command_buffer_from_handle(commandBuffer));
1048}
1049
1050void
1051vn_CmdDispatch(VkCommandBuffer commandBuffer,
1052               uint32_t groupCountX,
1053               uint32_t groupCountY,
1054               uint32_t groupCountZ)
1055{
1056   VN_CMD_ENQUEUE(vkCmdDispatch, commandBuffer, groupCountX, groupCountY,
1057                  groupCountZ);
1058}
1059
1060void
1061vn_CmdDispatchIndirect(VkCommandBuffer commandBuffer,
1062                       VkBuffer buffer,
1063                       VkDeviceSize offset)
1064{
1065   VN_CMD_ENQUEUE(vkCmdDispatchIndirect, commandBuffer, buffer, offset);
1066}
1067
1068void
1069vn_CmdCopyBuffer(VkCommandBuffer commandBuffer,
1070                 VkBuffer srcBuffer,
1071                 VkBuffer dstBuffer,
1072                 uint32_t regionCount,
1073                 const VkBufferCopy *pRegions)
1074{
1075   VN_CMD_ENQUEUE(vkCmdCopyBuffer, commandBuffer, srcBuffer, dstBuffer,
1076                  regionCount, pRegions);
1077}
1078
1079void
1080vn_CmdCopyBuffer2(VkCommandBuffer commandBuffer,
1081                  const VkCopyBufferInfo2 *pCopyBufferInfo)
1082{
1083   VN_CMD_ENQUEUE(vkCmdCopyBuffer2, commandBuffer, pCopyBufferInfo);
1084}
1085
1086void
1087vn_CmdCopyImage(VkCommandBuffer commandBuffer,
1088                VkImage srcImage,
1089                VkImageLayout srcImageLayout,
1090                VkImage dstImage,
1091                VkImageLayout dstImageLayout,
1092                uint32_t regionCount,
1093                const VkImageCopy *pRegions)
1094{
1095   VN_CMD_ENQUEUE(vkCmdCopyImage, commandBuffer, srcImage, srcImageLayout,
1096                  dstImage, dstImageLayout, regionCount, pRegions);
1097}
1098
1099void
1100vn_CmdCopyImage2(VkCommandBuffer commandBuffer,
1101                 const VkCopyImageInfo2 *pCopyImageInfo)
1102{
1103   VN_CMD_ENQUEUE(vkCmdCopyImage2, commandBuffer, pCopyImageInfo);
1104}
1105
1106void
1107vn_CmdBlitImage(VkCommandBuffer commandBuffer,
1108                VkImage srcImage,
1109                VkImageLayout srcImageLayout,
1110                VkImage dstImage,
1111                VkImageLayout dstImageLayout,
1112                uint32_t regionCount,
1113                const VkImageBlit *pRegions,
1114                VkFilter filter)
1115{
1116   VN_CMD_ENQUEUE(vkCmdBlitImage, commandBuffer, srcImage, srcImageLayout,
1117                  dstImage, dstImageLayout, regionCount, pRegions, filter);
1118}
1119
1120void
1121vn_CmdBlitImage2(VkCommandBuffer commandBuffer,
1122                 const VkBlitImageInfo2 *pBlitImageInfo)
1123{
1124   VN_CMD_ENQUEUE(vkCmdBlitImage2, commandBuffer, pBlitImageInfo);
1125}
1126
1127void
1128vn_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,
1129                        VkBuffer srcBuffer,
1130                        VkImage dstImage,
1131                        VkImageLayout dstImageLayout,
1132                        uint32_t regionCount,
1133                        const VkBufferImageCopy *pRegions)
1134{
1135   VN_CMD_ENQUEUE(vkCmdCopyBufferToImage, commandBuffer, srcBuffer, dstImage,
1136                  dstImageLayout, regionCount, pRegions);
1137}
1138
1139void
1140vn_CmdCopyBufferToImage2(
1141   VkCommandBuffer commandBuffer,
1142   const VkCopyBufferToImageInfo2 *pCopyBufferToImageInfo)
1143{
1144   VN_CMD_ENQUEUE(vkCmdCopyBufferToImage2, commandBuffer,
1145                  pCopyBufferToImageInfo);
1146}
1147
1148static bool
1149vn_needs_prime_blit(VkImage src_image, VkImageLayout src_image_layout)
1150{
1151   if (src_image_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
1152       VN_PRESENT_SRC_INTERNAL_LAYOUT != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
1153
1154      /* sanity check */
1155      ASSERTED const struct vn_image *img = vn_image_from_handle(src_image);
1156      assert(img->wsi.is_wsi && img->wsi.is_prime_blit_src);
1157      return true;
1158   }
1159
1160   return false;
1161}
1162
1163static void
1164vn_transition_prime_layout(struct vn_command_buffer *cmd, VkBuffer dst_buffer)
1165{
1166   const VkBufferMemoryBarrier buf_barrier = {
1167      .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1168      .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
1169      .srcQueueFamilyIndex = cmd->queue_family_index,
1170      .dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT,
1171      .buffer = dst_buffer,
1172      .size = VK_WHOLE_SIZE,
1173   };
1174   vn_cmd_encode_memory_barriers(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT,
1175                                 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 1,
1176                                 &buf_barrier, 0, NULL);
1177}
1178
1179void
1180vn_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
1181                        VkImage srcImage,
1182                        VkImageLayout srcImageLayout,
1183                        VkBuffer dstBuffer,
1184                        uint32_t regionCount,
1185                        const VkBufferImageCopy *pRegions)
1186{
1187   struct vn_command_buffer *cmd =
1188      vn_command_buffer_from_handle(commandBuffer);
1189
1190   bool prime_blit = vn_needs_prime_blit(srcImage, srcImageLayout);
1191   if (prime_blit)
1192      srcImageLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
1193
1194   VN_CMD_ENQUEUE(vkCmdCopyImageToBuffer, commandBuffer, srcImage,
1195                  srcImageLayout, dstBuffer, regionCount, pRegions);
1196
1197   if (prime_blit)
1198      vn_transition_prime_layout(cmd, dstBuffer);
1199}
1200
1201void
1202vn_CmdCopyImageToBuffer2(
1203   VkCommandBuffer commandBuffer,
1204   const VkCopyImageToBufferInfo2 *pCopyImageToBufferInfo)
1205{
1206   struct vn_command_buffer *cmd =
1207      vn_command_buffer_from_handle(commandBuffer);
1208   struct VkCopyImageToBufferInfo2 copy_info = *pCopyImageToBufferInfo;
1209
1210   bool prime_blit =
1211      vn_needs_prime_blit(copy_info.srcImage, copy_info.srcImageLayout);
1212   if (prime_blit)
1213      copy_info.srcImageLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
1214
1215   VN_CMD_ENQUEUE(vkCmdCopyImageToBuffer2, commandBuffer, &copy_info);
1216
1217   if (prime_blit)
1218      vn_transition_prime_layout(cmd, copy_info.dstBuffer);
1219}
1220
1221void
1222vn_CmdUpdateBuffer(VkCommandBuffer commandBuffer,
1223                   VkBuffer dstBuffer,
1224                   VkDeviceSize dstOffset,
1225                   VkDeviceSize dataSize,
1226                   const void *pData)
1227{
1228   VN_CMD_ENQUEUE(vkCmdUpdateBuffer, commandBuffer, dstBuffer, dstOffset,
1229                  dataSize, pData);
1230}
1231
1232void
1233vn_CmdFillBuffer(VkCommandBuffer commandBuffer,
1234                 VkBuffer dstBuffer,
1235                 VkDeviceSize dstOffset,
1236                 VkDeviceSize size,
1237                 uint32_t data)
1238{
1239   VN_CMD_ENQUEUE(vkCmdFillBuffer, commandBuffer, dstBuffer, dstOffset, size,
1240                  data);
1241}
1242
1243void
1244vn_CmdClearColorImage(VkCommandBuffer commandBuffer,
1245                      VkImage image,
1246                      VkImageLayout imageLayout,
1247                      const VkClearColorValue *pColor,
1248                      uint32_t rangeCount,
1249                      const VkImageSubresourceRange *pRanges)
1250{
1251   VN_CMD_ENQUEUE(vkCmdClearColorImage, commandBuffer, image, imageLayout,
1252                  pColor, rangeCount, pRanges);
1253}
1254
1255void
1256vn_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
1257                             VkImage image,
1258                             VkImageLayout imageLayout,
1259                             const VkClearDepthStencilValue *pDepthStencil,
1260                             uint32_t rangeCount,
1261                             const VkImageSubresourceRange *pRanges)
1262{
1263   VN_CMD_ENQUEUE(vkCmdClearDepthStencilImage, commandBuffer, image,
1264                  imageLayout, pDepthStencil, rangeCount, pRanges);
1265}
1266
1267void
1268vn_CmdClearAttachments(VkCommandBuffer commandBuffer,
1269                       uint32_t attachmentCount,
1270                       const VkClearAttachment *pAttachments,
1271                       uint32_t rectCount,
1272                       const VkClearRect *pRects)
1273{
1274   VN_CMD_ENQUEUE(vkCmdClearAttachments, commandBuffer, attachmentCount,
1275                  pAttachments, rectCount, pRects);
1276}
1277
1278void
1279vn_CmdResolveImage(VkCommandBuffer commandBuffer,
1280                   VkImage srcImage,
1281                   VkImageLayout srcImageLayout,
1282                   VkImage dstImage,
1283                   VkImageLayout dstImageLayout,
1284                   uint32_t regionCount,
1285                   const VkImageResolve *pRegions)
1286{
1287   VN_CMD_ENQUEUE(vkCmdResolveImage, commandBuffer, srcImage, srcImageLayout,
1288                  dstImage, dstImageLayout, regionCount, pRegions);
1289}
1290
1291void
1292vn_CmdResolveImage2(VkCommandBuffer commandBuffer,
1293                    const VkResolveImageInfo2 *pResolveImageInfo)
1294{
1295   VN_CMD_ENQUEUE(vkCmdResolveImage2, commandBuffer, pResolveImageInfo);
1296}
1297
1298void
1299vn_CmdSetEvent(VkCommandBuffer commandBuffer,
1300               VkEvent event,
1301               VkPipelineStageFlags stageMask)
1302{
1303   VN_CMD_ENQUEUE(vkCmdSetEvent, commandBuffer, event, stageMask);
1304
1305   vn_feedback_event_cmd_record(commandBuffer, event, stageMask,
1306                                VK_EVENT_SET);
1307}
1308
1309void
1310vn_CmdResetEvent(VkCommandBuffer commandBuffer,
1311                 VkEvent event,
1312                 VkPipelineStageFlags stageMask)
1313{
1314   VN_CMD_ENQUEUE(vkCmdResetEvent, commandBuffer, event, stageMask);
1315
1316   vn_feedback_event_cmd_record(commandBuffer, event, stageMask,
1317                                VK_EVENT_RESET);
1318}
1319
1320void
1321vn_CmdWaitEvents(VkCommandBuffer commandBuffer,
1322                 uint32_t eventCount,
1323                 const VkEvent *pEvents,
1324                 VkPipelineStageFlags srcStageMask,
1325                 VkPipelineStageFlags dstStageMask,
1326                 uint32_t memoryBarrierCount,
1327                 const VkMemoryBarrier *pMemoryBarriers,
1328                 uint32_t bufferMemoryBarrierCount,
1329                 const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1330                 uint32_t imageMemoryBarrierCount,
1331                 const VkImageMemoryBarrier *pImageMemoryBarriers)
1332{
1333   struct vn_command_buffer *cmd =
1334      vn_command_buffer_from_handle(commandBuffer);
1335   uint32_t transfer_count;
1336
1337   pImageMemoryBarriers = vn_cmd_wait_events_fix_image_memory_barriers(
1338      cmd, pImageMemoryBarriers, imageMemoryBarrierCount, &transfer_count);
1339   imageMemoryBarrierCount -= transfer_count;
1340
1341   VN_CMD_ENQUEUE(vkCmdWaitEvents, commandBuffer, eventCount, pEvents,
1342                  srcStageMask, dstStageMask, memoryBarrierCount,
1343                  pMemoryBarriers, bufferMemoryBarrierCount,
1344                  pBufferMemoryBarriers, imageMemoryBarrierCount,
1345                  pImageMemoryBarriers);
1346
1347   if (transfer_count) {
1348      pImageMemoryBarriers += imageMemoryBarrierCount;
1349      vn_cmd_encode_memory_barriers(cmd, srcStageMask, dstStageMask, 0, NULL,
1350                                    transfer_count, pImageMemoryBarriers);
1351   }
1352}
1353
1354void
1355vn_CmdPipelineBarrier(VkCommandBuffer commandBuffer,
1356                      VkPipelineStageFlags srcStageMask,
1357                      VkPipelineStageFlags dstStageMask,
1358                      VkDependencyFlags dependencyFlags,
1359                      uint32_t memoryBarrierCount,
1360                      const VkMemoryBarrier *pMemoryBarriers,
1361                      uint32_t bufferMemoryBarrierCount,
1362                      const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1363                      uint32_t imageMemoryBarrierCount,
1364                      const VkImageMemoryBarrier *pImageMemoryBarriers)
1365{
1366   struct vn_command_buffer *cmd =
1367      vn_command_buffer_from_handle(commandBuffer);
1368
1369   pImageMemoryBarriers = vn_cmd_pipeline_barrier_fix_image_memory_barriers(
1370      cmd, pImageMemoryBarriers, imageMemoryBarrierCount);
1371
1372   VN_CMD_ENQUEUE(vkCmdPipelineBarrier, commandBuffer, srcStageMask,
1373                  dstStageMask, dependencyFlags, memoryBarrierCount,
1374                  pMemoryBarriers, bufferMemoryBarrierCount,
1375                  pBufferMemoryBarriers, imageMemoryBarrierCount,
1376                  pImageMemoryBarriers);
1377}
1378
1379void
1380vn_CmdBeginQuery(VkCommandBuffer commandBuffer,
1381                 VkQueryPool queryPool,
1382                 uint32_t query,
1383                 VkQueryControlFlags flags)
1384{
1385   VN_CMD_ENQUEUE(vkCmdBeginQuery, commandBuffer, queryPool, query, flags);
1386}
1387
1388void
1389vn_CmdEndQuery(VkCommandBuffer commandBuffer,
1390               VkQueryPool queryPool,
1391               uint32_t query)
1392{
1393   VN_CMD_ENQUEUE(vkCmdEndQuery, commandBuffer, queryPool, query);
1394}
1395
1396void
1397vn_CmdResetQueryPool(VkCommandBuffer commandBuffer,
1398                     VkQueryPool queryPool,
1399                     uint32_t firstQuery,
1400                     uint32_t queryCount)
1401{
1402   VN_CMD_ENQUEUE(vkCmdResetQueryPool, commandBuffer, queryPool, firstQuery,
1403                  queryCount);
1404}
1405
1406void
1407vn_CmdWriteTimestamp(VkCommandBuffer commandBuffer,
1408                     VkPipelineStageFlagBits pipelineStage,
1409                     VkQueryPool queryPool,
1410                     uint32_t query)
1411{
1412   VN_CMD_ENQUEUE(vkCmdWriteTimestamp, commandBuffer, pipelineStage,
1413                  queryPool, query);
1414}
1415
1416void
1417vn_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
1418                           VkQueryPool queryPool,
1419                           uint32_t firstQuery,
1420                           uint32_t queryCount,
1421                           VkBuffer dstBuffer,
1422                           VkDeviceSize dstOffset,
1423                           VkDeviceSize stride,
1424                           VkQueryResultFlags flags)
1425{
1426   VN_CMD_ENQUEUE(vkCmdCopyQueryPoolResults, commandBuffer, queryPool,
1427                  firstQuery, queryCount, dstBuffer, dstOffset, stride,
1428                  flags);
1429}
1430
1431void
1432vn_CmdPushConstants(VkCommandBuffer commandBuffer,
1433                    VkPipelineLayout layout,
1434                    VkShaderStageFlags stageFlags,
1435                    uint32_t offset,
1436                    uint32_t size,
1437                    const void *pValues)
1438{
1439   VN_CMD_ENQUEUE(vkCmdPushConstants, commandBuffer, layout, stageFlags,
1440                  offset, size, pValues);
1441}
1442
1443void
1444vn_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
1445                      const VkRenderPassBeginInfo *pRenderPassBegin,
1446                      VkSubpassContents contents)
1447{
1448   struct vn_command_buffer *cmd =
1449      vn_command_buffer_from_handle(commandBuffer);
1450
1451   vn_cmd_begin_render_pass(
1452      cmd, vn_render_pass_from_handle(pRenderPassBegin->renderPass),
1453      vn_framebuffer_from_handle(pRenderPassBegin->framebuffer),
1454      pRenderPassBegin);
1455
1456   VN_CMD_ENQUEUE(vkCmdBeginRenderPass, commandBuffer, pRenderPassBegin,
1457                  contents);
1458}
1459
1460void
1461vn_CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
1462{
1463   VN_CMD_ENQUEUE(vkCmdNextSubpass, commandBuffer, contents);
1464}
1465
1466void
1467vn_CmdEndRenderPass(VkCommandBuffer commandBuffer)
1468{
1469   struct vn_command_buffer *cmd =
1470      vn_command_buffer_from_handle(commandBuffer);
1471
1472   VN_CMD_ENQUEUE(vkCmdEndRenderPass, commandBuffer);
1473
1474   vn_cmd_end_render_pass(cmd);
1475}
1476
1477void
1478vn_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
1479                       const VkRenderPassBeginInfo *pRenderPassBegin,
1480                       const VkSubpassBeginInfo *pSubpassBeginInfo)
1481{
1482   struct vn_command_buffer *cmd =
1483      vn_command_buffer_from_handle(commandBuffer);
1484
1485   vn_cmd_begin_render_pass(
1486      cmd, vn_render_pass_from_handle(pRenderPassBegin->renderPass),
1487      vn_framebuffer_from_handle(pRenderPassBegin->framebuffer),
1488      pRenderPassBegin);
1489
1490   VN_CMD_ENQUEUE(vkCmdBeginRenderPass2, commandBuffer, pRenderPassBegin,
1491                  pSubpassBeginInfo);
1492}
1493
1494void
1495vn_CmdNextSubpass2(VkCommandBuffer commandBuffer,
1496                   const VkSubpassBeginInfo *pSubpassBeginInfo,
1497                   const VkSubpassEndInfo *pSubpassEndInfo)
1498{
1499   VN_CMD_ENQUEUE(vkCmdNextSubpass2, commandBuffer, pSubpassBeginInfo,
1500                  pSubpassEndInfo);
1501}
1502
1503void
1504vn_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
1505                     const VkSubpassEndInfo *pSubpassEndInfo)
1506{
1507   struct vn_command_buffer *cmd =
1508      vn_command_buffer_from_handle(commandBuffer);
1509
1510   VN_CMD_ENQUEUE(vkCmdEndRenderPass2, commandBuffer, pSubpassEndInfo);
1511
1512   vn_cmd_end_render_pass(cmd);
1513}
1514
1515void
1516vn_CmdExecuteCommands(VkCommandBuffer commandBuffer,
1517                      uint32_t commandBufferCount,
1518                      const VkCommandBuffer *pCommandBuffers)
1519{
1520   VN_CMD_ENQUEUE(vkCmdExecuteCommands, commandBuffer, commandBufferCount,
1521                  pCommandBuffers);
1522}
1523
1524void
1525vn_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
1526{
1527   VN_CMD_ENQUEUE(vkCmdSetDeviceMask, commandBuffer, deviceMask);
1528}
1529
1530void
1531vn_CmdDispatchBase(VkCommandBuffer commandBuffer,
1532                   uint32_t baseGroupX,
1533                   uint32_t baseGroupY,
1534                   uint32_t baseGroupZ,
1535                   uint32_t groupCountX,
1536                   uint32_t groupCountY,
1537                   uint32_t groupCountZ)
1538{
1539   VN_CMD_ENQUEUE(vkCmdDispatchBase, commandBuffer, baseGroupX, baseGroupY,
1540                  baseGroupZ, groupCountX, groupCountY, groupCountZ);
1541}
1542
1543void
1544vn_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer,
1545                        uint32_t lineStippleFactor,
1546                        uint16_t lineStipplePattern)
1547{
1548   VN_CMD_ENQUEUE(vkCmdSetLineStippleEXT, commandBuffer, lineStippleFactor,
1549                  lineStipplePattern);
1550}
1551
1552void
1553vn_CmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer,
1554                           VkQueryPool queryPool,
1555                           uint32_t query,
1556                           VkQueryControlFlags flags,
1557                           uint32_t index)
1558{
1559   VN_CMD_ENQUEUE(vkCmdBeginQueryIndexedEXT, commandBuffer, queryPool, query,
1560                  flags, index);
1561}
1562
1563void
1564vn_CmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer,
1565                         VkQueryPool queryPool,
1566                         uint32_t query,
1567                         uint32_t index)
1568{
1569   VN_CMD_ENQUEUE(vkCmdEndQueryIndexedEXT, commandBuffer, queryPool, query,
1570                  index);
1571}
1572
1573void
1574vn_CmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer,
1575                                      uint32_t firstBinding,
1576                                      uint32_t bindingCount,
1577                                      const VkBuffer *pBuffers,
1578                                      const VkDeviceSize *pOffsets,
1579                                      const VkDeviceSize *pSizes)
1580{
1581   VN_CMD_ENQUEUE(vkCmdBindTransformFeedbackBuffersEXT, commandBuffer,
1582                  firstBinding, bindingCount, pBuffers, pOffsets, pSizes);
1583}
1584
1585void
1586vn_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,
1587                                uint32_t firstCounterBuffer,
1588                                uint32_t counterBufferCount,
1589                                const VkBuffer *pCounterBuffers,
1590                                const VkDeviceSize *pCounterBufferOffsets)
1591{
1592   VN_CMD_ENQUEUE(vkCmdBeginTransformFeedbackEXT, commandBuffer,
1593                  firstCounterBuffer, counterBufferCount, pCounterBuffers,
1594                  pCounterBufferOffsets);
1595}
1596
1597void
1598vn_CmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer,
1599                              uint32_t firstCounterBuffer,
1600                              uint32_t counterBufferCount,
1601                              const VkBuffer *pCounterBuffers,
1602                              const VkDeviceSize *pCounterBufferOffsets)
1603{
1604   VN_CMD_ENQUEUE(vkCmdEndTransformFeedbackEXT, commandBuffer,
1605                  firstCounterBuffer, counterBufferCount, pCounterBuffers,
1606                  pCounterBufferOffsets);
1607}
1608
1609void
1610vn_CmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer,
1611                               uint32_t instanceCount,
1612                               uint32_t firstInstance,
1613                               VkBuffer counterBuffer,
1614                               VkDeviceSize counterBufferOffset,
1615                               uint32_t counterOffset,
1616                               uint32_t vertexStride)
1617{
1618   VN_CMD_ENQUEUE(vkCmdDrawIndirectByteCountEXT, commandBuffer, instanceCount,
1619                  firstInstance, counterBuffer, counterBufferOffset,
1620                  counterOffset, vertexStride);
1621
1622   vn_cmd_count_draw_and_submit_on_batch_limit(
1623      vn_command_buffer_from_handle(commandBuffer));
1624}
1625
1626void
1627vn_CmdBindVertexBuffers2(VkCommandBuffer commandBuffer,
1628                         uint32_t firstBinding,
1629                         uint32_t bindingCount,
1630                         const VkBuffer *pBuffers,
1631                         const VkDeviceSize *pOffsets,
1632                         const VkDeviceSize *pSizes,
1633                         const VkDeviceSize *pStrides)
1634{
1635   VN_CMD_ENQUEUE(vkCmdBindVertexBuffers2, commandBuffer, firstBinding,
1636                  bindingCount, pBuffers, pOffsets, pSizes, pStrides);
1637}
1638
1639void
1640vn_CmdSetCullMode(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode)
1641{
1642   VN_CMD_ENQUEUE(vkCmdSetCullMode, commandBuffer, cullMode);
1643}
1644
1645void
1646vn_CmdSetDepthBoundsTestEnable(VkCommandBuffer commandBuffer,
1647                               VkBool32 depthBoundsTestEnable)
1648{
1649   VN_CMD_ENQUEUE(vkCmdSetDepthBoundsTestEnable, commandBuffer,
1650                  depthBoundsTestEnable);
1651}
1652
1653void
1654vn_CmdSetDepthCompareOp(VkCommandBuffer commandBuffer,
1655                        VkCompareOp depthCompareOp)
1656{
1657   VN_CMD_ENQUEUE(vkCmdSetDepthCompareOp, commandBuffer, depthCompareOp);
1658}
1659
1660void
1661vn_CmdSetDepthTestEnable(VkCommandBuffer commandBuffer,
1662                         VkBool32 depthTestEnable)
1663{
1664   VN_CMD_ENQUEUE(vkCmdSetDepthTestEnable, commandBuffer, depthTestEnable);
1665}
1666
1667void
1668vn_CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer,
1669                          VkBool32 depthWriteEnable)
1670{
1671   VN_CMD_ENQUEUE(vkCmdSetDepthWriteEnable, commandBuffer, depthWriteEnable);
1672}
1673
1674void
1675vn_CmdSetFrontFace(VkCommandBuffer commandBuffer, VkFrontFace frontFace)
1676{
1677   VN_CMD_ENQUEUE(vkCmdSetFrontFace, commandBuffer, frontFace);
1678}
1679
1680void
1681vn_CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer,
1682                           VkPrimitiveTopology primitiveTopology)
1683{
1684   VN_CMD_ENQUEUE(vkCmdSetPrimitiveTopology, commandBuffer,
1685                  primitiveTopology);
1686}
1687
1688void
1689vn_CmdSetScissorWithCount(VkCommandBuffer commandBuffer,
1690                          uint32_t scissorCount,
1691                          const VkRect2D *pScissors)
1692{
1693   VN_CMD_ENQUEUE(vkCmdSetScissorWithCount, commandBuffer, scissorCount,
1694                  pScissors);
1695}
1696
1697void
1698vn_CmdSetStencilOp(VkCommandBuffer commandBuffer,
1699                   VkStencilFaceFlags faceMask,
1700                   VkStencilOp failOp,
1701                   VkStencilOp passOp,
1702                   VkStencilOp depthFailOp,
1703                   VkCompareOp compareOp)
1704{
1705   VN_CMD_ENQUEUE(vkCmdSetStencilOp, commandBuffer, faceMask, failOp, passOp,
1706                  depthFailOp, compareOp);
1707}
1708
1709void
1710vn_CmdSetStencilTestEnable(VkCommandBuffer commandBuffer,
1711                           VkBool32 stencilTestEnable)
1712{
1713   VN_CMD_ENQUEUE(vkCmdSetStencilTestEnable, commandBuffer,
1714                  stencilTestEnable);
1715}
1716
1717void
1718vn_CmdSetViewportWithCount(VkCommandBuffer commandBuffer,
1719                           uint32_t viewportCount,
1720                           const VkViewport *pViewports)
1721{
1722   VN_CMD_ENQUEUE(vkCmdSetViewportWithCount, commandBuffer, viewportCount,
1723                  pViewports);
1724}
1725
1726void
1727vn_CmdSetDepthBiasEnable(VkCommandBuffer commandBuffer,
1728                         VkBool32 depthBiasEnable)
1729{
1730   VN_CMD_ENQUEUE(vkCmdSetDepthBiasEnable, commandBuffer, depthBiasEnable);
1731}
1732
1733void
1734vn_CmdSetLogicOpEXT(VkCommandBuffer commandBuffer, VkLogicOp logicOp)
1735{
1736   VN_CMD_ENQUEUE(vkCmdSetLogicOpEXT, commandBuffer, logicOp);
1737}
1738
1739void
1740vn_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer,
1741                               uint32_t patchControlPoints)
1742{
1743   VN_CMD_ENQUEUE(vkCmdSetPatchControlPointsEXT, commandBuffer,
1744                  patchControlPoints);
1745}
1746
1747void
1748vn_CmdSetPrimitiveRestartEnable(VkCommandBuffer commandBuffer,
1749                                VkBool32 primitiveRestartEnable)
1750{
1751   VN_CMD_ENQUEUE(vkCmdSetPrimitiveRestartEnable, commandBuffer,
1752                  primitiveRestartEnable);
1753}
1754
1755void
1756vn_CmdSetRasterizerDiscardEnable(VkCommandBuffer commandBuffer,
1757                                 VkBool32 rasterizerDiscardEnable)
1758{
1759   VN_CMD_ENQUEUE(vkCmdSetRasterizerDiscardEnable, commandBuffer,
1760                  rasterizerDiscardEnable);
1761}
1762
1763void
1764vn_CmdBeginConditionalRenderingEXT(
1765   VkCommandBuffer commandBuffer,
1766   const VkConditionalRenderingBeginInfoEXT *pConditionalRenderingBegin)
1767{
1768   VN_CMD_ENQUEUE(vkCmdBeginConditionalRenderingEXT, commandBuffer,
1769                  pConditionalRenderingBegin);
1770}
1771
1772void
1773vn_CmdEndConditionalRenderingEXT(VkCommandBuffer commandBuffer)
1774{
1775   VN_CMD_ENQUEUE(vkCmdEndConditionalRenderingEXT, commandBuffer);
1776}
1777