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@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9963>
This commit is contained in:
parent
357b54c9bb
commit
bbb00f739c
|
@ -327,8 +327,11 @@ post_submit(void *data, int thread_index)
|
||||||
{
|
{
|
||||||
struct zink_batch_state *bs = data;
|
struct zink_batch_state *bs = data;
|
||||||
|
|
||||||
if (bs->is_device_lost && bs->ctx->reset.reset)
|
if (bs->is_device_lost) {
|
||||||
bs->ctx->reset.reset(bs->ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET);
|
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
|
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);
|
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) {
|
util_dynarray_foreach(&batch->state->persistent_resources, struct zink_resource*, res) {
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
|
||||||
assert(!(*res)->obj->offset);
|
assert(!(*res)->obj->offset);
|
||||||
VkMappedMemoryRange range = {
|
VkMappedMemoryRange range = {
|
||||||
VK_STRUCTURE_TYPE_MAPPED_MEMORY_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);
|
simple_mtx_unlock(&ctx->batch_mtx);
|
||||||
ctx->resource_size += batch->state->resource_size;
|
ctx->resource_size += batch->state->resource_size;
|
||||||
|
|
||||||
|
if (screen->device_lost)
|
||||||
|
return;
|
||||||
|
|
||||||
if (util_queue_is_initialized(&batch->flush_queue)) {
|
if (util_queue_is_initialized(&batch->flush_queue)) {
|
||||||
batch->state->queue = batch->thread_queue;
|
batch->state->queue = batch->thread_queue;
|
||||||
util_queue_add_job(&batch->flush_queue, batch->state, &batch->state->flush_completed,
|
util_queue_add_job(&batch->flush_queue, batch->state, &batch->state->flush_completed,
|
||||||
|
|
|
@ -291,7 +291,7 @@ zink_context_destroy(struct pipe_context *pctx)
|
||||||
struct zink_context *ctx = zink_context(pctx);
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
struct zink_screen *screen = zink_screen(pctx->screen);
|
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");
|
debug_printf("vkQueueWaitIdle failed\n");
|
||||||
|
|
||||||
util_blitter_destroy(ctx->blitter);
|
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;
|
uint64_t batch_id64 = batch_id;
|
||||||
wi.pValues = &batch_id64;
|
wi.pValues = &batch_id64;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
if (screen->device_lost)
|
||||||
|
return true;
|
||||||
switch (screen->vk_WaitSemaphores(screen->dev, &wi, timeout)) {
|
switch (screen->vk_WaitSemaphores(screen->dev, &wi, timeout)) {
|
||||||
case VK_SUCCESS:
|
case VK_SUCCESS:
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -2027,6 +2029,7 @@ timeline_wait(struct zink_context *ctx, uint32_t batch_id, uint64_t timeout)
|
||||||
case VK_ERROR_DEVICE_LOST:
|
case VK_ERROR_DEVICE_LOST:
|
||||||
if (ctx->reset.reset)
|
if (ctx->reset.reset)
|
||||||
ctx->reset.reset(ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET);
|
ctx->reset.reset(ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET);
|
||||||
|
screen->device_lost = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -140,18 +140,31 @@ tc_fence_finish(struct zink_context *ctx, struct zink_tc_fence *mfence, uint64_t
|
||||||
bool
|
bool
|
||||||
zink_vkfence_wait(struct zink_screen *screen, struct zink_fence *fence, uint64_t timeout_ns)
|
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))
|
if (p_atomic_read(&fence->completed))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
assert(fence->batch_id);
|
assert(fence->batch_id);
|
||||||
assert(fence->submitted);
|
assert(fence->submitted);
|
||||||
|
|
||||||
bool success;
|
bool success = false;
|
||||||
|
|
||||||
|
VkResult ret;
|
||||||
if (timeout_ns)
|
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
|
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) {
|
if (success) {
|
||||||
p_atomic_set(&fence->completed, true);
|
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);
|
pctx = threaded_context_unwrap_sync(pctx);
|
||||||
struct zink_context *ctx = zink_context(pctx);
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
|
||||||
|
if (screen->device_lost)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (pctx && mfence->deferred_ctx == pctx) {
|
if (pctx && mfence->deferred_ctx == pctx) {
|
||||||
if (mfence->deferred_id == ctx->curr_batch) {
|
if (mfence->deferred_id == ctx->curr_batch) {
|
||||||
zink_context(pctx)->batch.has_work = true;
|
zink_context(pctx)->batch.has_work = true;
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct zink_screen {
|
||||||
uint32_t curr_batch; //the current batch id
|
uint32_t curr_batch; //the current batch id
|
||||||
uint32_t last_finished; //this is racy but ultimately doesn't matter
|
uint32_t last_finished; //this is racy but ultimately doesn't matter
|
||||||
|
|
||||||
|
bool device_lost;
|
||||||
struct sw_winsys *winsys;
|
struct sw_winsys *winsys;
|
||||||
|
|
||||||
struct hash_table framebuffer_cache;
|
struct hash_table framebuffer_cache;
|
||||||
|
|
Loading…
Reference in New Issue