From 97f82493367004c6c73747000b331f8140095bfe Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Sun, 9 May 2021 12:56:06 -0400 Subject: [PATCH] zink: move sparse buffer commit to screen queue all queue submission must be serialized with the dispatch thread Acked-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_context.c | 82 +++++++++++++++++-------- 1 file changed, 58 insertions(+), 24 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 31933128976..836794724c3 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -3137,6 +3137,29 @@ out: VK_PIPELINE_STAGE_VERTEX_INPUT_BIT); } +static inline struct zink_screen ** +get_screen_ptr_for_commit(uint8_t *mem) +{ + return (struct zink_screen**)(mem + sizeof(VkBindSparseInfo) + sizeof(VkSparseBufferMemoryBindInfo) + sizeof(VkSparseMemoryBind)); +} + +static bool +resource_commit(struct zink_screen *screen, VkBindSparseInfo *sparse) +{ + VkQueue queue = screen->threaded ? screen->thread_queue : screen->queue; + + VkResult ret = vkQueueBindSparse(queue, 1, sparse, VK_NULL_HANDLE); + return zink_screen_handle_vkresult(screen, ret); +} + +static void +submit_resource_commit(void *data, void *gdata, int thread_index) +{ + struct zink_screen **screen = get_screen_ptr_for_commit(data); + resource_commit(*screen, data); + free(data); +} + static bool zink_resource_commit(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, struct pipe_box *box, bool commit) { @@ -3149,37 +3172,48 @@ zink_resource_commit(struct pipe_context *pctx, struct pipe_resource *pres, unsi zink_batch_usage_is_unflushed(res->obj->writes)) zink_flush_queue(ctx); - VkBindSparseInfo sparse; - sparse.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO; - sparse.pNext = NULL; - sparse.waitSemaphoreCount = 0; - sparse.bufferBindCount = 1; - sparse.imageOpaqueBindCount = 0; - sparse.imageBindCount = 0; - sparse.signalSemaphoreCount = 0; + uint8_t *mem = malloc(sizeof(VkBindSparseInfo) + sizeof(VkSparseBufferMemoryBindInfo) + sizeof(VkSparseMemoryBind) + sizeof(void*)); + if (!mem) + return false; + VkBindSparseInfo *sparse = (void*)mem; + sparse->sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO; + sparse->pNext = NULL; + sparse->waitSemaphoreCount = 0; + sparse->bufferBindCount = 1; + sparse->imageOpaqueBindCount = 0; + sparse->imageBindCount = 0; + sparse->signalSemaphoreCount = 0; - VkSparseBufferMemoryBindInfo sparse_bind; - sparse_bind.buffer = res->obj->buffer; - sparse_bind.bindCount = 1; - sparse.pBufferBinds = &sparse_bind; + VkSparseBufferMemoryBindInfo *sparse_bind = (void*)(mem + sizeof(VkBindSparseInfo)); + sparse_bind->buffer = res->obj->buffer; + sparse_bind->bindCount = 1; + sparse->pBufferBinds = sparse_bind; - VkSparseMemoryBind mem_bind; - mem_bind.resourceOffset = box->x; - mem_bind.size = box->width; - mem_bind.memory = commit ? res->obj->mem : VK_NULL_HANDLE; + VkSparseMemoryBind *mem_bind = (void*)(mem + sizeof(VkBindSparseInfo) + sizeof(VkSparseBufferMemoryBindInfo)); + mem_bind->resourceOffset = box->x; + mem_bind->size = box->width; + mem_bind->memory = commit ? res->obj->mem : VK_NULL_HANDLE; /* currently sparse buffers allocate memory 1:1 for the max sparse size, * but probably it should dynamically allocate the committed regions; * if this ever changes, update the below line */ - mem_bind.memoryOffset = box->x; - mem_bind.flags = 0; - sparse_bind.pBinds = &mem_bind; - VkQueue queue = screen->threaded ? screen->thread_queue : screen->queue; + mem_bind->memoryOffset = box->x; + mem_bind->flags = 0; + sparse_bind->pBinds = mem_bind; - VkResult ret = vkQueueBindSparse(queue, 1, &sparse, VK_NULL_HANDLE); - if (!zink_screen_handle_vkresult(screen, ret)) { - check_device_lost(ctx); - return false; + struct zink_screen **ptr = get_screen_ptr_for_commit(mem); + *ptr = screen; + + if (screen->threaded) { + /* this doesn't need any kind of fencing because any access to this resource + * will be automagically synchronized by queue dispatch */ + util_queue_add_job(&screen->flush_queue, mem, NULL, submit_resource_commit, NULL, 0); + } else { + bool ret = resource_commit(screen, sparse); + if (!ret) + check_device_lost(ctx); + free(sparse); + return ret; } return true; }