venus: initial support for command buffers
authorChia-I Wu <olvaffe@gmail.com>
Tue, 5 Nov 2019 20:53:15 +0000 (12:53 -0800)
committerMarge Bot <eric+marge@anholt.net>
Thu, 8 Apr 2021 17:15:37 +0000 (17:15 +0000)
Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-by: Ryan Neph <ryanneph@google.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5800>

src/virtio/vulkan/vn_common.h
src/virtio/vulkan/vn_device.c
src/virtio/vulkan/vn_device.h

index ffa6a3e..bd7f4fc 100644 (file)
@@ -73,6 +73,7 @@ struct vn_shader_module;
 struct vn_pipeline_layout;
 struct vn_pipeline_cache;
 struct vn_pipeline;
+struct vn_command_pool;
 struct vn_command_buffer;
 
 struct vn_cs_encoder;
index 23b7fc7..b8aae8d 100644 (file)
@@ -6590,3 +6590,1262 @@ vn_DestroyPipeline(VkDevice device,
    vn_object_base_fini(&pipeline->base);
    vk_free(alloc, pipeline);
 }
+
+/* command pool commands */
+
+VkResult
+vn_CreateCommandPool(VkDevice device,
+                     const VkCommandPoolCreateInfo *pCreateInfo,
+                     const VkAllocationCallbacks *pAllocator,
+                     VkCommandPool *pCommandPool)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   const VkAllocationCallbacks *alloc =
+      pAllocator ? pAllocator : &dev->base.base.alloc;
+
+   struct vn_command_pool *pool =
+      vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!pool)
+      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   vn_object_base_init(&pool->base, VK_OBJECT_TYPE_COMMAND_POOL, &dev->base);
+
+   pool->allocator = *alloc;
+   list_inithead(&pool->command_buffers);
+
+   VkCommandPool pool_handle = vn_command_pool_to_handle(pool);
+   vn_async_vkCreateCommandPool(dev->instance, device, pCreateInfo, NULL,
+                                &pool_handle);
+
+   *pCommandPool = pool_handle;
+
+   return VK_SUCCESS;
+}
+
+void
+vn_DestroyCommandPool(VkDevice device,
+                      VkCommandPool commandPool,
+                      const VkAllocationCallbacks *pAllocator)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool);
+   const VkAllocationCallbacks *alloc;
+
+   if (!pool)
+      return;
+
+   alloc = pAllocator ? pAllocator : &pool->allocator;
+
+   vn_async_vkDestroyCommandPool(dev->instance, device, commandPool, NULL);
+
+   list_for_each_entry_safe (struct vn_command_buffer, cmd,
+                             &pool->command_buffers, head) {
+      vn_cs_encoder_fini(&cmd->cs);
+      vn_object_base_fini(&cmd->base);
+      vk_free(alloc, cmd);
+   }
+
+   vn_object_base_fini(&pool->base);
+   vk_free(alloc, pool);
+}
+
+VkResult
+vn_ResetCommandPool(VkDevice device,
+                    VkCommandPool commandPool,
+                    VkCommandPoolResetFlags flags)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool);
+
+   list_for_each_entry_safe (struct vn_command_buffer, cmd,
+                             &pool->command_buffers, head) {
+      vn_cs_encoder_reset(&cmd->cs);
+      cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
+   }
+
+   vn_async_vkResetCommandPool(dev->instance, device, commandPool, flags);
+
+   return VK_SUCCESS;
+}
+
+void
+vn_TrimCommandPool(VkDevice device,
+                   VkCommandPool commandPool,
+                   VkCommandPoolTrimFlags flags)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+
+   vn_async_vkTrimCommandPool(dev->instance, device, commandPool, flags);
+}
+
+/* command buffer commands */
+
+VkResult
+vn_AllocateCommandBuffers(VkDevice device,
+                          const VkCommandBufferAllocateInfo *pAllocateInfo,
+                          VkCommandBuffer *pCommandBuffers)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_command_pool *pool =
+      vn_command_pool_from_handle(pAllocateInfo->commandPool);
+   const VkAllocationCallbacks *alloc = &pool->allocator;
+
+   for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
+      struct vn_command_buffer *cmd =
+         vk_zalloc(alloc, sizeof(*cmd), VN_DEFAULT_ALIGN,
+                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+      if (!cmd) {
+         for (uint32_t j = 0; j < i; j++) {
+            cmd = vn_command_buffer_from_handle(pCommandBuffers[j]);
+            vn_cs_encoder_fini(&cmd->cs);
+            list_del(&cmd->head);
+            vk_free(alloc, cmd);
+         }
+         memset(pCommandBuffers, 0,
+                sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount);
+         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+      }
+
+      vn_object_base_init(&cmd->base, VK_OBJECT_TYPE_COMMAND_BUFFER,
+                          &dev->base);
+      cmd->device = dev;
+
+      list_addtail(&cmd->head, &pool->command_buffers);
+
+      cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
+      vn_cs_encoder_init_indirect(&cmd->cs, dev->instance, 16 * 1024);
+
+      VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd);
+      pCommandBuffers[i] = cmd_handle;
+   }
+
+   vn_async_vkAllocateCommandBuffers(dev->instance, device, pAllocateInfo,
+                                     pCommandBuffers);
+
+   return VK_SUCCESS;
+}
+
+void
+vn_FreeCommandBuffers(VkDevice device,
+                      VkCommandPool commandPool,
+                      uint32_t commandBufferCount,
+                      const VkCommandBuffer *pCommandBuffers)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool);
+   const VkAllocationCallbacks *alloc = &pool->allocator;
+
+   vn_async_vkFreeCommandBuffers(dev->instance, device, commandPool,
+                                 commandBufferCount, pCommandBuffers);
+
+   for (uint32_t i = 0; i < commandBufferCount; i++) {
+      struct vn_command_buffer *cmd =
+         vn_command_buffer_from_handle(pCommandBuffers[i]);
+
+      if (!cmd)
+         continue;
+
+      vn_cs_encoder_fini(&cmd->cs);
+      list_del(&cmd->head);
+
+      vn_object_base_fini(&cmd->base);
+      vk_free(alloc, cmd);
+   }
+}
+
+VkResult
+vn_ResetCommandBuffer(VkCommandBuffer commandBuffer,
+                      VkCommandBufferResetFlags flags)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+
+   vn_cs_encoder_reset(&cmd->cs);
+   cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
+
+   vn_async_vkResetCommandBuffer(cmd->device->instance, commandBuffer, flags);
+
+   return VK_SUCCESS;
+}
+
+VkResult
+vn_BeginCommandBuffer(VkCommandBuffer commandBuffer,
+                      const VkCommandBufferBeginInfo *pBeginInfo)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   struct vn_instance *instance = cmd->device->instance;
+   size_t cmd_size;
+
+   vn_cs_encoder_reset(&cmd->cs);
+
+   cmd_size = vn_sizeof_vkBeginCommandBuffer(commandBuffer, pBeginInfo);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) {
+      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
+      return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+
+   vn_encode_vkBeginCommandBuffer(&cmd->cs, 0, commandBuffer, pBeginInfo);
+
+   cmd->state = VN_COMMAND_BUFFER_STATE_RECORDING;
+
+   return VK_SUCCESS;
+}
+
+VkResult
+vn_EndCommandBuffer(VkCommandBuffer commandBuffer)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   struct vn_instance *instance = cmd->device->instance;
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkEndCommandBuffer(commandBuffer);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) {
+      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
+      return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+
+   vn_encode_vkEndCommandBuffer(&cmd->cs, 0, commandBuffer);
+   vn_cs_encoder_commit(&cmd->cs);
+
+   if (vn_cs_encoder_get_fatal(&cmd->cs)) {
+      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
+      return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+
+   vn_instance_wait_roundtrip(instance, cmd->cs.current_buffer_roundtrip);
+   mtx_lock(&instance->ring.mutex);
+   VkResult result =
+      vn_instance_ring_submit_locked(instance, &cmd->cs, NULL, NULL);
+   mtx_unlock(&instance->ring.mutex);
+   if (result != VK_SUCCESS) {
+      cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
+      return vn_error(instance, result);
+   }
+
+   vn_cs_encoder_reset(&cmd->cs);
+
+   cmd->state = VN_COMMAND_BUFFER_STATE_EXECUTABLE;
+
+   return VK_SUCCESS;
+}
+
+void
+vn_CmdBindPipeline(VkCommandBuffer commandBuffer,
+                   VkPipelineBindPoint pipelineBindPoint,
+                   VkPipeline pipeline)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size =
+      vn_sizeof_vkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBindPipeline(&cmd->cs, 0, commandBuffer, pipelineBindPoint,
+                               pipeline);
+}
+
+void
+vn_CmdSetViewport(VkCommandBuffer commandBuffer,
+                  uint32_t firstViewport,
+                  uint32_t viewportCount,
+                  const VkViewport *pViewports)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetViewport(commandBuffer, firstViewport,
+                                         viewportCount, pViewports);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetViewport(&cmd->cs, 0, commandBuffer, firstViewport,
+                              viewportCount, pViewports);
+}
+
+void
+vn_CmdSetScissor(VkCommandBuffer commandBuffer,
+                 uint32_t firstScissor,
+                 uint32_t scissorCount,
+                 const VkRect2D *pScissors)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetScissor(commandBuffer, firstScissor,
+                                        scissorCount, pScissors);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetScissor(&cmd->cs, 0, commandBuffer, firstScissor,
+                             scissorCount, pScissors);
+}
+
+void
+vn_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetLineWidth(commandBuffer, lineWidth);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetLineWidth(&cmd->cs, 0, commandBuffer, lineWidth);
+}
+
+void
+vn_CmdSetDepthBias(VkCommandBuffer commandBuffer,
+                   float depthBiasConstantFactor,
+                   float depthBiasClamp,
+                   float depthBiasSlopeFactor)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size =
+      vn_sizeof_vkCmdSetDepthBias(commandBuffer, depthBiasConstantFactor,
+                                  depthBiasClamp, depthBiasSlopeFactor);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetDepthBias(&cmd->cs, 0, commandBuffer,
+                               depthBiasConstantFactor, depthBiasClamp,
+                               depthBiasSlopeFactor);
+}
+
+void
+vn_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
+                        const float blendConstants[4])
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetBlendConstants(commandBuffer, blendConstants);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetBlendConstants(&cmd->cs, 0, commandBuffer,
+                                    blendConstants);
+}
+
+void
+vn_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
+                     float minDepthBounds,
+                     float maxDepthBounds)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetDepthBounds(commandBuffer, minDepthBounds,
+                                            maxDepthBounds);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetDepthBounds(&cmd->cs, 0, commandBuffer, minDepthBounds,
+                                 maxDepthBounds);
+}
+
+void
+vn_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
+                            VkStencilFaceFlags faceMask,
+                            uint32_t compareMask)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetStencilCompareMask(commandBuffer, faceMask,
+                                                   compareMask);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetStencilCompareMask(&cmd->cs, 0, commandBuffer, faceMask,
+                                        compareMask);
+}
+
+void
+vn_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
+                          VkStencilFaceFlags faceMask,
+                          uint32_t writeMask)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size =
+      vn_sizeof_vkCmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetStencilWriteMask(&cmd->cs, 0, commandBuffer, faceMask,
+                                      writeMask);
+}
+
+void
+vn_CmdSetStencilReference(VkCommandBuffer commandBuffer,
+                          VkStencilFaceFlags faceMask,
+                          uint32_t reference)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size =
+      vn_sizeof_vkCmdSetStencilReference(commandBuffer, faceMask, reference);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetStencilReference(&cmd->cs, 0, commandBuffer, faceMask,
+                                      reference);
+}
+
+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)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdBindDescriptorSets(
+      commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount,
+      pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBindDescriptorSets(&cmd->cs, 0, commandBuffer,
+                                     pipelineBindPoint, layout, firstSet,
+                                     descriptorSetCount, pDescriptorSets,
+                                     dynamicOffsetCount, pDynamicOffsets);
+}
+
+void
+vn_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
+                      VkBuffer buffer,
+                      VkDeviceSize offset,
+                      VkIndexType indexType)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdBindIndexBuffer(commandBuffer, buffer, offset,
+                                             indexType);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBindIndexBuffer(&cmd->cs, 0, commandBuffer, buffer, offset,
+                                  indexType);
+}
+
+void
+vn_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
+                        uint32_t firstBinding,
+                        uint32_t bindingCount,
+                        const VkBuffer *pBuffers,
+                        const VkDeviceSize *pOffsets)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdBindVertexBuffers(
+      commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBindVertexBuffers(&cmd->cs, 0, commandBuffer, firstBinding,
+                                    bindingCount, pBuffers, pOffsets);
+}
+
+void
+vn_CmdDraw(VkCommandBuffer commandBuffer,
+           uint32_t vertexCount,
+           uint32_t instanceCount,
+           uint32_t firstVertex,
+           uint32_t firstInstance)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDraw(commandBuffer, vertexCount, instanceCount,
+                                  firstVertex, firstInstance);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDraw(&cmd->cs, 0, commandBuffer, vertexCount, instanceCount,
+                       firstVertex, firstInstance);
+}
+
+void
+vn_CmdDrawIndexed(VkCommandBuffer commandBuffer,
+                  uint32_t indexCount,
+                  uint32_t instanceCount,
+                  uint32_t firstIndex,
+                  int32_t vertexOffset,
+                  uint32_t firstInstance)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size =
+      vn_sizeof_vkCmdDrawIndexed(commandBuffer, indexCount, instanceCount,
+                                 firstIndex, vertexOffset, firstInstance);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDrawIndexed(&cmd->cs, 0, commandBuffer, indexCount,
+                              instanceCount, firstIndex, vertexOffset,
+                              firstInstance);
+}
+
+void
+vn_CmdDrawIndirect(VkCommandBuffer commandBuffer,
+                   VkBuffer buffer,
+                   VkDeviceSize offset,
+                   uint32_t drawCount,
+                   uint32_t stride)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDrawIndirect(commandBuffer, buffer, offset,
+                                          drawCount, stride);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDrawIndirect(&cmd->cs, 0, commandBuffer, buffer, offset,
+                               drawCount, stride);
+}
+
+void
+vn_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
+                          VkBuffer buffer,
+                          VkDeviceSize offset,
+                          uint32_t drawCount,
+                          uint32_t stride)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDrawIndexedIndirect(commandBuffer, buffer,
+                                                 offset, drawCount, stride);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDrawIndexedIndirect(&cmd->cs, 0, commandBuffer, buffer,
+                                      offset, drawCount, stride);
+}
+
+void
+vn_CmdDrawIndirectCount(VkCommandBuffer commandBuffer,
+                        VkBuffer buffer,
+                        VkDeviceSize offset,
+                        VkBuffer countBuffer,
+                        VkDeviceSize countBufferOffset,
+                        uint32_t maxDrawCount,
+                        uint32_t stride)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDrawIndirectCount(commandBuffer, buffer, offset,
+                                               countBuffer, countBufferOffset,
+                                               maxDrawCount, stride);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDrawIndirectCount(&cmd->cs, 0, commandBuffer, buffer,
+                                    offset, countBuffer, countBufferOffset,
+                                    maxDrawCount, stride);
+}
+
+void
+vn_CmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer,
+                               VkBuffer buffer,
+                               VkDeviceSize offset,
+                               VkBuffer countBuffer,
+                               VkDeviceSize countBufferOffset,
+                               uint32_t maxDrawCount,
+                               uint32_t stride)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDrawIndexedIndirectCount(
+      commandBuffer, buffer, offset, countBuffer, countBufferOffset,
+      maxDrawCount, stride);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDrawIndexedIndirectCount(
+      &cmd->cs, 0, commandBuffer, buffer, offset, countBuffer,
+      countBufferOffset, maxDrawCount, stride);
+}
+
+void
+vn_CmdDispatch(VkCommandBuffer commandBuffer,
+               uint32_t groupCountX,
+               uint32_t groupCountY,
+               uint32_t groupCountZ)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDispatch(commandBuffer, groupCountX, groupCountY,
+                                      groupCountZ);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDispatch(&cmd->cs, 0, commandBuffer, groupCountX,
+                           groupCountY, groupCountZ);
+}
+
+void
+vn_CmdDispatchIndirect(VkCommandBuffer commandBuffer,
+                       VkBuffer buffer,
+                       VkDeviceSize offset)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDispatchIndirect(commandBuffer, buffer, offset);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDispatchIndirect(&cmd->cs, 0, commandBuffer, buffer,
+                                   offset);
+}
+
+void
+vn_CmdCopyBuffer(VkCommandBuffer commandBuffer,
+                 VkBuffer srcBuffer,
+                 VkBuffer dstBuffer,
+                 uint32_t regionCount,
+                 const VkBufferCopy *pRegions)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer,
+                                        regionCount, pRegions);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdCopyBuffer(&cmd->cs, 0, commandBuffer, srcBuffer, dstBuffer,
+                             regionCount, pRegions);
+}
+
+void
+vn_CmdCopyImage(VkCommandBuffer commandBuffer,
+                VkImage srcImage,
+                VkImageLayout srcImageLayout,
+                VkImage dstImage,
+                VkImageLayout dstImageLayout,
+                uint32_t regionCount,
+                const VkImageCopy *pRegions)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdCopyImage(commandBuffer, srcImage,
+                                       srcImageLayout, dstImage,
+                                       dstImageLayout, regionCount, pRegions);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdCopyImage(&cmd->cs, 0, commandBuffer, srcImage,
+                            srcImageLayout, dstImage, dstImageLayout,
+                            regionCount, pRegions);
+}
+
+void
+vn_CmdBlitImage(VkCommandBuffer commandBuffer,
+                VkImage srcImage,
+                VkImageLayout srcImageLayout,
+                VkImage dstImage,
+                VkImageLayout dstImageLayout,
+                uint32_t regionCount,
+                const VkImageBlit *pRegions,
+                VkFilter filter)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdBlitImage(
+      commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
+      regionCount, pRegions, filter);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBlitImage(&cmd->cs, 0, commandBuffer, srcImage,
+                            srcImageLayout, dstImage, dstImageLayout,
+                            regionCount, pRegions, filter);
+}
+
+void
+vn_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,
+                        VkBuffer srcBuffer,
+                        VkImage dstImage,
+                        VkImageLayout dstImageLayout,
+                        uint32_t regionCount,
+                        const VkBufferImageCopy *pRegions)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size =
+      vn_sizeof_vkCmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage,
+                                       dstImageLayout, regionCount, pRegions);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdCopyBufferToImage(&cmd->cs, 0, commandBuffer, srcBuffer,
+                                    dstImage, dstImageLayout, regionCount,
+                                    pRegions);
+}
+
+void
+vn_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
+                        VkImage srcImage,
+                        VkImageLayout srcImageLayout,
+                        VkBuffer dstBuffer,
+                        uint32_t regionCount,
+                        const VkBufferImageCopy *pRegions)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdCopyImageToBuffer(commandBuffer, srcImage,
+                                               srcImageLayout, dstBuffer,
+                                               regionCount, pRegions);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdCopyImageToBuffer(&cmd->cs, 0, commandBuffer, srcImage,
+                                    srcImageLayout, dstBuffer, regionCount,
+                                    pRegions);
+}
+
+void
+vn_CmdUpdateBuffer(VkCommandBuffer commandBuffer,
+                   VkBuffer dstBuffer,
+                   VkDeviceSize dstOffset,
+                   VkDeviceSize dataSize,
+                   const void *pData)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset,
+                                          dataSize, pData);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdUpdateBuffer(&cmd->cs, 0, commandBuffer, dstBuffer,
+                               dstOffset, dataSize, pData);
+}
+
+void
+vn_CmdFillBuffer(VkCommandBuffer commandBuffer,
+                 VkBuffer dstBuffer,
+                 VkDeviceSize dstOffset,
+                 VkDeviceSize size,
+                 uint32_t data)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdFillBuffer(commandBuffer, dstBuffer, dstOffset,
+                                        size, data);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdFillBuffer(&cmd->cs, 0, commandBuffer, dstBuffer, dstOffset,
+                             size, data);
+}
+
+void
+vn_CmdClearColorImage(VkCommandBuffer commandBuffer,
+                      VkImage image,
+                      VkImageLayout imageLayout,
+                      const VkClearColorValue *pColor,
+                      uint32_t rangeCount,
+                      const VkImageSubresourceRange *pRanges)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdClearColorImage(
+      commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdClearColorImage(&cmd->cs, 0, commandBuffer, image,
+                                  imageLayout, pColor, rangeCount, pRanges);
+}
+
+void
+vn_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
+                             VkImage image,
+                             VkImageLayout imageLayout,
+                             const VkClearDepthStencilValue *pDepthStencil,
+                             uint32_t rangeCount,
+                             const VkImageSubresourceRange *pRanges)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdClearDepthStencilImage(
+      commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdClearDepthStencilImage(&cmd->cs, 0, commandBuffer, image,
+                                         imageLayout, pDepthStencil,
+                                         rangeCount, pRanges);
+}
+
+void
+vn_CmdClearAttachments(VkCommandBuffer commandBuffer,
+                       uint32_t attachmentCount,
+                       const VkClearAttachment *pAttachments,
+                       uint32_t rectCount,
+                       const VkClearRect *pRects)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdClearAttachments(
+      commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdClearAttachments(&cmd->cs, 0, commandBuffer,
+                                   attachmentCount, pAttachments, rectCount,
+                                   pRects);
+}
+
+void
+vn_CmdResolveImage(VkCommandBuffer commandBuffer,
+                   VkImage srcImage,
+                   VkImageLayout srcImageLayout,
+                   VkImage dstImage,
+                   VkImageLayout dstImageLayout,
+                   uint32_t regionCount,
+                   const VkImageResolve *pRegions)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdResolveImage(
+      commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
+      regionCount, pRegions);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdResolveImage(&cmd->cs, 0, commandBuffer, srcImage,
+                               srcImageLayout, dstImage, dstImageLayout,
+                               regionCount, pRegions);
+}
+
+void
+vn_CmdSetEvent(VkCommandBuffer commandBuffer,
+               VkEvent event,
+               VkPipelineStageFlags stageMask)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetEvent(commandBuffer, event, stageMask);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetEvent(&cmd->cs, 0, commandBuffer, event, stageMask);
+}
+
+void
+vn_CmdResetEvent(VkCommandBuffer commandBuffer,
+                 VkEvent event,
+                 VkPipelineStageFlags stageMask)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdResetEvent(commandBuffer, event, stageMask);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdResetEvent(&cmd->cs, 0, commandBuffer, event, stageMask);
+}
+
+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)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdWaitEvents(
+      commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask,
+      memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
+      pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdWaitEvents(&cmd->cs, 0, commandBuffer, eventCount, pEvents,
+                             srcStageMask, dstStageMask, memoryBarrierCount,
+                             pMemoryBarriers, bufferMemoryBarrierCount,
+                             pBufferMemoryBarriers, imageMemoryBarrierCount,
+                             pImageMemoryBarriers);
+}
+
+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)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdPipelineBarrier(
+      commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
+      memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
+      pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdPipelineBarrier(
+      &cmd->cs, 0, commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
+      memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
+      pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+void
+vn_CmdBeginQuery(VkCommandBuffer commandBuffer,
+                 VkQueryPool queryPool,
+                 uint32_t query,
+                 VkQueryControlFlags flags)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size =
+      vn_sizeof_vkCmdBeginQuery(commandBuffer, queryPool, query, flags);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBeginQuery(&cmd->cs, 0, commandBuffer, queryPool, query,
+                             flags);
+}
+
+void
+vn_CmdEndQuery(VkCommandBuffer commandBuffer,
+               VkQueryPool queryPool,
+               uint32_t query)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdEndQuery(commandBuffer, queryPool, query);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdEndQuery(&cmd->cs, 0, commandBuffer, queryPool, query);
+}
+
+void
+vn_CmdResetQueryPool(VkCommandBuffer commandBuffer,
+                     VkQueryPool queryPool,
+                     uint32_t firstQuery,
+                     uint32_t queryCount)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdResetQueryPool(commandBuffer, queryPool,
+                                            firstQuery, queryCount);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdResetQueryPool(&cmd->cs, 0, commandBuffer, queryPool,
+                                 firstQuery, queryCount);
+}
+
+void
+vn_CmdWriteTimestamp(VkCommandBuffer commandBuffer,
+                     VkPipelineStageFlagBits pipelineStage,
+                     VkQueryPool queryPool,
+                     uint32_t query)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdWriteTimestamp(commandBuffer, pipelineStage,
+                                            queryPool, query);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdWriteTimestamp(&cmd->cs, 0, commandBuffer, pipelineStage,
+                                 queryPool, query);
+}
+
+void
+vn_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
+                           VkQueryPool queryPool,
+                           uint32_t firstQuery,
+                           uint32_t queryCount,
+                           VkBuffer dstBuffer,
+                           VkDeviceSize dstOffset,
+                           VkDeviceSize stride,
+                           VkQueryResultFlags flags)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdCopyQueryPoolResults(
+      commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset,
+      stride, flags);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdCopyQueryPoolResults(&cmd->cs, 0, commandBuffer, queryPool,
+                                       firstQuery, queryCount, dstBuffer,
+                                       dstOffset, stride, flags);
+}
+
+void
+vn_CmdPushConstants(VkCommandBuffer commandBuffer,
+                    VkPipelineLayout layout,
+                    VkShaderStageFlags stageFlags,
+                    uint32_t offset,
+                    uint32_t size,
+                    const void *pValues)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdPushConstants(commandBuffer, layout, stageFlags,
+                                           offset, size, pValues);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdPushConstants(&cmd->cs, 0, commandBuffer, layout,
+                                stageFlags, offset, size, pValues);
+}
+
+void
+vn_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
+                      const VkRenderPassBeginInfo *pRenderPassBegin,
+                      VkSubpassContents contents)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdBeginRenderPass(commandBuffer, pRenderPassBegin,
+                                             contents);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBeginRenderPass(&cmd->cs, 0, commandBuffer,
+                                  pRenderPassBegin, contents);
+}
+
+void
+vn_CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdNextSubpass(commandBuffer, contents);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdNextSubpass(&cmd->cs, 0, commandBuffer, contents);
+}
+
+void
+vn_CmdEndRenderPass(VkCommandBuffer commandBuffer)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdEndRenderPass(commandBuffer);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdEndRenderPass(&cmd->cs, 0, commandBuffer);
+}
+
+void
+vn_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
+                       const VkRenderPassBeginInfo *pRenderPassBegin,
+                       const VkSubpassBeginInfo *pSubpassBeginInfo)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdBeginRenderPass2(commandBuffer, pRenderPassBegin,
+                                              pSubpassBeginInfo);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdBeginRenderPass2(&cmd->cs, 0, commandBuffer,
+                                   pRenderPassBegin, pSubpassBeginInfo);
+}
+
+void
+vn_CmdNextSubpass2(VkCommandBuffer commandBuffer,
+                   const VkSubpassBeginInfo *pSubpassBeginInfo,
+                   const VkSubpassEndInfo *pSubpassEndInfo)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdNextSubpass2(commandBuffer, pSubpassBeginInfo,
+                                          pSubpassEndInfo);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdNextSubpass2(&cmd->cs, 0, commandBuffer, pSubpassBeginInfo,
+                               pSubpassEndInfo);
+}
+
+void
+vn_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
+                     const VkSubpassEndInfo *pSubpassEndInfo)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdEndRenderPass2(commandBuffer, pSubpassEndInfo);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdEndRenderPass2(&cmd->cs, 0, commandBuffer, pSubpassEndInfo);
+}
+
+void
+vn_CmdExecuteCommands(VkCommandBuffer commandBuffer,
+                      uint32_t commandBufferCount,
+                      const VkCommandBuffer *pCommandBuffers)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdExecuteCommands(
+      commandBuffer, commandBufferCount, pCommandBuffers);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdExecuteCommands(&cmd->cs, 0, commandBuffer,
+                                  commandBufferCount, pCommandBuffers);
+}
+
+void
+vn_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdSetDeviceMask(commandBuffer, deviceMask);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdSetDeviceMask(&cmd->cs, 0, commandBuffer, deviceMask);
+}
+
+void
+vn_CmdDispatchBase(VkCommandBuffer commandBuffer,
+                   uint32_t baseGroupX,
+                   uint32_t baseGroupY,
+                   uint32_t baseGroupZ,
+                   uint32_t groupCountX,
+                   uint32_t groupCountY,
+                   uint32_t groupCountZ)
+{
+   struct vn_command_buffer *cmd =
+      vn_command_buffer_from_handle(commandBuffer);
+   size_t cmd_size;
+
+   cmd_size = vn_sizeof_vkCmdDispatchBase(commandBuffer, baseGroupX,
+                                          baseGroupY, baseGroupZ, groupCountX,
+                                          groupCountY, groupCountZ);
+   if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size))
+      return;
+
+   vn_encode_vkCmdDispatchBase(&cmd->cs, 0, commandBuffer, baseGroupX,
+                               baseGroupY, baseGroupZ, groupCountX,
+                               groupCountY, groupCountZ);
+}
index d7a2444..a0037d9 100644 (file)
@@ -381,10 +381,33 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(vn_pipeline,
                                VkPipeline,
                                VK_OBJECT_TYPE_PIPELINE)
 
+struct vn_command_pool {
+   struct vn_object_base base;
+
+   VkAllocationCallbacks allocator;
+   struct list_head command_buffers;
+};
+VK_DEFINE_NONDISP_HANDLE_CASTS(vn_command_pool,
+                               base.base,
+                               VkCommandPool,
+                               VK_OBJECT_TYPE_COMMAND_POOL)
+
+enum vn_command_buffer_state {
+   VN_COMMAND_BUFFER_STATE_INITIAL,
+   VN_COMMAND_BUFFER_STATE_RECORDING,
+   VN_COMMAND_BUFFER_STATE_EXECUTABLE,
+   VN_COMMAND_BUFFER_STATE_INVALID,
+};
+
 struct vn_command_buffer {
    struct vn_object_base base;
 
    struct vn_device *device;
+
+   struct list_head head;
+
+   enum vn_command_buffer_state state;
+   struct vn_cs_encoder cs;
 };
 VK_DEFINE_HANDLE_CASTS(vn_command_buffer,
                        base.base,