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)
{
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;
-
- VkSparseBufferMemoryBindInfo sparse_bind;
- 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;
+ 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 = (void*)(mem + sizeof(VkBindSparseInfo));
+ sparse_bind->buffer = res->obj->buffer;
+ sparse_bind->bindCount = 1;
+ sparse->pBufferBinds = sparse_bind;
+
+ 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;
}