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