From: Dave Airlie Date: Tue, 31 May 2022 00:35:42 +0000 (+1000) Subject: nvk: add cmd buffer framework X-Git-Tag: upstream/23.3.3~4598 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6e0089307ef4f539ed4ee82c4966e977a6b95a0b;p=platform%2Fupstream%2Fmesa.git nvk: add cmd buffer framework Part-of: --- diff --git a/src/nouveau/vulkan/meson.build b/src/nouveau/vulkan/meson.build index f35709f..3d6dbe5 100644 --- a/src/nouveau/vulkan/meson.build +++ b/src/nouveau/vulkan/meson.build @@ -1,6 +1,8 @@ nvk_files = files( 'nvk_buffer.c', 'nvk_buffer.h', + 'nvk_cmd_buffer.c', + 'nvk_cmd_buffer.h', 'nvk_device.c', 'nvk_device.h', 'nvk_device_memory.c', diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c b/src/nouveau/vulkan/nvk_cmd_buffer.c new file mode 100644 index 0000000..c53d03b --- /dev/null +++ b/src/nouveau/vulkan/nvk_cmd_buffer.c @@ -0,0 +1,211 @@ +#include "nvk_cmd_buffer.h" + +#include "nvk_device.h" +#include "nvk_physical_device.h" + +#include "nouveau_push.h" + +static void +nvk_destroy_cmd_buffer(struct nvk_cmd_buffer *cmd_buffer) +{ + list_del(&cmd_buffer->pool_link); + + nouveau_ws_push_destroy(cmd_buffer->push); + vk_command_buffer_finish(&cmd_buffer->vk); + vk_free(&cmd_buffer->pool->vk.alloc, cmd_buffer); +} + +static VkResult +nvk_create_cmd_buffer(struct nvk_device *device, struct nvk_cmd_pool *pool, + VkCommandBufferLevel level, VkCommandBuffer *pCommandBuffer) +{ + struct nvk_cmd_buffer *cmd_buffer; + + cmd_buffer = vk_zalloc(&pool->vk.alloc, sizeof(*cmd_buffer), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (cmd_buffer == NULL) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + VkResult result = + vk_command_buffer_init(&pool->vk, &cmd_buffer->vk, NULL, level); + if (result != VK_SUCCESS) { + vk_free(&cmd_buffer->pool->vk.alloc, cmd_buffer); + return result; + } + + cmd_buffer->pool = pool; + list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers); + + cmd_buffer->push = nouveau_ws_push_new(device->pdev->dev, NVK_CMD_BUF_SIZE); + *pCommandBuffer = nvk_cmd_buffer_to_handle(cmd_buffer); + return VK_SUCCESS; +} + +static VkResult +nvk_reset_cmd_buffer(struct nvk_cmd_buffer *cmd_buffer) +{ + vk_command_buffer_reset(&cmd_buffer->vk); + return VK_SUCCESS; +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_CreateCommandPool(VkDevice _device, const VkCommandPoolCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkCommandPool *pCmdPool) +{ + VK_FROM_HANDLE(nvk_device, device, _device); + struct nvk_cmd_pool *pool; + + pool = + vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*pool), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (pool == NULL) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + VkResult result = vk_command_pool_init(&device->vk, &pool->vk, pCreateInfo, pAllocator); + if (result != VK_SUCCESS) { + vk_free2(&device->vk.alloc, pAllocator, pool); + return result; + } + + list_inithead(&pool->cmd_buffers); + list_inithead(&pool->free_cmd_buffers); + + *pCmdPool = nvk_cmd_pool_to_handle(pool); + return VK_SUCCESS; +} + +VKAPI_ATTR void VKAPI_CALL +nvk_DestroyCommandPool(VkDevice _device, VkCommandPool commandPool, + const VkAllocationCallbacks *pAllocator) +{ + VK_FROM_HANDLE(nvk_device, device, _device); + VK_FROM_HANDLE(nvk_cmd_pool, pool, commandPool); + + if (!pool) + return; + + list_for_each_entry_safe(struct nvk_cmd_buffer, cmd_buffer, &pool->cmd_buffers, pool_link) + { + nvk_destroy_cmd_buffer(cmd_buffer); + } + + list_for_each_entry_safe(struct nvk_cmd_buffer, cmd_buffer, &pool->free_cmd_buffers, pool_link) + { + nvk_destroy_cmd_buffer(cmd_buffer); + } + + vk_command_pool_finish(&pool->vk); + vk_free2(&device->vk.alloc, pAllocator, pool); +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) +{ + VK_FROM_HANDLE(nvk_cmd_pool, pool, commandPool); + VkResult result; + + list_for_each_entry(struct nvk_cmd_buffer, cmd_buffer, &pool->cmd_buffers, pool_link) + { + result = nvk_reset_cmd_buffer(cmd_buffer); + if (result != VK_SUCCESS) + return result; + } + + return VK_SUCCESS; +} + +VKAPI_ATTR void VKAPI_CALL +nvk_TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) +{ + VK_FROM_HANDLE(nvk_cmd_pool, pool, commandPool); + + list_for_each_entry_safe(struct nvk_cmd_buffer, cmd_buffer, &pool->free_cmd_buffers, pool_link) + { + nvk_destroy_cmd_buffer(cmd_buffer); + } +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_AllocateCommandBuffers(VkDevice _device, + const VkCommandBufferAllocateInfo *pAllocateInfo, + VkCommandBuffer *pCommandBuffers) +{ + VK_FROM_HANDLE(nvk_device, device, _device); + VK_FROM_HANDLE(nvk_cmd_pool, pool, pAllocateInfo->commandPool); + uint32_t i; + VkResult result = VK_SUCCESS; + + for (i = 0; i < pAllocateInfo->commandBufferCount; i++) { + if (!list_is_empty(&pool->free_cmd_buffers)) { + struct nvk_cmd_buffer *cmd_buffer = + list_first_entry(&pool->free_cmd_buffers, struct nvk_cmd_buffer, pool_link); + + list_del(&cmd_buffer->pool_link); + list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers); + + result = nvk_reset_cmd_buffer(cmd_buffer); + vk_command_buffer_finish(&cmd_buffer->vk); + VkResult init_result = + vk_command_buffer_init(&pool->vk, &cmd_buffer->vk, NULL, + pAllocateInfo->level); + if (init_result != VK_SUCCESS) + result = init_result; + + pCommandBuffers[i] = nvk_cmd_buffer_to_handle(cmd_buffer); + } else { + result = nvk_create_cmd_buffer(device, pool, pAllocateInfo->level, &pCommandBuffers[i]); + } + if (result != VK_SUCCESS) + break; + } + + if (result != VK_SUCCESS) { + nvk_FreeCommandBuffers(_device, pAllocateInfo->commandPool, i, pCommandBuffers); + /* From the Vulkan 1.0.66 spec: + * + * "vkAllocateCommandBuffers can be used to create multiple + * command buffers. If the creation of any of those command + * buffers fails, the implementation must destroy all + * successfully created command buffer objects from this + * command, set all entries of the pCommandBuffers array to + * NULL and return the error." + */ + memset(pCommandBuffers, 0, sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount); + } + return result; +} + +VKAPI_ATTR void VKAPI_CALL +nvk_FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, + const VkCommandBuffer *pCommandBuffers) +{ + VK_FROM_HANDLE(nvk_cmd_pool, pool, commandPool); + for (uint32_t i = 0; i < commandBufferCount; i++) { + VK_FROM_HANDLE(nvk_cmd_buffer, cmd_buffer, pCommandBuffers[i]); + + if (!cmd_buffer) + continue; + assert(cmd_buffer->pool == pool); + + list_del(&cmd_buffer->pool_link); + list_addtail(&cmd_buffer->pool_link, &pool->free_cmd_buffers); + } +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) +{ + VK_FROM_HANDLE(nvk_cmd_buffer, cmd_buffer, commandBuffer); + return nvk_reset_cmd_buffer(cmd_buffer); +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) +{ + return VK_SUCCESS; +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_EndCommandBuffer(VkCommandBuffer commandBuffer) +{ + return VK_SUCCESS; +} diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.h b/src/nouveau/vulkan/nvk_cmd_buffer.h new file mode 100644 index 0000000..ac2d0d5 --- /dev/null +++ b/src/nouveau/vulkan/nvk_cmd_buffer.h @@ -0,0 +1,31 @@ +#ifndef NVK_CMD_BUFFER_H +#define NVK_CMD_BUFFER_H 1 + +#include "nvk_private.h" + +#include "vulkan/runtime/vk_command_buffer.h" +#include "vulkan/runtime/vk_command_pool.h" + +#define NVK_CMD_BUF_SIZE 64*1024 + +struct nvk_cmd_pool { + struct vk_command_pool vk; + struct list_head cmd_buffers; + struct list_head free_cmd_buffers; +}; + +struct nvk_cmd_buffer { + struct vk_command_buffer vk; + + struct nvk_cmd_pool *pool; + struct list_head pool_link; + + struct nouveau_ws_push *push; +}; + +VK_DEFINE_HANDLE_CASTS(nvk_cmd_buffer, vk.base, VkCommandBuffer, + VK_OBJECT_TYPE_COMMAND_BUFFER) +VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_cmd_pool, vk.base, VkCommandPool, + VK_OBJECT_TYPE_COMMAND_POOL) + +#endif diff --git a/src/nouveau/vulkan/nvk_device.c b/src/nouveau/vulkan/nvk_device.c index 1a648fd..b1285e5 100644 --- a/src/nouveau/vulkan/nvk_device.c +++ b/src/nouveau/vulkan/nvk_device.c @@ -1,15 +1,24 @@ #include "nvk_device.h" +#include "nvk_cmd_buffer.h" #include "nvk_instance.h" #include "nvk_physical_device.h" #include "nouveau_context.h" +#include "nouveau_push.h" #include "vulkan/wsi/wsi_common.h" static VkResult -nvk_queue_submit(struct vk_queue *vqueue, struct vk_queue_submit *submission) +nvk_queue_submit(struct vk_queue *queue, struct vk_queue_submit *submission) { + struct nvk_device *device = container_of(queue->base.device, struct nvk_device, vk); + + for (unsigned i = 0; i < submission->command_buffer_count; i++) { + struct nvk_cmd_buffer *cmd = (struct nvk_cmd_buffer *)submission->command_buffers[i]; + nouveau_ws_push_submit(cmd->push, device->pdev->dev, device->ctx); + } + return VK_SUCCESS; }