nvk: Use nvk_cmd_bo for push bufs
This allows us to recycle them. It also makes implementing secondary command buffers tractable. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
committed by
Marge Bot
parent
4998896ae8
commit
40eedabd4a
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "nvk_physical_device.h"
|
||||
|
||||
#include "nouveau_context.h"
|
||||
#include "nouveau_push.h"
|
||||
|
||||
#include <nouveau_drm.h>
|
||||
#include <xf86drm.h>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user