diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 0ac6c47af60..fa51d5d7e9c 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -5138,3 +5138,82 @@ zink_tc_context_unwrap(struct pipe_context *pctx, bool threaded) pctx = trace_get_possibly_threaded_context(pctx); return zink_context(pctx); } + + +static bool +add_implicit_color_feedback_loop(struct zink_context *ctx, struct zink_resource *res) +{ + if (!res->fb_bind_count || !res->sampler_bind_count[0] || ctx->feedback_loops & res->fb_binds) + return false; + bool is_feedback = false; + /* avoid false positives when a texture is bound but not used */ + u_foreach_bit(vkstage, res->gfx_barrier) { + VkPipelineStageFlags vkstagebit = BITFIELD_BIT(vkstage); + if (vkstagebit < VK_PIPELINE_STAGE_VERTEX_SHADER_BIT || vkstagebit > VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) + continue; + /* in-range VkPipelineStageFlagBits can be converted to VkShaderStageFlags with a bitshift */ + gl_shader_stage stage = vk_to_mesa_shader_stage((VkShaderStageFlagBits)(vkstagebit >> 3)); + /* check shader texture usage against resource's sampler binds */ + if ((ctx->gfx_stages[stage] && (res->sampler_binds[stage] & ctx->gfx_stages[stage]->nir->info.textures_used[0]))) + is_feedback = true; + } + if (!is_feedback) + return false; + /* new feedback loop detected */ + if (res->aspect == VK_IMAGE_ASPECT_COLOR_BIT) { + if (!ctx->gfx_pipeline_state.feedback_loop) + ctx->gfx_pipeline_state.dirty = true; + ctx->gfx_pipeline_state.feedback_loop = true; + } else { + if (!ctx->gfx_pipeline_state.feedback_loop_zs) + ctx->gfx_pipeline_state.dirty = true; + ctx->gfx_pipeline_state.feedback_loop_zs = true; + } + ctx->rp_layout_changed = true; + ctx->feedback_loops |= res->fb_binds; + u_foreach_bit(idx, res->fb_binds) { + if (zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout) + ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT; + else + ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + return true; +} + +void +zink_update_barriers(struct zink_context *ctx, bool is_compute, + struct pipe_resource *index, struct pipe_resource *indirect, struct pipe_resource *indirect_draw_count) +{ + if (!ctx->need_barriers[is_compute]->entries) + return; + struct set *need_barriers = ctx->need_barriers[is_compute]; + ctx->barrier_set_idx[is_compute] = !ctx->barrier_set_idx[is_compute]; + ctx->need_barriers[is_compute] = &ctx->update_barriers[is_compute][ctx->barrier_set_idx[is_compute]]; + set_foreach(need_barriers, he) { + struct zink_resource *res = (struct zink_resource *)he->key; + if (res->bind_count[is_compute]) { + VkPipelineStageFlagBits pipeline = is_compute ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : res->gfx_barrier; + if (res->base.b.target == PIPE_BUFFER) + zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, res->barrier_access[is_compute], pipeline); + else { + bool is_feedback = is_compute ? false : add_implicit_color_feedback_loop(ctx, res); + VkImageLayout layout = zink_descriptor_util_image_layout_eval(ctx, res, is_compute); + /* GENERAL is only used for feedback loops and storage image binds */ + if (is_feedback || layout != VK_IMAGE_LAYOUT_GENERAL || res->image_bind_count[is_compute]) + zink_screen(ctx->base.screen)->image_barrier(ctx, res, layout, res->barrier_access[is_compute], pipeline); + } + if (zink_resource_access_is_write(res->barrier_access[is_compute])) + res->obj->unordered_read = res->obj->unordered_write = false; + else + res->obj->unordered_read = false; + /* always barrier on draw if this resource has either multiple image write binds or + * image write binds and image read binds + */ + if (res->write_bind_count[is_compute] && res->bind_count[is_compute] > 1) + _mesa_set_add_pre_hashed(ctx->need_barriers[is_compute], he->hash, res); + } + _mesa_set_remove(need_barriers, he); + if (!need_barriers->entries) + break; + } +} \ No newline at end of file diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index e20980a335f..62546db7f07 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -162,6 +162,11 @@ void zink_init_grid_functions(struct zink_context *ctx); struct zink_context * zink_tc_context_unwrap(struct pipe_context *pctx, bool threaded); + +void +zink_update_barriers(struct zink_context *ctx, bool is_compute, + struct pipe_resource *index, struct pipe_resource *indirect, struct pipe_resource *indirect_draw_count); + #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index 1a0d1365e3e..6ae6be594ab 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -280,84 +280,6 @@ draw(struct zink_context *ctx, } } -static bool -add_implicit_color_feedback_loop(struct zink_context *ctx, struct zink_resource *res) -{ - if (!res->fb_bind_count || !res->sampler_bind_count[0] || ctx->feedback_loops & res->fb_binds) - return false; - bool is_feedback = false; - /* avoid false positives when a texture is bound but not used */ - u_foreach_bit(vkstage, res->gfx_barrier) { - VkPipelineStageFlags vkstagebit = BITFIELD_BIT(vkstage); - if (vkstagebit < VK_PIPELINE_STAGE_VERTEX_SHADER_BIT || vkstagebit > VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) - continue; - /* in-range VkPipelineStageFlagBits can be converted to VkShaderStageFlags with a bitshift */ - gl_shader_stage stage = vk_to_mesa_shader_stage((VkShaderStageFlagBits)(vkstagebit >> 3)); - /* check shader texture usage against resource's sampler binds */ - if ((ctx->gfx_stages[stage] && (res->sampler_binds[stage] & ctx->gfx_stages[stage]->nir->info.textures_used[0]))) - is_feedback = true; - } - if (!is_feedback) - return false; - /* new feedback loop detected */ - if (res->aspect == VK_IMAGE_ASPECT_COLOR_BIT) { - if (!ctx->gfx_pipeline_state.feedback_loop) - ctx->gfx_pipeline_state.dirty = true; - ctx->gfx_pipeline_state.feedback_loop = true; - } else { - if (!ctx->gfx_pipeline_state.feedback_loop_zs) - ctx->gfx_pipeline_state.dirty = true; - ctx->gfx_pipeline_state.feedback_loop_zs = true; - } - ctx->rp_layout_changed = true; - ctx->feedback_loops |= res->fb_binds; - u_foreach_bit(idx, res->fb_binds) { - if (zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout) - ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT; - else - ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - } - return true; -} - -static void -update_barriers(struct zink_context *ctx, bool is_compute, - struct pipe_resource *index, struct pipe_resource *indirect, struct pipe_resource *indirect_draw_count) -{ - if (!ctx->need_barriers[is_compute]->entries) - return; - struct set *need_barriers = ctx->need_barriers[is_compute]; - ctx->barrier_set_idx[is_compute] = !ctx->barrier_set_idx[is_compute]; - ctx->need_barriers[is_compute] = &ctx->update_barriers[is_compute][ctx->barrier_set_idx[is_compute]]; - set_foreach(need_barriers, he) { - struct zink_resource *res = (struct zink_resource *)he->key; - if (res->bind_count[is_compute]) { - VkPipelineStageFlagBits pipeline = is_compute ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : res->gfx_barrier; - if (res->base.b.target == PIPE_BUFFER) - zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, res->barrier_access[is_compute], pipeline); - else { - bool is_feedback = is_compute ? false : add_implicit_color_feedback_loop(ctx, res); - VkImageLayout layout = zink_descriptor_util_image_layout_eval(ctx, res, is_compute); - /* GENERAL is only used for feedback loops and storage image binds */ - if (is_feedback || layout != VK_IMAGE_LAYOUT_GENERAL || res->image_bind_count[is_compute]) - zink_screen(ctx->base.screen)->image_barrier(ctx, res, layout, res->barrier_access[is_compute], pipeline); - } - if (zink_resource_access_is_write(res->barrier_access[is_compute])) - res->obj->unordered_read = res->obj->unordered_write = false; - else - res->obj->unordered_read = false; - /* always barrier on draw if this resource has either multiple image write binds or - * image write binds and image read binds - */ - if (res->write_bind_count[is_compute] && res->bind_count[is_compute] > 1) - _mesa_set_add_pre_hashed(ctx->need_barriers[is_compute], he->hash, res); - } - _mesa_set_remove(need_barriers, he); - if (!need_barriers->entries) - break; - } -} - template static bool update_gfx_pipeline(struct zink_context *ctx, struct zink_batch_state *bs, enum pipe_prim_type mode) @@ -499,7 +421,7 @@ zink_draw(struct pipe_context *pctx, barrier_draw_buffers(ctx, dinfo, dindirect, index_buffer); /* this may re-emit draw buffer barriers, but such synchronization is harmless */ - update_barriers(ctx, false, index_buffer, dindirect ? dindirect->buffer : NULL, dindirect ? dindirect->indirect_draw_count : NULL); + zink_update_barriers(ctx, false, index_buffer, dindirect ? dindirect->buffer : NULL, dindirect ? dindirect->indirect_draw_count : NULL); /* ensure synchronization between doing streamout with counter buffer * and using counter buffer for indirect draw @@ -1022,7 +944,7 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) check_buffer_barrier(ctx, info->indirect, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT); } - update_barriers(ctx, true, NULL, info->indirect, NULL); + zink_update_barriers(ctx, true, NULL, info->indirect, NULL); if (ctx->memory_barrier) zink_flush_memory_barrier(ctx, true);