From a64ef1cd12611116f62901a05a165b03dbff6ebc Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 Jan 2021 09:37:17 -0500 Subject: [PATCH] zink: reapply resource/surface refs after app flushes instead of doing this during descriptor update, we can automatically handle this rollover Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_context.c | 145 ++++++++++++++++++++---- src/gallium/drivers/zink/zink_context.h | 3 + src/gallium/drivers/zink/zink_draw.c | 5 + 3 files changed, 129 insertions(+), 24 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 70f297c51ba..d7adcb2b01c 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -935,7 +935,8 @@ zink_set_constant_buffer(struct pipe_context *pctx, new_res->bind_stages |= 1 << shader; new_res->ubo_bind_count[shader == PIPE_SHADER_COMPUTE]++; new_res->bind_count[shader == PIPE_SHADER_COMPUTE]++; - zink_batch_reference_resource_rw(&ctx->batch, new_res, false); + if (!ctx->descriptor_refs_dirty[shader == PIPE_SHADER_COMPUTE]) + zink_batch_reference_resource_rw(&ctx->batch, new_res, false); zink_resource_buffer_barrier(ctx, NULL, new_res, VK_ACCESS_UNIFORM_READ_BIT, zink_pipeline_flags_from_stage(zink_shader_stage(shader))); } @@ -1013,9 +1014,9 @@ zink_set_shader_buffers(struct pipe_context *pctx, if (ctx->writable_ssbos[p_stage] & BITFIELD64_BIT(start_slot + i)) { res->write_bind_count[p_stage == PIPE_SHADER_COMPUTE]++; access |= VK_ACCESS_SHADER_WRITE_BIT; - zink_batch_reference_resource_rw(&ctx->batch, res, true); - } else - zink_batch_reference_resource_rw(&ctx->batch, res, false); + } + if (!ctx->descriptor_refs_dirty[p_stage == PIPE_SHADER_COMPUTE]) + zink_batch_reference_resource_rw(&ctx->batch, res, access & VK_ACCESS_SHADER_WRITE_BIT); pipe_resource_reference(&ssbo->buffer, &res->base.b); ssbo->buffer_offset = buffers[i].buffer_offset; ssbo->buffer_size = MIN2(buffers[i].buffer_size, res->obj->size - ssbo->buffer_offset); @@ -1130,11 +1131,8 @@ zink_set_shader_images(struct pipe_context *pctx, if (image_view->base.access & PIPE_IMAGE_ACCESS_WRITE) { zink_resource(image_view->base.resource)->write_bind_count[p_stage == PIPE_SHADER_COMPUTE]++; access |= VK_ACCESS_SHADER_WRITE_BIT; - zink_batch_reference_resource_rw(&ctx->batch, zink_resource(image_view->base.resource), true); } if (image_view->base.access & PIPE_IMAGE_ACCESS_READ) { - if (!access) - zink_batch_reference_resource_rw(&ctx->batch, zink_resource(image_view->base.resource), false); access |= VK_ACCESS_SHADER_READ_BIT; } if (images[i].resource->target == PIPE_BUFFER) { @@ -1144,7 +1142,6 @@ zink_set_shader_images(struct pipe_context *pctx, images[i].u.buf.offset + images[i].u.buf.size); zink_resource_buffer_barrier(ctx, NULL, res, access, zink_pipeline_flags_from_stage(zink_shader_stage(p_stage))); - zink_batch_reference_bufferview(&ctx->batch, image_view->buffer_view); } else { struct pipe_surface tmpl = {}; tmpl.format = images[i].format; @@ -1166,7 +1163,11 @@ zink_set_shader_images(struct pipe_context *pctx, zink_pipeline_flags_from_stage(zink_shader_stage(p_stage))); else _mesa_set_add(ctx->need_barriers[0], res); - zink_batch_reference_surface(&ctx->batch, image_view->surface); + } + if (!ctx->descriptor_refs_dirty[p_stage == PIPE_SHADER_COMPUTE]) { + zink_batch_reference_resource_rw(&ctx->batch, zink_resource(image_view->base.resource), + zink_resource_access_is_write(access)); + zink_batch_reference_image_view(&ctx->batch, image_view); } update = true; } else if (image_view->base.resource) { @@ -1226,7 +1227,6 @@ zink_set_sampler_views(struct pipe_context *pctx, unbind_samplerview(ctx, shader_type, start_slot + i); if (b && b->base.texture) { struct zink_resource *res = zink_resource(b->base.texture); - zink_batch_reference_resource_rw(&ctx->batch, res, false); if (res->base.b.target == PIPE_BUFFER) { if (res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)) { /* if this resource has been rebound while it wasn't set here, @@ -1244,8 +1244,8 @@ zink_set_sampler_views(struct pipe_context *pctx, } zink_resource_buffer_barrier(ctx, NULL, res, VK_ACCESS_SHADER_READ_BIT, zink_pipeline_flags_from_stage(zink_shader_stage(shader_type))); - zink_batch_reference_bufferview(&ctx->batch, b->buffer_view); - update |= !a || a->buffer_view->buffer_view != b->buffer_view->buffer_view; + if (!a || a->buffer_view->buffer_view != b->buffer_view->buffer_view) + update = true; } else if (!res->obj->is_buffer) { if (res->obj != b->image_view->obj) { struct pipe_surface *psurf = &b->image_view->base; @@ -1253,20 +1253,22 @@ zink_set_sampler_views(struct pipe_context *pctx, zink_rebind_surface(ctx, &psurf); b->image_view = zink_surface(psurf); update |= iv != b->image_view->image_view; - } else { - if (a != b) - update = true; - if (shader_type == PIPE_SHADER_COMPUTE) - zink_resource_image_barrier(ctx, NULL, res, get_layout_for_binding(res, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW), - VK_ACCESS_SHADER_READ_BIT, - zink_pipeline_flags_from_stage(zink_shader_stage(shader_type))); - else - _mesa_set_add(ctx->need_barriers[0], res); - } + } else if (a != b) + update = true; res->sampler_binds[shader_type] |= BITFIELD_BIT(start_slot + i); - zink_batch_reference_surface(&ctx->batch, b->image_view); - update |= !a || a->image_view->image_view != b->image_view->image_view; + if (shader_type == PIPE_SHADER_COMPUTE) + zink_resource_image_barrier(ctx, NULL, res, get_layout_for_binding(res, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW), + VK_ACCESS_SHADER_READ_BIT, + zink_pipeline_flags_from_stage(zink_shader_stage(shader_type))); + else + _mesa_set_add(ctx->need_barriers[0], res); + if (!a) + update = true; + } + if (!ctx->descriptor_refs_dirty[shader_type == PIPE_SHADER_COMPUTE]) { + zink_batch_reference_resource_rw(&ctx->batch, res, false); + zink_batch_reference_sampler_view(&ctx->batch, b); } res->bind_count[shader_type == PIPE_SHADER_COMPUTE]++; res->bind_history |= BITFIELD_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW); @@ -1583,6 +1585,100 @@ sync_flush(struct zink_context *ctx, struct zink_batch_state *bs) util_queue_fence_wait(&bs->flush_completed); } +static inline VkAccessFlags +get_access_flags_for_binding(struct zink_context *ctx, enum zink_descriptor_type type, enum pipe_shader_type stage, unsigned idx) +{ + VkAccessFlags flags = 0; + switch (type) { + case ZINK_DESCRIPTOR_TYPE_UBO: + return VK_ACCESS_UNIFORM_READ_BIT; + case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW: + return VK_ACCESS_SHADER_READ_BIT; + case ZINK_DESCRIPTOR_TYPE_SSBO: { + flags = VK_ACCESS_SHADER_READ_BIT; + if (ctx->writable_ssbos[stage] & (1 << idx)) + flags |= VK_ACCESS_SHADER_WRITE_BIT; + return flags; + } + case ZINK_DESCRIPTOR_TYPE_IMAGE: { + struct zink_image_view *image_view = &ctx->image_views[stage][idx]; + if (image_view->base.access & PIPE_IMAGE_ACCESS_READ) + flags |= VK_ACCESS_SHADER_READ_BIT; + if (image_view->base.access & PIPE_IMAGE_ACCESS_WRITE) + flags |= VK_ACCESS_SHADER_WRITE_BIT; + return flags; + } + default: + break; + } + unreachable("ACK"); + return 0; +} + +static inline void +add_surface_ref(struct zink_context *ctx, struct zink_resource *res, union zink_descriptor_surface *surface) +{ + if (!surface) + return; + if (res->obj->is_buffer) { + if (surface->bufferview) + zink_batch_reference_bufferview(&ctx->batch, surface->bufferview); + } else if (surface->surface) + zink_batch_reference_surface(&ctx->batch, surface->surface); +} + +static void +update_resource_refs_for_stage(struct zink_context *ctx, enum pipe_shader_type stage) +{ + struct zink_batch *batch = &ctx->batch; + unsigned max_slot[] = { + [ZINK_DESCRIPTOR_TYPE_UBO] = ctx->di.num_ubos[stage], + [ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = ctx->di.num_samplers[stage], + [ZINK_DESCRIPTOR_TYPE_SSBO] = ctx->di.num_ssbos[stage], + [ZINK_DESCRIPTOR_TYPE_IMAGE] = ctx->di.num_images[stage] + }; + for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) { + for (unsigned j = 0; j < max_slot[i]; j++) { + if (ctx->di.descriptor_res[i][stage][j]) { + struct zink_resource *res = ctx->di.descriptor_res[i][stage][j]; + if (!res) + continue; + bool is_write = zink_resource_access_is_write(get_access_flags_for_binding(ctx, i, stage, j)); + zink_batch_reference_resource_rw(batch, res, is_write); + + struct zink_sampler_view *sv = zink_sampler_view(ctx->sampler_views[stage][j]); + struct zink_sampler_state *sampler_state = ctx->sampler_states[stage][j]; + struct zink_image_view *iv = &ctx->image_views[stage][j]; + if (sampler_state && i == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW && j <= ctx->di.num_samplers[stage]) + zink_batch_usage_set(&sampler_state->batch_uses, ctx->curr_batch); + if (sv && i == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW && j <= ctx->di.num_sampler_views[stage]) + zink_batch_reference_sampler_view(batch, sv); + else if (i == ZINK_DESCRIPTOR_TYPE_IMAGE && j <= ctx->di.num_images[stage]) + zink_batch_reference_image_view(batch, iv); + } + } + } +} + +void +zink_update_descriptor_refs(struct zink_context *ctx, bool compute) +{ + struct zink_batch *batch = &ctx->batch; + if (compute) + update_resource_refs_for_stage(ctx, PIPE_SHADER_COMPUTE); + else { + for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) + update_resource_refs_for_stage(ctx, i); + unsigned vertex_buffers_enabled_mask = ctx->gfx_pipeline_state.vertex_buffers_enabled_mask; + unsigned last_vbo = util_last_bit(vertex_buffers_enabled_mask); + for (unsigned i = 0; i < last_vbo + 1; i++) { + if (ctx->vertex_buffers[i].buffer.resource) + zink_batch_reference_resource_rw(batch, zink_resource(ctx->vertex_buffers[i].buffer.resource), false); + } + } + ctx->descriptor_refs_dirty[compute] = false; +} + static void flush_batch(struct zink_context *ctx, bool sync) { @@ -1604,6 +1700,7 @@ flush_batch(struct zink_context *ctx, bool sync) zink_start_batch(ctx, batch); if (zink_screen(ctx->base.screen)->info.have_EXT_transform_feedback && ctx->num_so_targets) ctx->dirty_so_targets = true; + ctx->descriptor_refs_dirty[0] = ctx->descriptor_refs_dirty[1] = true; } } diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index edf2189b704..0196d3dacce 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -251,6 +251,7 @@ struct zink_context { union zink_descriptor_surface sampler_surfaces[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; union zink_descriptor_surface image_surfaces[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES]; } di; + bool descriptor_refs_dirty[2]; struct set *need_barriers[2]; //gfx, compute struct set update_barriers[2][2]; //[gfx, compute][current, next] uint8_t barrier_set_idx[2]; @@ -397,4 +398,6 @@ zink_buffer_view_reference(struct zink_screen *screen, if (dst) *dst = src; } +void +zink_update_descriptor_refs(struct zink_context *ctx, bool compute); #endif diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c index efcb90373c2..81761eacf81 100644 --- a/src/gallium/drivers/zink/zink_draw.c +++ b/src/gallium/drivers/zink/zink_draw.c @@ -524,6 +524,9 @@ zink_draw_vbo(struct pipe_context *pctx, if (zink_program_has_descriptors(&gfx_program->base)) screen->descriptors_update(ctx, false); + if (ctx->descriptor_refs_dirty[0]) + zink_update_descriptor_refs(ctx, false); + struct zink_batch *batch = zink_batch_rp(ctx); VkViewport viewports[PIPE_MAX_VIEWPORTS]; for (unsigned i = 0; i < ctx->vp_state.num_viewports; i++) { @@ -778,6 +781,8 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) if (zink_program_has_descriptors(&comp_program->base)) screen->descriptors_update(ctx, true); + if (ctx->descriptor_refs_dirty[1]) + zink_update_descriptor_refs(ctx, true); vkCmdBindPipeline(batch->state->cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);