From 3137ff47095e9c28e0b27c72acab52301b87f99d Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 29 Oct 2021 11:06:34 -0400 Subject: [PATCH] zink: add queue locking sparse binds have to be processed synchronously with cmdbuf recording to avoid resource object desync in the vk driver, which means they have to be done in the driver thread instead of the flush thread. this necessitates adding locking for the queue since there is now a case when submissions occur in a different thread fixes illegal multithread usage in KHR-GL46.CommonBugs.CommonBug_SparseBuffersWithCopyOps cc: mesa-stable Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_batch.c | 2 + src/gallium/drivers/zink/zink_bo.c | 78 +++++++------------------- src/gallium/drivers/zink/zink_screen.c | 4 ++ src/gallium/drivers/zink/zink_screen.h | 1 + 4 files changed, 26 insertions(+), 59 deletions(-) diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c index 33e4ad17921..ae23a1f6d01 100644 --- a/src/gallium/drivers/zink/zink_batch.c +++ b/src/gallium/drivers/zink/zink_batch.c @@ -418,10 +418,12 @@ submit_queue(void *data, void *gdata, int thread_index) VKSCR(FlushMappedMemoryRanges)(screen->dev, 1, &range); } + simple_mtx_lock(&screen->queue_lock); if (VKSCR(QueueSubmit)(bs->queue, 1, &si, bs->fence.fence) != VK_SUCCESS) { debug_printf("ZINK: vkQueueSubmit() failed\n"); bs->is_device_lost = true; } + simple_mtx_unlock(&screen->queue_lock); bs->submit_count++; end: cnd_broadcast(&bs->usage.flush); diff --git a/src/gallium/drivers/zink/zink_bo.c b/src/gallium/drivers/zink/zink_bo.c index ad4282dc2d8..8594e3be0bb 100644 --- a/src/gallium/drivers/zink/zink_bo.c +++ b/src/gallium/drivers/zink/zink_bo.c @@ -675,72 +675,32 @@ zink_bo_unmap(struct zink_screen *screen, struct zink_bo *bo) } } - -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 = VKSCR(QueueBindSparse)(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 do_commit_single(struct zink_screen *screen, struct zink_resource *res, struct zink_bo *bo, uint32_t offset, uint32_t size, bool commit) { + VkBindSparseInfo sparse = {0}; + sparse.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO; + sparse.bufferBindCount = 1; - 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 = offset; + mem_bind.size = MIN2(res->base.b.width0 - offset, size); + mem_bind.memory = commit ? bo->mem : VK_NULL_HANDLE; + mem_bind.memoryOffset = 0; + mem_bind.flags = 0; + sparse_bind.pBinds = &mem_bind; - VkSparseMemoryBind *mem_bind = (void*)(mem + sizeof(VkBindSparseInfo) + sizeof(VkSparseBufferMemoryBindInfo)); - mem_bind->resourceOffset = offset; - mem_bind->size = MIN2(res->base.b.width0 - offset, size); - mem_bind->memory = commit ? bo->mem : VK_NULL_HANDLE; - mem_bind->memoryOffset = 0; - mem_bind->flags = 0; - sparse_bind->pBinds = mem_bind; + VkQueue queue = screen->threaded ? screen->thread_queue : screen->queue; - 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); - free(sparse); - return ret; - } - return true; + simple_mtx_lock(&screen->queue_lock); + VkResult ret = VKSCR(QueueBindSparse)(queue, 1, &sparse, VK_NULL_HANDLE); + simple_mtx_unlock(&screen->queue_lock); + return zink_screen_handle_vkresult(screen, ret); } bool diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 2a7c5084535..a07083213f2 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -1122,6 +1122,7 @@ zink_destroy_screen(struct pipe_screen *pscreen) if (screen->threaded) util_queue_destroy(&screen->flush_queue); + simple_mtx_destroy(&screen->queue_lock); VKSCR(DestroyDevice)(screen->dev, NULL); vkDestroyInstance(screen->instance, NULL); util_idalloc_mt_fini(&screen->buffer_ids); @@ -1208,6 +1209,7 @@ update_queue_props(struct zink_screen *screen) static void init_queue(struct zink_screen *screen) { + simple_mtx_init(&screen->queue_lock, mtx_plain); vkGetDeviceQueue(screen->dev, screen->gfx_queue, 0, &screen->queue); if (screen->threaded && screen->max_queues > 1) vkGetDeviceQueue(screen->dev, screen->gfx_queue, 1, &screen->thread_queue); @@ -1601,11 +1603,13 @@ noop_submit(void *data, void *gdata, int thread_index) struct noop_submit_info *n = data; VkSubmitInfo si = {0}; si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + simple_mtx_lock(&n->screen->queue_lock); if (n->VKSCR(QueueSubmit)(n->screen->threaded ? n->screen->thread_queue : n->screen->queue, 1, &si, n->fence) != VK_SUCCESS) { debug_printf("ZINK: vkQueueSubmit() failed\n"); n->screen->device_lost = true; } + simple_mtx_unlock(&n->screen->queue_lock); } bool diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index 23f7fbafd54..a1b7811935d 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -133,6 +133,7 @@ struct zink_screen { VkDevice dev; VkQueue queue; //gfx+compute VkQueue thread_queue; //gfx+compute + simple_mtx_t queue_lock; VkDebugUtilsMessengerEXT debugUtilsCallbackHandle; uint32_t cur_custom_border_color_samplers;