mesa/src/virtio/vulkan/vn_command_buffer.c

1776 lines
59 KiB
C

/*
* Copyright 2019 Google LLC
* SPDX-License-Identifier: MIT
*
* based in part on anv and radv which are:
* Copyright © 2015 Intel Corporation
* Copyright © 2016 Red Hat.
* Copyright © 2016 Bas Nieuwenhuizen
*/
#include "vn_command_buffer.h"
#include "venus-protocol/vn_protocol_driver_command_buffer.h"
#include "venus-protocol/vn_protocol_driver_command_pool.h"
#include "vn_device.h"
#include "vn_image.h"
#include "vn_render_pass.h"
#define VN_CMD_ENQUEUE(cmd_name, commandBuffer, ...) \
do { \
struct vn_command_buffer *_cmd = \
vn_command_buffer_from_handle(commandBuffer); \
size_t _cmd_size = vn_sizeof_##cmd_name(commandBuffer, ##__VA_ARGS__); \
\
if (vn_cs_encoder_reserve(&_cmd->cs, _cmd_size)) \
vn_encode_##cmd_name(&_cmd->cs, 0, commandBuffer, ##__VA_ARGS__); \
else \
_cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; \
} while (0)
static bool
vn_image_memory_barrier_has_present_src(
const VkImageMemoryBarrier *img_barriers, uint32_t count)
{
for (uint32_t i = 0; i < count; i++) {
if (img_barriers[i].oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ||
img_barriers[i].newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
return true;
}
return false;
}
static VkImageMemoryBarrier *
vn_cmd_get_image_memory_barriers(struct vn_command_buffer *cmd,
uint32_t count)
{
/* avoid shrinking in case of non efficient reallocation implementation */
if (count > cmd->builder.image_barrier_count) {
size_t size = sizeof(VkImageMemoryBarrier) * count;
VkImageMemoryBarrier *img_barriers =
vk_realloc(&cmd->allocator, cmd->builder.image_barriers, size,
VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!img_barriers)
return NULL;
/* update upon successful reallocation */
cmd->builder.image_barrier_count = count;
cmd->builder.image_barriers = img_barriers;
}
return cmd->builder.image_barriers;
}
/* About VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, the spec says
*
* VK_IMAGE_LAYOUT_PRESENT_SRC_KHR must only be used for presenting a
* presentable image for display. A swapchain's image must be transitioned
* to this layout before calling vkQueuePresentKHR, and must be
* transitioned away from this layout after calling vkAcquireNextImageKHR.
*
* That allows us to treat the layout internally as
*
* - VK_IMAGE_LAYOUT_GENERAL
* - VK_QUEUE_FAMILY_FOREIGN_EXT has the ownership, if the image is not a
* prime blit source
*
* while staying performant.
*
* About queue family ownerships, the spec says
*
* A queue family can take ownership of an image subresource or buffer
* range of a resource created with VK_SHARING_MODE_EXCLUSIVE, without an
* ownership transfer, in the same way as for a resource that was just
* created; however, taking ownership in this way has the effect that the
* contents of the image subresource or buffer range are undefined.
*
* It is unclear if that is applicable to external resources, which supposedly
* have the same semantics
*
* Binding a resource to a memory object shared between multiple Vulkan
* instances or other APIs does not change the ownership of the underlying
* memory. The first entity to access the resource implicitly acquires
* ownership. Accessing a resource backed by memory that is owned by a
* particular instance or API has the same semantics as accessing a
* VK_SHARING_MODE_EXCLUSIVE resource[...]
*
* We should get the spec clarified, or get rid of this completely broken code
* (TODO).
*
* Assuming a queue family can acquire the ownership implicitly when the
* contents are not needed, we do not need to worry about
* VK_IMAGE_LAYOUT_UNDEFINED. We can use VK_IMAGE_LAYOUT_PRESENT_SRC_KHR as
* the sole signal to trigger queue family ownership transfers.
*
* When the image has VK_SHARING_MODE_CONCURRENT, we can, and are required to,
* use VK_QUEUE_FAMILY_IGNORED as the other queue family whether we are
* transitioning to or from VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.
*
* When the image has VK_SHARING_MODE_EXCLUSIVE, we have to work out who the
* other queue family is. It is easier when the barrier does not also define
* a queue family ownership transfer (i.e., srcQueueFamilyIndex equals to
* dstQueueFamilyIndex). The other queue family must be the queue family the
* command buffer was allocated for.
*
* When the barrier also defines a queue family ownership transfer, it is
* submitted both to the source queue family to release the ownership and to
* the destination queue family to acquire the ownership. Depending on
* whether the barrier transitions to or from VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
* we are only interested in the ownership release or acquire respectively and
* should be careful to avoid double releases/acquires.
*
* I haven't followed all transition paths mentally to verify the correctness.
* I likely also violate some VUs or miss some cases below. They are
* hopefully fixable and are left as TODOs.
*/
static void
vn_cmd_fix_image_memory_barrier(const struct vn_command_buffer *cmd,
const VkImageMemoryBarrier *src_barrier,
VkImageMemoryBarrier *out_barrier)
{
const struct vn_image *img = vn_image_from_handle(src_barrier->image);
*out_barrier = *src_barrier;
/* no fix needed */
if (out_barrier->oldLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
out_barrier->newLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
return;
assert(img->wsi.is_wsi);
if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
return;
/* prime blit src or no layout transition */
if (img->wsi.is_prime_blit_src ||
out_barrier->oldLayout == out_barrier->newLayout) {
if (out_barrier->oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
out_barrier->oldLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
if (out_barrier->newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
out_barrier->newLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
return;
}
if (out_barrier->oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
out_barrier->oldLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
/* no availability operation needed */
out_barrier->srcAccessMask = 0;
const uint32_t dst_qfi = out_barrier->dstQueueFamilyIndex;
if (img->sharing_mode == VK_SHARING_MODE_CONCURRENT) {
out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
} else if (dst_qfi == out_barrier->srcQueueFamilyIndex ||
dst_qfi == cmd->queue_family_index) {
out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
out_barrier->dstQueueFamilyIndex = cmd->queue_family_index;
} else {
/* The barrier also defines a queue family ownership transfer, and
* this is the one that gets submitted to the source queue family to
* release the ownership. Skip both the transfer and the transition.
*/
out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
out_barrier->newLayout = out_barrier->oldLayout;
}
} else {
out_barrier->newLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
/* no visibility operation needed */
out_barrier->dstAccessMask = 0;
const uint32_t src_qfi = out_barrier->srcQueueFamilyIndex;
if (img->sharing_mode == VK_SHARING_MODE_CONCURRENT) {
out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
} else if (src_qfi == out_barrier->dstQueueFamilyIndex ||
src_qfi == cmd->queue_family_index) {
out_barrier->srcQueueFamilyIndex = cmd->queue_family_index;
out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
} else {
/* The barrier also defines a queue family ownership transfer, and
* this is the one that gets submitted to the destination queue
* family to acquire the ownership. Skip both the transfer and the
* transition.
*/
out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
out_barrier->oldLayout = out_barrier->newLayout;
}
}
}
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)
{
*out_transfer_count = 0;
if (cmd->builder.render_pass ||
!vn_image_memory_barrier_has_present_src(src_barriers, count))
return src_barriers;
VkImageMemoryBarrier *img_barriers =
vn_cmd_get_image_memory_barriers(cmd, count * 2);
if (!img_barriers) {
cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
return src_barriers;
}
/* vkCmdWaitEvents cannot be used for queue family ownership transfers.
* Nothing appears to be said about the submission order of image memory
* barriers in the same array. We take the liberty to move queue family
* ownership transfers to the tail.
*/
VkImageMemoryBarrier *transfer_barriers = img_barriers + count;
uint32_t transfer_count = 0;
uint32_t valid_count = 0;
for (uint32_t i = 0; i < count; i++) {
VkImageMemoryBarrier *img_barrier = &img_barriers[valid_count];
vn_cmd_fix_image_memory_barrier(cmd, &src_barriers[i], img_barrier);
if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
valid_count++;
continue;
}
if (img_barrier->srcQueueFamilyIndex ==
img_barrier->dstQueueFamilyIndex) {
valid_count++;
} else {
transfer_barriers[transfer_count++] = *img_barrier;
}
}
assert(valid_count + transfer_count == count);
if (transfer_count) {
/* copy back to the tail */
memcpy(&img_barriers[valid_count], transfer_barriers,
sizeof(*transfer_barriers) * transfer_count);
*out_transfer_count = transfer_count;
}
return img_barriers;
}
static const VkImageMemoryBarrier *
vn_cmd_pipeline_barrier_fix_image_memory_barriers(
struct vn_command_buffer *cmd,
const VkImageMemoryBarrier *src_barriers,
uint32_t count)
{
if (cmd->builder.render_pass ||
!vn_image_memory_barrier_has_present_src(src_barriers, count))
return src_barriers;
VkImageMemoryBarrier *img_barriers =
vn_cmd_get_image_memory_barriers(cmd, count);
if (!img_barriers) {
cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
return src_barriers;
}
for (uint32_t i = 0; i < count; i++) {
vn_cmd_fix_image_memory_barrier(cmd, &src_barriers[i],
&img_barriers[i]);
}
return img_barriers;
}
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)
{
const VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd);
VN_CMD_ENQUEUE(vkCmdPipelineBarrier, cmd_handle, src_stage_mask,
dst_stage_mask, 0, 0, NULL, buf_barrier_count, buf_barriers,
img_barrier_count, img_barriers);
}
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)
{
*img_barrier = (VkImageMemoryBarrier)
{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = att->src_access_mask,
.dstAccessMask = att->dst_access_mask,
.oldLayout = att->acquire ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
: VN_PRESENT_SRC_INTERNAL_LAYOUT,
.newLayout = att->acquire ? VN_PRESENT_SRC_INTERNAL_LAYOUT
: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
.image = vn_image_to_handle((struct vn_image *)img),
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1,
.layerCount = 1,
},
};
}
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)
{
VkImageMemoryBarrier *img_barriers =
vn_cmd_get_image_memory_barriers(cmd, count);
if (!img_barriers) {
cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
return;
}
VkPipelineStageFlags src_stage_mask = 0;
VkPipelineStageFlags dst_stage_mask = 0;
for (uint32_t i = 0; i < count; i++) {
src_stage_mask |= atts[i].src_stage_mask;
dst_stage_mask |= atts[i].dst_stage_mask;
vn_present_src_attachment_to_image_memory_barrier(images[i], &atts[i],
&img_barriers[i]);
vn_cmd_fix_image_memory_barrier(cmd, &img_barriers[i],
&img_barriers[i]);
}
if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
return;
vn_cmd_encode_memory_barriers(cmd, src_stage_mask, dst_stage_mask, 0, NULL,
count, img_barriers);
}
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)
{
cmd->builder.render_pass = pass;
cmd->builder.framebuffer = fb;
if (!pass->present_src_count ||
cmd->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
return;
/* find fb attachments */
const VkImageView *views;
ASSERTED uint32_t view_count;
if (fb->image_view_count) {
views = fb->image_views;
view_count = fb->image_view_count;
} else {
const VkRenderPassAttachmentBeginInfo *imageless_info =
vk_find_struct_const(begin_info->pNext,
RENDER_PASS_ATTACHMENT_BEGIN_INFO);
assert(imageless_info);
views = imageless_info->pAttachments;
view_count = imageless_info->attachmentCount;
}
const struct vn_image **images =
vk_alloc(&cmd->allocator, sizeof(*images) * pass->present_src_count,
VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!images) {
cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
return;
}
for (uint32_t i = 0; i < pass->present_src_count; i++) {
const uint32_t index = pass->present_src_attachments[i].index;
assert(index < view_count);
images[i] = vn_image_view_from_handle(views[index])->image;
}
if (pass->acquire_count) {
vn_cmd_transfer_present_src_images(
cmd, images, pass->present_src_attachments, pass->acquire_count);
}
cmd->builder.present_src_images = images;
}
static void
vn_cmd_end_render_pass(struct vn_command_buffer *cmd)
{
const struct vn_render_pass *pass = cmd->builder.render_pass;
cmd->builder.render_pass = NULL;
cmd->builder.framebuffer = NULL;
if (!pass->present_src_count || !cmd->builder.present_src_images)
return;
const struct vn_image **images = cmd->builder.present_src_images;
cmd->builder.present_src_images = NULL;
if (pass->release_count) {
vn_cmd_transfer_present_src_images(
cmd, images + pass->acquire_count,
pass->present_src_attachments + pass->acquire_count,
pass->release_count);
}
vk_free(&cmd->allocator, images);
}
/* command pool commands */
VkResult
vn_CreateCommandPool(VkDevice device,
const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkCommandPool *pCommandPool)
{
VN_TRACE_FUNC();
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;
pool->queue_family_index = pCreateInfo->queueFamilyIndex;
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)
{
VN_TRACE_FUNC();
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;
/* We must emit vkDestroyCommandPool before freeing the command buffers in
* pool->command_buffers. Otherwise, another thread might reuse their
* object ids while they still refer to the command buffers in the
* renderer.
*/
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)
{
VN_TRACE_FUNC();
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)
{
VN_TRACE_FUNC();
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)
{
VN_TRACE_FUNC();
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);
vn_object_base_fini(&cmd->base);
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;
cmd->allocator = pool->allocator;
cmd->level = pAllocateInfo->level;
cmd->queue_family_index = pool->queue_family_index;
list_addtail(&cmd->head, &pool->command_buffers);
cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
vn_cs_encoder_init(&cmd->cs, dev->instance,
VN_CS_ENCODER_STORAGE_SHMEM_POOL, 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)
{
VN_TRACE_FUNC();
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;
if (cmd->builder.image_barriers)
vk_free(alloc, cmd->builder.image_barriers);
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)
{
VN_TRACE_FUNC();
struct vn_command_buffer *cmd =
vn_command_buffer_from_handle(commandBuffer);
vn_cs_encoder_reset(&cmd->cs);
cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL;
cmd->draw_cmd_batched = 0;
vn_async_vkResetCommandBuffer(cmd->device->instance, commandBuffer, flags);
return VK_SUCCESS;
}
struct vn_command_buffer_begin_info {
VkCommandBufferBeginInfo begin;
VkCommandBufferInheritanceInfo inheritance;
VkCommandBufferInheritanceConditionalRenderingInfoEXT conditional_rendering;
bool has_inherited_pass;
};
static const VkCommandBufferBeginInfo *
vn_fix_command_buffer_begin_info(struct vn_command_buffer *cmd,
const VkCommandBufferBeginInfo *begin_info,
struct vn_command_buffer_begin_info *local)
{
local->has_inherited_pass = false;
if (!begin_info->pInheritanceInfo)
return begin_info;
const bool is_cmd_secondary =
cmd->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY;
const bool has_continue =
begin_info->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
const bool has_renderpass =
begin_info->pInheritanceInfo->renderPass != VK_NULL_HANDLE;
/* Can early-return if dynamic rendering is used and no structures need to
* be dropped from the pNext chain of VkCommandBufferInheritanceInfo.
*/
if (is_cmd_secondary && has_continue && !has_renderpass)
return begin_info;
local->begin = *begin_info;
if (!is_cmd_secondary) {
local->begin.pInheritanceInfo = NULL;
return &local->begin;
}
local->inheritance = *begin_info->pInheritanceInfo;
local->begin.pInheritanceInfo = &local->inheritance;
if (!has_continue) {
local->inheritance.framebuffer = VK_NULL_HANDLE;
local->inheritance.renderPass = VK_NULL_HANDLE;
local->inheritance.subpass = 0;
} else {
/* With early-returns above, it must be an inherited pass. */
local->has_inherited_pass = true;
}
/* Per spec, about VkCommandBufferInheritanceRenderingInfo:
*
* If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE, or
* VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT is not specified in
* VkCommandBufferBeginInfo::flags, parameters of this structure are
* ignored.
*/
VkBaseOutStructure *head = NULL;
VkBaseOutStructure *tail = NULL;
vk_foreach_struct_const(src, local->inheritance.pNext) {
void *pnext = NULL;
switch (src->sType) {
case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT:
memcpy(
&local->conditional_rendering, src,
sizeof(VkCommandBufferInheritanceConditionalRenderingInfoEXT));
pnext = &local->conditional_rendering;
break;
case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO:
default:
break;
}
if (pnext) {
if (!head)
head = pnext;
else
tail->pNext = pnext;
tail = pnext;
}
}
local->inheritance.pNext = head;
return &local->begin;
}
VkResult
vn_BeginCommandBuffer(VkCommandBuffer commandBuffer,
const VkCommandBufferBeginInfo *pBeginInfo)
{
VN_TRACE_FUNC();
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->draw_cmd_batched = 0;
struct vn_command_buffer_begin_info local_begin_info;
pBeginInfo =
vn_fix_command_buffer_begin_info(cmd, pBeginInfo, &local_begin_info);
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;
if (local_begin_info.has_inherited_pass) {
const VkCommandBufferInheritanceInfo *inheritance_info =
pBeginInfo->pInheritanceInfo;
vn_cmd_begin_render_pass(
cmd, vn_render_pass_from_handle(inheritance_info->renderPass),
vn_framebuffer_from_handle(inheritance_info->framebuffer), NULL);
}
return VK_SUCCESS;
}
static void
vn_cmd_submit(struct vn_command_buffer *cmd)
{
struct vn_instance *instance = cmd->device->instance;
if (cmd->state != VN_COMMAND_BUFFER_STATE_RECORDING)
return;
vn_cs_encoder_commit(&cmd->cs);
if (vn_cs_encoder_get_fatal(&cmd->cs)) {
cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
vn_cs_encoder_reset(&cmd->cs);
return;
}
if (unlikely(!instance->renderer->info.supports_blob_id_0))
vn_instance_wait_roundtrip(instance, cmd->cs.current_buffer_roundtrip);
if (vn_instance_ring_submit(instance, &cmd->cs) != VK_SUCCESS) {
cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
return;
}
vn_cs_encoder_reset(&cmd->cs);
cmd->draw_cmd_batched = 0;
}
static inline void
vn_cmd_count_draw_and_submit_on_batch_limit(struct vn_command_buffer *cmd)
{
if (++cmd->draw_cmd_batched >= vn_env.draw_cmd_batch_limit)
vn_cmd_submit(cmd);
}
VkResult
vn_EndCommandBuffer(VkCommandBuffer commandBuffer)
{
VN_TRACE_FUNC();
struct vn_command_buffer *cmd =
vn_command_buffer_from_handle(commandBuffer);
struct vn_instance *instance = cmd->device->instance;
size_t cmd_size;
if (cmd->state != VN_COMMAND_BUFFER_STATE_RECORDING)
return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
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_cmd_submit(cmd);
if (cmd->state == VN_COMMAND_BUFFER_STATE_INVALID)
return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
cmd->state = VN_COMMAND_BUFFER_STATE_EXECUTABLE;
return VK_SUCCESS;
}
void
vn_CmdBindPipeline(VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipeline pipeline)
{
VN_CMD_ENQUEUE(vkCmdBindPipeline, commandBuffer, pipelineBindPoint,
pipeline);
}
void
vn_CmdSetViewport(VkCommandBuffer commandBuffer,
uint32_t firstViewport,
uint32_t viewportCount,
const VkViewport *pViewports)
{
VN_CMD_ENQUEUE(vkCmdSetViewport, commandBuffer, firstViewport,
viewportCount, pViewports);
}
void
vn_CmdSetScissor(VkCommandBuffer commandBuffer,
uint32_t firstScissor,
uint32_t scissorCount,
const VkRect2D *pScissors)
{
VN_CMD_ENQUEUE(vkCmdSetScissor, commandBuffer, firstScissor, scissorCount,
pScissors);
}
void
vn_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)
{
VN_CMD_ENQUEUE(vkCmdSetLineWidth, commandBuffer, lineWidth);
}
void
vn_CmdSetDepthBias(VkCommandBuffer commandBuffer,
float depthBiasConstantFactor,
float depthBiasClamp,
float depthBiasSlopeFactor)
{
VN_CMD_ENQUEUE(vkCmdSetDepthBias, commandBuffer, depthBiasConstantFactor,
depthBiasClamp, depthBiasSlopeFactor);
}
void
vn_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
const float blendConstants[4])
{
VN_CMD_ENQUEUE(vkCmdSetBlendConstants, commandBuffer, blendConstants);
}
void
vn_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
float minDepthBounds,
float maxDepthBounds)
{
VN_CMD_ENQUEUE(vkCmdSetDepthBounds, commandBuffer, minDepthBounds,
maxDepthBounds);
}
void
vn_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t compareMask)
{
VN_CMD_ENQUEUE(vkCmdSetStencilCompareMask, commandBuffer, faceMask,
compareMask);
}
void
vn_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t writeMask)
{
VN_CMD_ENQUEUE(vkCmdSetStencilWriteMask, commandBuffer, faceMask,
writeMask);
}
void
vn_CmdSetStencilReference(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t reference)
{
VN_CMD_ENQUEUE(vkCmdSetStencilReference, 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)
{
VN_CMD_ENQUEUE(vkCmdBindDescriptorSets, commandBuffer, pipelineBindPoint,
layout, firstSet, descriptorSetCount, pDescriptorSets,
dynamicOffsetCount, pDynamicOffsets);
}
void
vn_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
VN_CMD_ENQUEUE(vkCmdBindIndexBuffer, commandBuffer, buffer, offset,
indexType);
}
void
vn_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *pBuffers,
const VkDeviceSize *pOffsets)
{
VN_CMD_ENQUEUE(vkCmdBindVertexBuffers, commandBuffer, firstBinding,
bindingCount, pBuffers, pOffsets);
}
void
vn_CmdDraw(VkCommandBuffer commandBuffer,
uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
VN_CMD_ENQUEUE(vkCmdDraw, commandBuffer, vertexCount, instanceCount,
firstVertex, firstInstance);
vn_cmd_count_draw_and_submit_on_batch_limit(
vn_command_buffer_from_handle(commandBuffer));
}
void
vn_CmdBeginRendering(VkCommandBuffer commandBuffer,
const VkRenderingInfo *pRenderingInfo)
{
VN_CMD_ENQUEUE(vkCmdBeginRendering, commandBuffer, pRenderingInfo);
}
void
vn_CmdEndRendering(VkCommandBuffer commandBuffer)
{
VN_CMD_ENQUEUE(vkCmdEndRendering, commandBuffer);
}
void
vn_CmdDrawIndexed(VkCommandBuffer commandBuffer,
uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
VN_CMD_ENQUEUE(vkCmdDrawIndexed, commandBuffer, indexCount, instanceCount,
firstIndex, vertexOffset, firstInstance);
vn_cmd_count_draw_and_submit_on_batch_limit(
vn_command_buffer_from_handle(commandBuffer));
}
void
vn_CmdDrawIndirect(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
VN_CMD_ENQUEUE(vkCmdDrawIndirect, commandBuffer, buffer, offset, drawCount,
stride);
vn_cmd_count_draw_and_submit_on_batch_limit(
vn_command_buffer_from_handle(commandBuffer));
}
void
vn_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
VN_CMD_ENQUEUE(vkCmdDrawIndexedIndirect, commandBuffer, buffer, offset,
drawCount, stride);
vn_cmd_count_draw_and_submit_on_batch_limit(
vn_command_buffer_from_handle(commandBuffer));
}
void
vn_CmdDrawIndirectCount(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset,
VkBuffer countBuffer,
VkDeviceSize countBufferOffset,
uint32_t maxDrawCount,
uint32_t stride)
{
VN_CMD_ENQUEUE(vkCmdDrawIndirectCount, commandBuffer, buffer, offset,
countBuffer, countBufferOffset, maxDrawCount, stride);
vn_cmd_count_draw_and_submit_on_batch_limit(
vn_command_buffer_from_handle(commandBuffer));
}
void
vn_CmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset,
VkBuffer countBuffer,
VkDeviceSize countBufferOffset,
uint32_t maxDrawCount,
uint32_t stride)
{
VN_CMD_ENQUEUE(vkCmdDrawIndexedIndirectCount, commandBuffer, buffer,
offset, countBuffer, countBufferOffset, maxDrawCount,
stride);
vn_cmd_count_draw_and_submit_on_batch_limit(
vn_command_buffer_from_handle(commandBuffer));
}
void
vn_CmdDispatch(VkCommandBuffer commandBuffer,
uint32_t groupCountX,
uint32_t groupCountY,
uint32_t groupCountZ)
{
VN_CMD_ENQUEUE(vkCmdDispatch, commandBuffer, groupCountX, groupCountY,
groupCountZ);
}
void
vn_CmdDispatchIndirect(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset)
{
VN_CMD_ENQUEUE(vkCmdDispatchIndirect, commandBuffer, buffer, offset);
}
void
vn_CmdCopyBuffer(VkCommandBuffer commandBuffer,
VkBuffer srcBuffer,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferCopy *pRegions)
{
VN_CMD_ENQUEUE(vkCmdCopyBuffer, commandBuffer, srcBuffer, dstBuffer,
regionCount, pRegions);
}
void
vn_CmdCopyBuffer2(VkCommandBuffer commandBuffer,
const VkCopyBufferInfo2 *pCopyBufferInfo)
{
VN_CMD_ENQUEUE(vkCmdCopyBuffer2, commandBuffer, pCopyBufferInfo);
}
void
vn_CmdCopyImage(VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageCopy *pRegions)
{
VN_CMD_ENQUEUE(vkCmdCopyImage, commandBuffer, srcImage, srcImageLayout,
dstImage, dstImageLayout, regionCount, pRegions);
}
void
vn_CmdCopyImage2(VkCommandBuffer commandBuffer,
const VkCopyImageInfo2 *pCopyImageInfo)
{
VN_CMD_ENQUEUE(vkCmdCopyImage2, commandBuffer, pCopyImageInfo);
}
void
vn_CmdBlitImage(VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit *pRegions,
VkFilter filter)
{
VN_CMD_ENQUEUE(vkCmdBlitImage, commandBuffer, srcImage, srcImageLayout,
dstImage, dstImageLayout, regionCount, pRegions, filter);
}
void
vn_CmdBlitImage2(VkCommandBuffer commandBuffer,
const VkBlitImageInfo2 *pBlitImageInfo)
{
VN_CMD_ENQUEUE(vkCmdBlitImage2, commandBuffer, pBlitImageInfo);
}
void
vn_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,
VkBuffer srcBuffer,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkBufferImageCopy *pRegions)
{
VN_CMD_ENQUEUE(vkCmdCopyBufferToImage, commandBuffer, srcBuffer, dstImage,
dstImageLayout, regionCount, pRegions);
}
void
vn_CmdCopyBufferToImage2(
VkCommandBuffer commandBuffer,
const VkCopyBufferToImageInfo2 *pCopyBufferToImageInfo)
{
VN_CMD_ENQUEUE(vkCmdCopyBufferToImage2, commandBuffer,
pCopyBufferToImageInfo);
}
static bool
vn_needs_prime_blit(VkImage src_image, VkImageLayout src_image_layout)
{
if (src_image_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
VN_PRESENT_SRC_INTERNAL_LAYOUT != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
/* sanity check */
ASSERTED const struct vn_image *img = vn_image_from_handle(src_image);
assert(img->wsi.is_wsi && img->wsi.is_prime_blit_src);
return true;
}
return false;
}
static void
vn_transition_prime_layout(struct vn_command_buffer *cmd, VkBuffer dst_buffer)
{
const VkBufferMemoryBarrier buf_barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.srcQueueFamilyIndex = cmd->queue_family_index,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT,
.buffer = dst_buffer,
.size = VK_WHOLE_SIZE,
};
vn_cmd_encode_memory_barriers(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 1,
&buf_barrier, 0, NULL);
}
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);
bool prime_blit = vn_needs_prime_blit(srcImage, srcImageLayout);
if (prime_blit)
srcImageLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
VN_CMD_ENQUEUE(vkCmdCopyImageToBuffer, commandBuffer, srcImage,
srcImageLayout, dstBuffer, regionCount, pRegions);
if (prime_blit)
vn_transition_prime_layout(cmd, dstBuffer);
}
void
vn_CmdCopyImageToBuffer2(
VkCommandBuffer commandBuffer,
const VkCopyImageToBufferInfo2 *pCopyImageToBufferInfo)
{
struct vn_command_buffer *cmd =
vn_command_buffer_from_handle(commandBuffer);
struct VkCopyImageToBufferInfo2 copy_info = *pCopyImageToBufferInfo;
bool prime_blit =
vn_needs_prime_blit(copy_info.srcImage, copy_info.srcImageLayout);
if (prime_blit)
copy_info.srcImageLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;
VN_CMD_ENQUEUE(vkCmdCopyImageToBuffer2, commandBuffer, &copy_info);
if (prime_blit)
vn_transition_prime_layout(cmd, copy_info.dstBuffer);
}
void
vn_CmdUpdateBuffer(VkCommandBuffer commandBuffer,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void *pData)
{
VN_CMD_ENQUEUE(vkCmdUpdateBuffer, commandBuffer, dstBuffer, dstOffset,
dataSize, pData);
}
void
vn_CmdFillBuffer(VkCommandBuffer commandBuffer,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize size,
uint32_t data)
{
VN_CMD_ENQUEUE(vkCmdFillBuffer, commandBuffer, dstBuffer, dstOffset, size,
data);
}
void
vn_CmdClearColorImage(VkCommandBuffer commandBuffer,
VkImage image,
VkImageLayout imageLayout,
const VkClearColorValue *pColor,
uint32_t rangeCount,
const VkImageSubresourceRange *pRanges)
{
VN_CMD_ENQUEUE(vkCmdClearColorImage, commandBuffer, image, imageLayout,
pColor, rangeCount, pRanges);
}
void
vn_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
VkImage image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue *pDepthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange *pRanges)
{
VN_CMD_ENQUEUE(vkCmdClearDepthStencilImage, commandBuffer, image,
imageLayout, pDepthStencil, rangeCount, pRanges);
}
void
vn_CmdClearAttachments(VkCommandBuffer commandBuffer,
uint32_t attachmentCount,
const VkClearAttachment *pAttachments,
uint32_t rectCount,
const VkClearRect *pRects)
{
VN_CMD_ENQUEUE(vkCmdClearAttachments, commandBuffer, attachmentCount,
pAttachments, rectCount, pRects);
}
void
vn_CmdResolveImage(VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageResolve *pRegions)
{
VN_CMD_ENQUEUE(vkCmdResolveImage, commandBuffer, srcImage, srcImageLayout,
dstImage, dstImageLayout, regionCount, pRegions);
}
void
vn_CmdResolveImage2(VkCommandBuffer commandBuffer,
const VkResolveImageInfo2 *pResolveImageInfo)
{
VN_CMD_ENQUEUE(vkCmdResolveImage2, commandBuffer, pResolveImageInfo);
}
void
vn_CmdSetEvent(VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask)
{
VN_CMD_ENQUEUE(vkCmdSetEvent, commandBuffer, event, stageMask);
vn_feedback_event_cmd_record(commandBuffer, event, stageMask,
VK_EVENT_SET);
}
void
vn_CmdResetEvent(VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask)
{
VN_CMD_ENQUEUE(vkCmdResetEvent, commandBuffer, event, stageMask);
vn_feedback_event_cmd_record(commandBuffer, event, stageMask,
VK_EVENT_RESET);
}
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);
uint32_t transfer_count;
pImageMemoryBarriers = vn_cmd_wait_events_fix_image_memory_barriers(
cmd, pImageMemoryBarriers, imageMemoryBarrierCount, &transfer_count);
imageMemoryBarrierCount -= transfer_count;
VN_CMD_ENQUEUE(vkCmdWaitEvents, commandBuffer, eventCount, pEvents,
srcStageMask, dstStageMask, memoryBarrierCount,
pMemoryBarriers, bufferMemoryBarrierCount,
pBufferMemoryBarriers, imageMemoryBarrierCount,
pImageMemoryBarriers);
if (transfer_count) {
pImageMemoryBarriers += imageMemoryBarrierCount;
vn_cmd_encode_memory_barriers(cmd, srcStageMask, dstStageMask, 0, NULL,
transfer_count, 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);
pImageMemoryBarriers = vn_cmd_pipeline_barrier_fix_image_memory_barriers(
cmd, pImageMemoryBarriers, imageMemoryBarrierCount);
VN_CMD_ENQUEUE(vkCmdPipelineBarrier, commandBuffer, srcStageMask,
dstStageMask, dependencyFlags, memoryBarrierCount,
pMemoryBarriers, bufferMemoryBarrierCount,
pBufferMemoryBarriers, imageMemoryBarrierCount,
pImageMemoryBarriers);
}
void
vn_CmdBeginQuery(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
uint32_t query,
VkQueryControlFlags flags)
{
VN_CMD_ENQUEUE(vkCmdBeginQuery, commandBuffer, queryPool, query, flags);
}
void
vn_CmdEndQuery(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
uint32_t query)
{
VN_CMD_ENQUEUE(vkCmdEndQuery, commandBuffer, queryPool, query);
}
void
vn_CmdResetQueryPool(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
uint32_t firstQuery,
uint32_t queryCount)
{
VN_CMD_ENQUEUE(vkCmdResetQueryPool, commandBuffer, queryPool, firstQuery,
queryCount);
}
void
vn_CmdWriteTimestamp(VkCommandBuffer commandBuffer,
VkPipelineStageFlagBits pipelineStage,
VkQueryPool queryPool,
uint32_t query)
{
VN_CMD_ENQUEUE(vkCmdWriteTimestamp, 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)
{
VN_CMD_ENQUEUE(vkCmdCopyQueryPoolResults, 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)
{
VN_CMD_ENQUEUE(vkCmdPushConstants, 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);
vn_cmd_begin_render_pass(
cmd, vn_render_pass_from_handle(pRenderPassBegin->renderPass),
vn_framebuffer_from_handle(pRenderPassBegin->framebuffer),
pRenderPassBegin);
VN_CMD_ENQUEUE(vkCmdBeginRenderPass, commandBuffer, pRenderPassBegin,
contents);
}
void
vn_CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
{
VN_CMD_ENQUEUE(vkCmdNextSubpass, commandBuffer, contents);
}
void
vn_CmdEndRenderPass(VkCommandBuffer commandBuffer)
{
struct vn_command_buffer *cmd =
vn_command_buffer_from_handle(commandBuffer);
VN_CMD_ENQUEUE(vkCmdEndRenderPass, commandBuffer);
vn_cmd_end_render_pass(cmd);
}
void
vn_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo *pRenderPassBegin,
const VkSubpassBeginInfo *pSubpassBeginInfo)
{
struct vn_command_buffer *cmd =
vn_command_buffer_from_handle(commandBuffer);
vn_cmd_begin_render_pass(
cmd, vn_render_pass_from_handle(pRenderPassBegin->renderPass),
vn_framebuffer_from_handle(pRenderPassBegin->framebuffer),
pRenderPassBegin);
VN_CMD_ENQUEUE(vkCmdBeginRenderPass2, commandBuffer, pRenderPassBegin,
pSubpassBeginInfo);
}
void
vn_CmdNextSubpass2(VkCommandBuffer commandBuffer,
const VkSubpassBeginInfo *pSubpassBeginInfo,
const VkSubpassEndInfo *pSubpassEndInfo)
{
VN_CMD_ENQUEUE(vkCmdNextSubpass2, commandBuffer, pSubpassBeginInfo,
pSubpassEndInfo);
}
void
vn_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
const VkSubpassEndInfo *pSubpassEndInfo)
{
struct vn_command_buffer *cmd =
vn_command_buffer_from_handle(commandBuffer);
VN_CMD_ENQUEUE(vkCmdEndRenderPass2, commandBuffer, pSubpassEndInfo);
vn_cmd_end_render_pass(cmd);
}
void
vn_CmdExecuteCommands(VkCommandBuffer commandBuffer,
uint32_t commandBufferCount,
const VkCommandBuffer *pCommandBuffers)
{
VN_CMD_ENQUEUE(vkCmdExecuteCommands, commandBuffer, commandBufferCount,
pCommandBuffers);
}
void
vn_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
{
VN_CMD_ENQUEUE(vkCmdSetDeviceMask, 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)
{
VN_CMD_ENQUEUE(vkCmdDispatchBase, commandBuffer, baseGroupX, baseGroupY,
baseGroupZ, groupCountX, groupCountY, groupCountZ);
}
void
vn_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer,
uint32_t lineStippleFactor,
uint16_t lineStipplePattern)
{
VN_CMD_ENQUEUE(vkCmdSetLineStippleEXT, commandBuffer, lineStippleFactor,
lineStipplePattern);
}
void
vn_CmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
uint32_t query,
VkQueryControlFlags flags,
uint32_t index)
{
VN_CMD_ENQUEUE(vkCmdBeginQueryIndexedEXT, commandBuffer, queryPool, query,
flags, index);
}
void
vn_CmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
uint32_t query,
uint32_t index)
{
VN_CMD_ENQUEUE(vkCmdEndQueryIndexedEXT, commandBuffer, queryPool, query,
index);
}
void
vn_CmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *pBuffers,
const VkDeviceSize *pOffsets,
const VkDeviceSize *pSizes)
{
VN_CMD_ENQUEUE(vkCmdBindTransformFeedbackBuffersEXT, commandBuffer,
firstBinding, bindingCount, pBuffers, pOffsets, pSizes);
}
void
vn_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,
uint32_t firstCounterBuffer,
uint32_t counterBufferCount,
const VkBuffer *pCounterBuffers,
const VkDeviceSize *pCounterBufferOffsets)
{
VN_CMD_ENQUEUE(vkCmdBeginTransformFeedbackEXT, commandBuffer,
firstCounterBuffer, counterBufferCount, pCounterBuffers,
pCounterBufferOffsets);
}
void
vn_CmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer,
uint32_t firstCounterBuffer,
uint32_t counterBufferCount,
const VkBuffer *pCounterBuffers,
const VkDeviceSize *pCounterBufferOffsets)
{
VN_CMD_ENQUEUE(vkCmdEndTransformFeedbackEXT, commandBuffer,
firstCounterBuffer, counterBufferCount, pCounterBuffers,
pCounterBufferOffsets);
}
void
vn_CmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer,
uint32_t instanceCount,
uint32_t firstInstance,
VkBuffer counterBuffer,
VkDeviceSize counterBufferOffset,
uint32_t counterOffset,
uint32_t vertexStride)
{
VN_CMD_ENQUEUE(vkCmdDrawIndirectByteCountEXT, commandBuffer, instanceCount,
firstInstance, counterBuffer, counterBufferOffset,
counterOffset, vertexStride);
vn_cmd_count_draw_and_submit_on_batch_limit(
vn_command_buffer_from_handle(commandBuffer));
}
void
vn_CmdBindVertexBuffers2(VkCommandBuffer commandBuffer,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *pBuffers,
const VkDeviceSize *pOffsets,
const VkDeviceSize *pSizes,
const VkDeviceSize *pStrides)
{
VN_CMD_ENQUEUE(vkCmdBindVertexBuffers2, commandBuffer, firstBinding,
bindingCount, pBuffers, pOffsets, pSizes, pStrides);
}
void
vn_CmdSetCullMode(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode)
{
VN_CMD_ENQUEUE(vkCmdSetCullMode, commandBuffer, cullMode);
}
void
vn_CmdSetDepthBoundsTestEnable(VkCommandBuffer commandBuffer,
VkBool32 depthBoundsTestEnable)
{
VN_CMD_ENQUEUE(vkCmdSetDepthBoundsTestEnable, commandBuffer,
depthBoundsTestEnable);
}
void
vn_CmdSetDepthCompareOp(VkCommandBuffer commandBuffer,
VkCompareOp depthCompareOp)
{
VN_CMD_ENQUEUE(vkCmdSetDepthCompareOp, commandBuffer, depthCompareOp);
}
void
vn_CmdSetDepthTestEnable(VkCommandBuffer commandBuffer,
VkBool32 depthTestEnable)
{
VN_CMD_ENQUEUE(vkCmdSetDepthTestEnable, commandBuffer, depthTestEnable);
}
void
vn_CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer,
VkBool32 depthWriteEnable)
{
VN_CMD_ENQUEUE(vkCmdSetDepthWriteEnable, commandBuffer, depthWriteEnable);
}
void
vn_CmdSetFrontFace(VkCommandBuffer commandBuffer, VkFrontFace frontFace)
{
VN_CMD_ENQUEUE(vkCmdSetFrontFace, commandBuffer, frontFace);
}
void
vn_CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer,
VkPrimitiveTopology primitiveTopology)
{
VN_CMD_ENQUEUE(vkCmdSetPrimitiveTopology, commandBuffer,
primitiveTopology);
}
void
vn_CmdSetScissorWithCount(VkCommandBuffer commandBuffer,
uint32_t scissorCount,
const VkRect2D *pScissors)
{
VN_CMD_ENQUEUE(vkCmdSetScissorWithCount, commandBuffer, scissorCount,
pScissors);
}
void
vn_CmdSetStencilOp(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
VkStencilOp failOp,
VkStencilOp passOp,
VkStencilOp depthFailOp,
VkCompareOp compareOp)
{
VN_CMD_ENQUEUE(vkCmdSetStencilOp, commandBuffer, faceMask, failOp, passOp,
depthFailOp, compareOp);
}
void
vn_CmdSetStencilTestEnable(VkCommandBuffer commandBuffer,
VkBool32 stencilTestEnable)
{
VN_CMD_ENQUEUE(vkCmdSetStencilTestEnable, commandBuffer,
stencilTestEnable);
}
void
vn_CmdSetViewportWithCount(VkCommandBuffer commandBuffer,
uint32_t viewportCount,
const VkViewport *pViewports)
{
VN_CMD_ENQUEUE(vkCmdSetViewportWithCount, commandBuffer, viewportCount,
pViewports);
}
void
vn_CmdSetDepthBiasEnable(VkCommandBuffer commandBuffer,
VkBool32 depthBiasEnable)
{
VN_CMD_ENQUEUE(vkCmdSetDepthBiasEnable, commandBuffer, depthBiasEnable);
}
void
vn_CmdSetLogicOpEXT(VkCommandBuffer commandBuffer, VkLogicOp logicOp)
{
VN_CMD_ENQUEUE(vkCmdSetLogicOpEXT, commandBuffer, logicOp);
}
void
vn_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer,
uint32_t patchControlPoints)
{
VN_CMD_ENQUEUE(vkCmdSetPatchControlPointsEXT, commandBuffer,
patchControlPoints);
}
void
vn_CmdSetPrimitiveRestartEnable(VkCommandBuffer commandBuffer,
VkBool32 primitiveRestartEnable)
{
VN_CMD_ENQUEUE(vkCmdSetPrimitiveRestartEnable, commandBuffer,
primitiveRestartEnable);
}
void
vn_CmdSetRasterizerDiscardEnable(VkCommandBuffer commandBuffer,
VkBool32 rasterizerDiscardEnable)
{
VN_CMD_ENQUEUE(vkCmdSetRasterizerDiscardEnable, commandBuffer,
rasterizerDiscardEnable);
}
void
vn_CmdBeginConditionalRenderingEXT(
VkCommandBuffer commandBuffer,
const VkConditionalRenderingBeginInfoEXT *pConditionalRenderingBegin)
{
VN_CMD_ENQUEUE(vkCmdBeginConditionalRenderingEXT, commandBuffer,
pConditionalRenderingBegin);
}
void
vn_CmdEndConditionalRenderingEXT(VkCommandBuffer commandBuffer)
{
VN_CMD_ENQUEUE(vkCmdEndConditionalRenderingEXT, commandBuffer);
}