zink: move sparse buffer commit to screen queue

all queue submission must be serialized with the dispatch thread

Acked-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11437>
This commit is contained in:
Mike Blumenkrantz 2021-05-09 12:56:06 -04:00 committed by Marge Bot
parent 478f129ee7
commit 97f8249336
1 changed files with 58 additions and 24 deletions

View File

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