diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c b/src/nouveau/vulkan/nvk_cmd_buffer.c index 26903e22a30..a11a0545b6a 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.c +++ b/src/nouveau/vulkan/nvk_cmd_buffer.c @@ -24,7 +24,8 @@ nvk_destroy_cmd_buffer(struct vk_command_buffer *vk_cmd_buffer) struct nvk_cmd_pool *pool = nvk_cmd_buffer_pool(cmd); nvk_cmd_pool_free_bo_list(pool, &cmd->bos); - nouveau_ws_push_destroy(cmd->push); + util_dynarray_fini(&cmd->pushes); + util_dynarray_fini(&cmd->bo_refs); vk_command_buffer_finish(&cmd->vk); vk_free(&pool->vk.alloc, cmd); } @@ -54,7 +55,8 @@ nvk_create_cmd_buffer(struct vk_command_pool *vk_pool, &cmd->state.gfx._dynamic_vi; list_inithead(&cmd->bos); - cmd->push = nouveau_ws_push_new(device->pdev->dev, NVK_CMD_BUF_SIZE); + util_dynarray_init(&cmd->pushes, NULL); + util_dynarray_init(&cmd->bo_refs, NULL); *cmd_buffer_out = &cmd->vk; @@ -73,7 +75,13 @@ nvk_reset_cmd_buffer(struct vk_command_buffer *vk_cmd_buffer, nvk_cmd_pool_free_bo_list(pool, &cmd->bos); cmd->upload_bo = NULL; - nouveau_ws_push_reset(cmd->push); + cmd->push_bo = NULL; + cmd->push_bo_limit = NULL; + cmd->push = (struct nv_push) {0}; + + util_dynarray_clear(&cmd->pushes); + util_dynarray_clear(&cmd->bo_refs); + memset(&cmd->state, 0, sizeof(cmd->state)); } @@ -83,6 +91,41 @@ const struct vk_command_buffer_ops nvk_cmd_buffer_ops = { .destroy = nvk_destroy_cmd_buffer, }; +/* If we ever fail to allocate a push, we use this */ +static uint32_t push_runout[NVK_CMD_BUFFER_MAX_PUSH]; + +void +nvk_cmd_buffer_new_push(struct nvk_cmd_buffer *cmd) +{ + struct nvk_cmd_pool *pool = nvk_cmd_buffer_pool(cmd); + VkResult result; + + result = nvk_cmd_pool_alloc_bo(pool, &cmd->push_bo); + if (unlikely(result != VK_SUCCESS)) { + STATIC_ASSERT(NVK_CMD_BUFFER_MAX_PUSH <= NVK_CMD_BO_SIZE / 4); + cmd->push_bo = NULL; + nv_push_init(&cmd->push, push_runout, 0); + cmd->push_bo_limit = &push_runout[NVK_CMD_BUFFER_MAX_PUSH]; + } else { + nv_push_init(&cmd->push, cmd->push_bo->map, 0); + cmd->push_bo_limit = + (uint32_t *)((char *)cmd->push_bo->map + NVK_CMD_BO_SIZE); + } +} + +static void +nvk_cmd_buffer_flush_push(struct nvk_cmd_buffer *cmd) +{ + struct nvk_cmd_push push = { + .bo = cmd->push_bo, + .start_dw = cmd->push.start - (uint32_t *)cmd->push_bo->map, + .dw_count = nv_push_dw_count(&cmd->push), + }; + util_dynarray_append(&cmd->pushes, struct nvk_cmd_push, push); + + cmd->push.start = cmd->push.end; +} + VkResult nvk_cmd_buffer_upload_alloc(struct nvk_cmd_buffer *cmd, uint32_t size, uint32_t alignment, @@ -155,6 +198,9 @@ VKAPI_ATTR VkResult VKAPI_CALL nvk_EndCommandBuffer(VkCommandBuffer commandBuffer) { VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); + + nvk_cmd_buffer_flush_push(cmd); + return vk_command_buffer_get_record_result(&cmd->vk); } diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.h b/src/nouveau/vulkan/nvk_cmd_buffer.h index b0ac3bc86a9..deca45f0ce6 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.h +++ b/src/nouveau/vulkan/nvk_cmd_buffer.h @@ -3,16 +3,18 @@ #include "nvk_private.h" -#include "nouveau_push.h" +#include "nv_push.h" +#include "nvk_cmd_pool.h" #include "nvk_descriptor_set.h" +#include "util/u_dynarray.h" + #include "vk_command_buffer.h" +struct nvk_cmd_bo; struct nvk_cmd_pool; struct nvk_image_view; -#define NVK_CMD_BUF_SIZE 64*1024 - /** Root descriptor table. This gets pushed to the GPU directly */ struct nvk_root_descriptor_table { union { @@ -83,6 +85,16 @@ struct nvk_compute_state { struct nvk_descriptor_state descriptors; }; +struct nvk_cmd_push { + struct nvk_cmd_bo *bo; + uint32_t start_dw; + uint32_t dw_count; +}; + +struct nvk_cmd_bo_ref { + struct nouveau_ws_bo *bo; +}; + struct nvk_cmd_buffer { struct vk_command_buffer vk; @@ -91,13 +103,34 @@ struct nvk_cmd_buffer { struct nvk_compute_state cs; } state; - /** List of nvk_cmd_bo */ + /** List of nvk_cmd_bo + * + * This list exists entirely for ownership tracking. Everything in here + * must also be in pushes or bo_refs if it is to be referenced by this + * command buffer. + */ struct list_head bos; struct nvk_cmd_bo *upload_bo; uint32_t upload_offset; - struct nouveau_ws_push *push; + struct nvk_cmd_bo *push_bo; + uint32_t *push_bo_limit; + struct nv_push push; + + /** Array of struct nvk_cmd_push + * + * This acts both as a BO reference as well as provides a range in the + * buffer to use as a pushbuf. + */ + struct util_dynarray pushes; + + /** Array of struct nvk_cmd_bo_ref + * + * This is for any internal allocations which we want to reference which + * aren't push buffers. + */ + struct util_dynarray bo_refs; uint64_t tls_space_needed; }; @@ -119,17 +152,30 @@ nvk_cmd_buffer_pool(struct nvk_cmd_buffer *cmd) return (struct nvk_cmd_pool *)cmd->vk.pool; } +void nvk_cmd_buffer_new_push(struct nvk_cmd_buffer *cmd); + +#define NVK_CMD_BUFFER_MAX_PUSH 256 + static inline struct nv_push * nvk_cmd_buffer_push(struct nvk_cmd_buffer *cmd, uint32_t dw_count) { - return P_SPACE(cmd->push, dw_count); + assert(dw_count <= NVK_CMD_BUFFER_MAX_PUSH); + + /* Compare to the actual limit on our push bo */ + if (unlikely(cmd->push.end + dw_count > cmd->push_bo_limit)) + nvk_cmd_buffer_new_push(cmd); + + cmd->push.limit = cmd->push.end + dw_count; + + return &cmd->push; } static inline void nvk_cmd_buffer_ref_bo(struct nvk_cmd_buffer *cmd, struct nouveau_ws_bo *bo) { - nouveau_ws_push_ref(cmd->push, bo, NOUVEAU_WS_BO_RDWR); + struct nvk_cmd_bo_ref ref = { .bo = bo }; + util_dynarray_append(&cmd->bo_refs, struct nvk_cmd_bo_ref, ref); } void nvk_cmd_buffer_begin_graphics(struct nvk_cmd_buffer *cmd, diff --git a/src/nouveau/vulkan/nvk_queue_drm_nouveau.c b/src/nouveau/vulkan/nvk_queue_drm_nouveau.c index 75c69cca493..aabc025792a 100644 --- a/src/nouveau/vulkan/nvk_queue_drm_nouveau.c +++ b/src/nouveau/vulkan/nvk_queue_drm_nouveau.c @@ -8,7 +8,6 @@ #include "nvk_physical_device.h" #include "nouveau_context.h" -#include "nouveau_push.h" #include #include @@ -84,16 +83,6 @@ push_add_push(struct push_builder *pb, struct nouveau_ws_bo *bo, }; } -static void -push_add_ws_push(struct push_builder *pb, struct nouveau_ws_push *push) -{ - util_dynarray_foreach(&push->bos, struct nouveau_ws_push_bo, push_bo) - push_add_bo(pb, push_bo->bo, push_bo->flags); - - util_dynarray_foreach(&push->pushs, struct nouveau_ws_push_buffer, buf) - push_add_push(pb, buf->bo, 0, nv_push_dw_count(&buf->push)); -} - static VkResult push_submit(struct push_builder *pb, struct nvk_queue *queue) { @@ -181,7 +170,11 @@ nvk_queue_submit_drm_nouveau(struct vk_queue *vk_queue, list_for_each_entry_safe(struct nvk_cmd_bo, bo, &cmd->bos, link) push_add_bo(&pb, bo->bo, NOUVEAU_WS_BO_RD); - push_add_ws_push(&pb, cmd->push); + util_dynarray_foreach(&cmd->pushes, struct nvk_cmd_push, push) + push_add_push(&pb, push->bo->bo, push->start_dw, push->dw_count); + + util_dynarray_foreach(&cmd->bo_refs, struct nvk_cmd_bo_ref, ref) + push_add_bo(&pb, ref->bo, NOUVEAU_WS_BO_RDWR); } }