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
vn_image_memory_barrier_has_present_src(const VkImageMemoryBarrier * img_barriers,uint32_t count)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 *
vn_cmd_get_image_memory_barriers(struct vn_command_buffer * cmd,uint32_t count)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
vn_cmd_fix_image_memory_barrier(const struct vn_command_buffer * cmd,const VkImageMemoryBarrier * src_barrier,VkImageMemoryBarrier * out_barrier)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 *
vn_cmd_wait_events_fix_image_memory_barriers(struct vn_command_buffer * cmd,const VkImageMemoryBarrier * src_barriers,uint32_t count,uint32_t * out_transfer_count)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 *
vn_cmd_pipeline_barrier_fix_image_memory_barriers(struct vn_command_buffer * cmd,const VkImageMemoryBarrier * src_barriers,uint32_t count)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
vn_cmd_encode_memory_barriers(struct vn_command_buffer * cmd,VkPipelineStageFlags src_stage_mask,VkPipelineStageFlags dst_stage_mask,uint32_t buf_barrier_count,const VkBufferMemoryBarrier * buf_barriers,uint32_t img_barrier_count,const VkImageMemoryBarrier * img_barriers)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
vn_present_src_attachment_to_image_memory_barrier(const struct vn_image * img,const struct vn_present_src_attachment * att,VkImageMemoryBarrier * img_barrier)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
vn_cmd_transfer_present_src_images(struct vn_command_buffer * cmd,const struct vn_image * const * images,const struct vn_present_src_attachment * atts,uint32_t count)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
vn_cmd_begin_render_pass(struct vn_command_buffer * cmd,const struct vn_render_pass * pass,const struct vn_framebuffer * fb,const VkRenderPassBeginInfo * begin_info)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
vn_cmd_end_render_pass(struct vn_command_buffer * cmd)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
vn_CreateCommandPool(VkDevice device,const VkCommandPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkCommandPool * pCommandPool)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
vn_DestroyCommandPool(VkDevice device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)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
vn_ResetCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolResetFlags flags)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
vn_TrimCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolTrimFlags flags)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
vn_AllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)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
vn_FreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)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
vn_ResetCommandBuffer(VkCommandBuffer commandBuffer,VkCommandBufferResetFlags flags)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
vn_BeginCommandBuffer(VkCommandBuffer commandBuffer,const VkCommandBufferBeginInfo * pBeginInfo)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
vn_cmd_submit(struct vn_command_buffer * cmd)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
vn_EndCommandBuffer(VkCommandBuffer commandBuffer)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
vn_CmdBindPipeline(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipeline pipeline)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
vn_CmdSetViewport(VkCommandBuffer commandBuffer,uint32_t firstViewport,uint32_t viewportCount,const VkViewport * pViewports)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
vn_CmdSetScissor(VkCommandBuffer commandBuffer,uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * pScissors)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
vn_CmdSetLineWidth(VkCommandBuffer commandBuffer,float lineWidth)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
vn_CmdSetDepthBias(VkCommandBuffer commandBuffer,float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)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
vn_CmdSetBlendConstants(VkCommandBuffer commandBuffer,const float blendConstants[4])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
vn_CmdSetDepthBounds(VkCommandBuffer commandBuffer,float minDepthBounds,float maxDepthBounds)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
vn_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,VkStencilFaceFlags faceMask,uint32_t compareMask)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
vn_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,VkStencilFaceFlags faceMask,uint32_t writeMask)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
vn_CmdSetStencilReference(VkCommandBuffer commandBuffer,VkStencilFaceFlags faceMask,uint32_t reference)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
vn_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)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
vn_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkIndexType indexType)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
vn_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets)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
vn_CmdDraw(VkCommandBuffer commandBuffer,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)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
vn_CmdDrawIndexed(VkCommandBuffer commandBuffer,uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)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
vn_CmdDrawIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)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
vn_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)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
vn_CmdDrawIndirectCount(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)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
vn_CmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)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
vn_CmdDispatch(VkCommandBuffer commandBuffer,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)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
vn_CmdDispatchIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset)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
vn_CmdCopyBuffer(VkCommandBuffer commandBuffer,VkBuffer srcBuffer,VkBuffer dstBuffer,uint32_t regionCount,const VkBufferCopy * pRegions)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
vn_CmdCopyImage(VkCommandBuffer commandBuffer,VkImage srcImage,VkImageLayout srcImageLayout,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageCopy * pRegions)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
vn_CmdBlitImage(VkCommandBuffer commandBuffer,VkImage srcImage,VkImageLayout srcImageLayout,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageBlit * pRegions,VkFilter filter)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
vn_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,VkBuffer srcBuffer,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkBufferImageCopy * pRegions)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
vn_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer,VkImage srcImage,VkImageLayout srcImageLayout,VkBuffer dstBuffer,uint32_t regionCount,const VkBufferImageCopy * pRegions)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
vn_CmdUpdateBuffer(VkCommandBuffer commandBuffer,VkBuffer dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * pData)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
vn_CmdFillBuffer(VkCommandBuffer commandBuffer,VkBuffer dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)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
vn_CmdClearColorImage(VkCommandBuffer commandBuffer,VkImage image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)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
vn_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,VkImage image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)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
vn_CmdClearAttachments(VkCommandBuffer commandBuffer,uint32_t attachmentCount,const VkClearAttachment * pAttachments,uint32_t rectCount,const VkClearRect * pRects)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
vn_CmdResolveImage(VkCommandBuffer commandBuffer,VkImage srcImage,VkImageLayout srcImageLayout,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageResolve * pRegions)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
vn_CmdSetEvent(VkCommandBuffer commandBuffer,VkEvent event,VkPipelineStageFlags stageMask)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
vn_CmdResetEvent(VkCommandBuffer commandBuffer,VkEvent event,VkPipelineStageFlags stageMask)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
vn_CmdWaitEvents(VkCommandBuffer commandBuffer,uint32_t eventCount,const VkEvent * pEvents,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,uint32_t memoryBarrierCount,const VkMemoryBarrier * pMemoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * pBufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * pImageMemoryBarriers)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
vn_CmdPipelineBarrier(VkCommandBuffer commandBuffer,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkDependencyFlags dependencyFlags,uint32_t memoryBarrierCount,const VkMemoryBarrier * pMemoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * pBufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * pImageMemoryBarriers)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
vn_CmdBeginQuery(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query,VkQueryControlFlags flags)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
vn_CmdEndQuery(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query)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
vn_CmdResetQueryPool(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount)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
vn_CmdWriteTimestamp(VkCommandBuffer commandBuffer,VkPipelineStageFlagBits pipelineStage,VkQueryPool queryPool,uint32_t query)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
vn_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount,VkBuffer dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)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
vn_CmdPushConstants(VkCommandBuffer commandBuffer,VkPipelineLayout layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)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
vn_CmdBeginRenderPass(VkCommandBuffer commandBuffer,const VkRenderPassBeginInfo * pRenderPassBegin,VkSubpassContents contents)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
vn_CmdNextSubpass(VkCommandBuffer commandBuffer,VkSubpassContents contents)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
vn_CmdEndRenderPass(VkCommandBuffer commandBuffer)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
vn_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,const VkRenderPassBeginInfo * pRenderPassBegin,const VkSubpassBeginInfo * pSubpassBeginInfo)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
vn_CmdNextSubpass2(VkCommandBuffer commandBuffer,const VkSubpassBeginInfo * pSubpassBeginInfo,const VkSubpassEndInfo * pSubpassEndInfo)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
vn_CmdEndRenderPass2(VkCommandBuffer commandBuffer,const VkSubpassEndInfo * pSubpassEndInfo)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
vn_CmdExecuteCommands(VkCommandBuffer commandBuffer,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)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
vn_CmdSetDeviceMask(VkCommandBuffer commandBuffer,uint32_t deviceMask)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
vn_CmdDispatchBase(VkCommandBuffer commandBuffer,uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)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
vn_CmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query,VkQueryControlFlags flags,uint32_t index)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
vn_CmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query,uint32_t index)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
vn_CmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets,const VkDeviceSize * pSizes)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
vn_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,uint32_t firstCounterBuffer,uint32_t counterBufferCount,const VkBuffer * pCounterBuffers,const VkDeviceSize * pCounterBufferOffsets)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
vn_CmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer,uint32_t firstCounterBuffer,uint32_t counterBufferCount,const VkBuffer * pCounterBuffers,const VkDeviceSize * pCounterBufferOffsets)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
vn_CmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer,uint32_t instanceCount,uint32_t firstInstance,VkBuffer counterBuffer,VkDeviceSize counterBufferOffset,uint32_t counterOffset,uint32_t vertexStride)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