From b27e729c0d330502a61b40860ebd9492ec7df117 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 Jan 2021 12:05:48 -0500 Subject: [PATCH] zink: add vertex buffer barriers during bind now we have tracking for vbo binds and can automatically reapply the correct barrier just before draw if the resource is modified after bind Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_context.c | 47 +++++++++++++++++++++--- src/gallium/drivers/zink/zink_draw.c | 21 +++-------- src/gallium/drivers/zink/zink_resource.h | 1 + 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index f92e71fa84d..67106acd6b4 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -812,6 +812,18 @@ zink_set_polygon_stipple(struct pipe_context *pctx, { } +static void +update_existing_vbo(struct zink_context *ctx, unsigned slot) +{ + if (!ctx->vertex_buffers[slot].buffer.resource) + return; + struct zink_resource *res = zink_resource(ctx->vertex_buffers[slot].buffer.resource); + res->vbo_bind_count--; + res->bind_count[0]--; + if (!res->bind_count[0]) + _mesa_set_remove_key(ctx->need_barriers[0], res); +} + static void zink_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot, @@ -822,9 +834,29 @@ zink_set_vertex_buffers(struct pipe_context *pctx, { struct zink_context *ctx = zink_context(pctx); - if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state && - (num_buffers || (!buffers && ctx->gfx_pipeline_state.vertex_buffers_enabled_mask))) - ctx->gfx_pipeline_state.vertex_state_dirty = true; + if (buffers) { + if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state) + ctx->gfx_pipeline_state.vertex_state_dirty = true; + for (int i = 0; i < num_buffers; ++i) { + const struct pipe_vertex_buffer *vb = buffers + i; + update_existing_vbo(ctx, start_slot + i); + if (vb->buffer.resource) { + struct zink_resource *res = zink_resource(vb->buffer.resource); + res->vbo_bind_count++; + res->bind_count[0]++; + zink_resource_buffer_barrier(ctx, NULL, res, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT); + } + } + } else if (ctx->gfx_pipeline_state.vertex_buffers_enabled_mask) { + if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state) + ctx->gfx_pipeline_state.vertex_state_dirty = true; + unsigned vertex_buffers_enabled_mask = ctx->gfx_pipeline_state.vertex_buffers_enabled_mask; + while (vertex_buffers_enabled_mask) { + unsigned slot = u_bit_scan(&vertex_buffers_enabled_mask); + update_existing_vbo(ctx, slot); + } + } util_set_vertex_buffers_mask(ctx->vertex_buffers, &ctx->gfx_pipeline_state.vertex_buffers_enabled_mask, buffers, start_slot, num_buffers, unbind_num_trailing_slots, take_ownership); @@ -1887,9 +1919,12 @@ is_shader_pipline_stage(VkPipelineStageFlags pipeline) static void resource_check_defer_barrier(struct zink_context *ctx, struct zink_resource *res, VkPipelineStageFlags pipeline) { - if (res->bind_count[0] && !is_shader_pipline_stage(pipeline)) - /* gfx rebind */ - _mesa_set_add(ctx->need_barriers[0], res); + if (res->bind_count[0]) { + if ((res->obj->is_buffer && res->vbo_bind_count && !(pipeline & VK_PIPELINE_STAGE_VERTEX_INPUT_BIT)) || + ((!res->obj->is_buffer || res->vbo_bind_count != res->bind_count[0]) && !is_shader_pipline_stage(pipeline))) + /* gfx rebind */ + _mesa_set_add(ctx->need_barriers[0], res); + } if (res->bind_count[1] && !(pipeline & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT)) /* compute rebind */ _mesa_set_add(ctx->need_barriers[1], res); diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c index 8c5863f9350..efcb90373c2 100644 --- a/src/gallium/drivers/zink/zink_draw.c +++ b/src/gallium/drivers/zink/zink_draw.c @@ -101,21 +101,6 @@ zink_emit_stream_output_targets(struct pipe_context *pctx) ctx->dirty_so_targets = false; } -static void -barrier_vertex_buffers(struct zink_context *ctx) -{ - const struct zink_vertex_elements_state *elems = ctx->element_state; - for (unsigned i = 0; i < elems->hw_state.num_bindings; i++) { - struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ctx->element_state->binding_map[i]; - assert(vb); - if (vb->buffer.resource) { - struct zink_resource *res = zink_resource(vb->buffer.resource); - zink_resource_buffer_barrier(ctx, NULL, res, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT); - } - } -} - static void check_buffer_barrier(struct zink_context *ctx, struct pipe_resource *pres, VkAccessFlags flags, VkPipelineStageFlags pipeline) { @@ -376,6 +361,11 @@ update_barriers(struct zink_context *ctx, bool is_compute) access |= VK_ACCESS_UNIFORM_READ_BIT; bind_count -= res->ubo_bind_count[is_compute]; } + if (!is_compute && res->vbo_bind_count) { + access |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + pipeline |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + bind_count -= res->vbo_bind_count; + } } if (bind_count) access |= VK_ACCESS_SHADER_READ_BIT; @@ -512,7 +502,6 @@ zink_draw_vbo(struct pipe_context *pctx, if (so_target) zink_emit_xfb_vertex_input_barrier(ctx, zink_resource(so_target->base.buffer)); - barrier_vertex_buffers(ctx); barrier_draw_buffers(ctx, dinfo, dindirect, index_buffer); for (int i = 0; i < ZINK_SHADER_COUNT; i++) { diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h index 92ac55c3773..821f616c807 100644 --- a/src/gallium/drivers/zink/zink_resource.h +++ b/src/gallium/drivers/zink/zink_resource.h @@ -96,6 +96,7 @@ struct zink_resource { union { struct { struct util_range valid_buffer_range; + uint16_t vbo_bind_count; uint16_t ubo_bind_count[2]; }; struct {