diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c index e4779a8e68a..be760dcface 100644 --- a/src/gallium/drivers/zink/zink_batch.c +++ b/src/gallium/drivers/zink/zink_batch.c @@ -327,8 +327,11 @@ post_submit(void *data, int thread_index) { struct zink_batch_state *bs = data; - if (bs->is_device_lost && bs->ctx->reset.reset) - bs->ctx->reset.reset(bs->ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET); + if (bs->is_device_lost) { + if (bs->ctx->reset.reset) + bs->ctx->reset.reset(bs->ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET); + zink_screen(bs->ctx->base.screen)->device_lost = true; + } } static void @@ -385,8 +388,8 @@ zink_end_batch(struct zink_context *ctx, struct zink_batch *batch) } vkResetFences(zink_screen(ctx->base.screen)->dev, 1, &batch->state->fence.fence); + struct zink_screen *screen = zink_screen(ctx->base.screen); util_dynarray_foreach(&batch->state->persistent_resources, struct zink_resource*, res) { - struct zink_screen *screen = zink_screen(ctx->base.screen); assert(!(*res)->obj->offset); VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, @@ -404,6 +407,9 @@ zink_end_batch(struct zink_context *ctx, struct zink_batch *batch) simple_mtx_unlock(&ctx->batch_mtx); ctx->resource_size += batch->state->resource_size; + if (screen->device_lost) + return; + if (util_queue_is_initialized(&batch->flush_queue)) { batch->state->queue = batch->thread_queue; util_queue_add_job(&batch->flush_queue, batch->state, &batch->state->flush_completed, diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 9d4c5f3c288..e366376a4d7 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -291,7 +291,7 @@ zink_context_destroy(struct pipe_context *pctx) struct zink_context *ctx = zink_context(pctx); struct zink_screen *screen = zink_screen(pctx->screen); - if (ctx->batch.queue && vkQueueWaitIdle(ctx->batch.queue) != VK_SUCCESS) + if (ctx->batch.queue && !screen->device_lost && vkQueueWaitIdle(ctx->batch.queue) != VK_SUCCESS) debug_printf("vkQueueWaitIdle failed\n"); util_blitter_destroy(ctx->blitter); @@ -2020,6 +2020,8 @@ timeline_wait(struct zink_context *ctx, uint32_t batch_id, uint64_t timeout) uint64_t batch_id64 = batch_id; wi.pValues = &batch_id64; bool success = false; + if (screen->device_lost) + return true; switch (screen->vk_WaitSemaphores(screen->dev, &wi, timeout)) { case VK_SUCCESS: success = true; @@ -2027,6 +2029,7 @@ timeline_wait(struct zink_context *ctx, uint32_t batch_id, uint64_t timeout) case VK_ERROR_DEVICE_LOST: if (ctx->reset.reset) ctx->reset.reset(ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET); + screen->device_lost = true; break; default: break; diff --git a/src/gallium/drivers/zink/zink_fence.c b/src/gallium/drivers/zink/zink_fence.c index d54dc5b13cd..6fbc81de70f 100644 --- a/src/gallium/drivers/zink/zink_fence.c +++ b/src/gallium/drivers/zink/zink_fence.c @@ -140,18 +140,31 @@ tc_fence_finish(struct zink_context *ctx, struct zink_tc_fence *mfence, uint64_t bool zink_vkfence_wait(struct zink_screen *screen, struct zink_fence *fence, uint64_t timeout_ns) { + if (screen->device_lost) + return true; if (p_atomic_read(&fence->completed)) return true; assert(fence->batch_id); assert(fence->submitted); - bool success; + bool success = false; + VkResult ret; if (timeout_ns) - success = vkWaitForFences(screen->dev, 1, &fence->fence, VK_TRUE, timeout_ns) == VK_SUCCESS; + ret = vkWaitForFences(screen->dev, 1, &fence->fence, VK_TRUE, timeout_ns); else - success = vkGetFenceStatus(screen->dev, fence->fence) == VK_SUCCESS; + ret = vkGetFenceStatus(screen->dev, fence->fence); + switch (ret) { + case VK_SUCCESS: + success = true; + break; + case VK_ERROR_DEVICE_LOST: + screen->device_lost = true; + break; + default: + break; + } if (success) { p_atomic_set(&fence->completed, true); @@ -168,6 +181,9 @@ zink_fence_finish(struct zink_screen *screen, struct pipe_context *pctx, struct pctx = threaded_context_unwrap_sync(pctx); struct zink_context *ctx = zink_context(pctx); + if (screen->device_lost) + return true; + if (pctx && mfence->deferred_ctx == pctx) { if (mfence->deferred_id == ctx->curr_batch) { zink_context(pctx)->batch.has_work = true; diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index 2114be352d8..038570e028a 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -55,6 +55,7 @@ struct zink_screen { uint32_t curr_batch; //the current batch id uint32_t last_finished; //this is racy but ultimately doesn't matter + bool device_lost; struct sw_winsys *winsys; struct hash_table framebuffer_cache;