nvk: add cmd buffer framework

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Dave Airlie 2022-05-31 10:35:42 +10:00 committed by Marge Bot
parent decb8c6fd4
commit 6e0089307e
4 changed files with 254 additions and 1 deletions

View file

@ -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',

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}