Mesa (master): zink: enforce device lost status

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 1 13:33:53 UTC 2021


Module: Mesa
Branch: master
Commit: bbb00f739c8fc001d2dea9d3d340a65843eaf7ee
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=bbb00f739c8fc001d2dea9d3d340a65843eaf7ee

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Wed Feb 10 18:40:55 2021 -0500

zink: enforce device lost status

many apps don't request device-lost notification, so just calling the reset
callback isn't enough; once the device has been lost, no more cmdbufs should
be submitted and the queue should not be waited on

Acked-by: Erik Faye-Lund <erik.faye-lund at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9963>

---

 src/gallium/drivers/zink/zink_batch.c   | 12 +++++++++---
 src/gallium/drivers/zink/zink_context.c |  5 ++++-
 src/gallium/drivers/zink/zink_fence.c   | 22 +++++++++++++++++++---
 src/gallium/drivers/zink/zink_screen.h  |  1 +
 4 files changed, 33 insertions(+), 7 deletions(-)

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;



More information about the mesa-commit mailing list