From 8d9891088f1cc5d041b7019c7b23d13bd8bba40f Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 3 Jun 2021 15:20:34 -0400 Subject: [PATCH] zink: rebind all buffers on replacement in theory it's possible to trigger cases where rebinds aren't based on the current context, so ensure that (very unlikely) case is handled Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_context.c | 41 +++++++++++++++++++++++-- src/gallium/drivers/zink/zink_context.h | 5 +++ src/gallium/drivers/zink/zink_draw.cpp | 4 +++ src/gallium/drivers/zink/zink_screen.h | 2 ++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 754757f18b3..27bb8b09e04 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -3359,6 +3359,41 @@ zink_resource_rebind(struct zink_context *ctx, struct zink_resource *res) rebind_image(ctx, res); } +void +zink_rebind_all_buffers(struct zink_context *ctx) +{ + struct zink_batch *batch = &ctx->batch; + u_foreach_bit(slot, ctx->gfx_pipeline_state.vertex_buffers_enabled_mask) + set_vertex_buffer_clamped(ctx, slot); + ctx->vertex_buffers_dirty = ctx->gfx_pipeline_state.vertex_buffers_enabled_mask > 0; + ctx->dirty_so_targets = ctx->num_so_targets > 0; + if (ctx->num_so_targets) + zink_resource_buffer_barrier(ctx, NULL, zink_resource(ctx->dummy_xfb_buffer), + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT); + for (unsigned shader = PIPE_SHADER_VERTEX; shader < PIPE_SHADER_TYPES; shader++) { + for (unsigned slot = 0; slot < ctx->di.num_ubos[shader]; slot++) { + struct zink_resource *res = rebind_ubo(ctx, shader, slot); + if (res) + zink_batch_resource_usage_set(batch, res, false); + } + for (unsigned slot = 0; slot < ctx->di.num_sampler_views[shader]; slot++) { + struct zink_resource *res = rebind_tbo(ctx, shader, slot); + if (res) + zink_batch_resource_usage_set(batch, res, false); + } + for (unsigned slot = 0; slot < ctx->di.num_ssbos[shader]; slot++) { + struct zink_resource *res = rebind_ssbo(ctx, shader, slot); + if (res) + zink_batch_resource_usage_set(batch, res, (ctx->writable_ssbos[shader] & BITFIELD64_BIT(slot)) != 0); + } + for (unsigned slot = 0; slot < ctx->di.num_images[shader]; slot++) { + struct zink_resource *res = rebind_ibo(ctx, shader, slot); + if (res) + zink_batch_resource_usage_set(batch, res, (ctx->image_views[shader][slot].base.access & PIPE_IMAGE_ACCESS_WRITE) != 0); + } + } +} + static void zink_context_replace_buffer_storage(struct pipe_context *pctx, struct pipe_resource *dst, struct pipe_resource *src, unsigned num_rebinds, @@ -3366,16 +3401,18 @@ zink_context_replace_buffer_storage(struct pipe_context *pctx, struct pipe_resou { struct zink_resource *d = zink_resource(dst); struct zink_resource *s = zink_resource(src); + struct zink_context *ctx = zink_context(pctx); assert(d->internal_format == s->internal_format); util_idalloc_mt_free(&zink_screen(pctx->screen)->buffer_ids, delete_buffer_id); if (zink_resource_has_unflushed_usage(d)) - zink_batch_reference_resource(&zink_context(pctx)->batch, d); + zink_batch_reference_resource(&ctx->batch, d); zink_resource_object_reference(zink_screen(pctx->screen), &d->obj, s->obj); d->access = s->access; d->access_stage = s->access_stage; d->unordered_barrier = s->unordered_barrier; - zink_resource_rebind(zink_context(pctx), d); + zink_resource_rebind(ctx, d); + ctx->buffer_rebind_counter = p_atomic_inc_return(&zink_screen(ctx->base.screen)->buffer_rebind_counter); } static bool diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index f4ebce713e6..1dc83cdcaad 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -269,6 +269,8 @@ struct zink_context { struct pipe_surface *dummy_surface; struct zink_buffer_view *dummy_bufferview; + unsigned buffer_rebind_counter; + struct { /* descriptor info */ VkDescriptorBufferInfo ubos[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; @@ -406,6 +408,9 @@ zink_pipeline_flags_from_pipe_stage(enum pipe_shader_type pstage) } } +void +zink_rebind_all_buffers(struct zink_context *ctx); + void zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen); void diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index 62ae9e0b226..b4bd2b7b7cb 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -429,6 +429,10 @@ zink_draw_vbo(struct pipe_context *pctx, update_barriers(ctx, false); + if (unlikely(ctx->buffer_rebind_counter < screen->buffer_rebind_counter)) { + ctx->buffer_rebind_counter = screen->buffer_rebind_counter; + zink_rebind_all_buffers(ctx); + } if (ctx->gfx_pipeline_state.vertices_per_patch != ctx->gfx_pipeline_state.patch_vertices) ctx->gfx_pipeline_state.dirty = true; bool drawid_broken = ctx->drawid_broken; diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index 082ac2d23a6..feeb80cbe07 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -81,6 +81,8 @@ struct zink_screen { VkSemaphore prev_sem; struct util_queue flush_queue; + unsigned buffer_rebind_counter; + bool device_lost; struct sw_winsys *winsys;