diff --git a/src/gallium/drivers/zink/zink_blit.c b/src/gallium/drivers/zink/zink_blit.c index 83a35738a5a..45899d3461b 100644 --- a/src/gallium/drivers/zink/zink_blit.c +++ b/src/gallium/drivers/zink/zink_blit.c @@ -356,12 +356,36 @@ zink_blit(struct pipe_context *pctx, */ apply_dst_clears(ctx, info, true); zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box)); + unsigned rp_clears_enabled = ctx->rp_clears_enabled; + unsigned clears_enabled = ctx->clears_enabled; + if (!dst->fb_bind_count) { + /* avoid applying clears from fb unbind by storing and re-setting them after the blit */ + ctx->rp_clears_enabled = 0; + ctx->clears_enabled = 0; + } else { + unsigned bit; + /* convert to PIPE_CLEAR_XYZ */ + if (dst->fb_binds & BITFIELD_BIT(PIPE_MAX_COLOR_BUFS)) + bit = PIPE_CLEAR_DEPTHSTENCIL; + else + bit = dst->fb_binds << 2; + rp_clears_enabled &= ~bit; + clears_enabled &= ~bit; + ctx->rp_clears_enabled &= bit; + ctx->clears_enabled &= bit; + } /* this will draw a full-resource quad, so ignore existing data */ - if (util_blit_covers_whole_resource(info)) + bool whole = util_blit_covers_whole_resource(info); + if (whole) pctx->invalidate_resource(pctx, info->dst.resource); - ctx->blitting = true; zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES); + if (info->src.format != info->src.resource->format) + zink_resource_object_init_mutable(ctx, src); + if (info->dst.format != info->dst.resource->format) + zink_resource_object_init_mutable(ctx, dst); + zink_blit_barriers(ctx, src, dst, whole); + ctx->blitting = true; if (stencil_blit) { struct pipe_surface *dst_view, dst_templ; @@ -386,6 +410,8 @@ zink_blit(struct pipe_context *pctx, util_blitter_blit(ctx->blitter, info); } ctx->blitting = false; + ctx->rp_clears_enabled = rp_clears_enabled; + ctx->clears_enabled = clears_enabled; end: if (needs_present_readback) zink_kopper_present_readback(ctx, src); diff --git a/src/gallium/drivers/zink/zink_clear.c b/src/gallium/drivers/zink/zink_clear.c index 4a14e58c389..19c9a331384 100644 --- a/src/gallium/drivers/zink/zink_clear.c +++ b/src/gallium/drivers/zink/zink_clear.c @@ -539,6 +539,7 @@ zink_clear_texture(struct pipe_context *pctx, surf = create_clear_surface(pctx, pres, level, box); util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); set_clear_fb(pctx, surf, NULL); + zink_blit_barriers(ctx, NULL, res, false); ctx->blitting = true; ctx->queries_disabled = true; pctx->clear(pctx, PIPE_CLEAR_COLOR0, &scissor, &color, 0, 0); @@ -562,6 +563,7 @@ zink_clear_texture(struct pipe_context *pctx, flags |= PIPE_CLEAR_STENCIL; surf = create_clear_surface(pctx, pres, level, box); util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); + zink_blit_barriers(ctx, NULL, res, false); ctx->blitting = true; set_clear_fb(pctx, NULL, surf); ctx->queries_disabled = true; @@ -633,6 +635,7 @@ zink_clear_render_target(struct pipe_context *pctx, struct pipe_surface *dst, util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); set_clear_fb(pctx, dst, NULL); struct pipe_scissor_state scissor = {dstx, dsty, dstx + width, dsty + height}; + zink_blit_barriers(ctx, NULL, zink_resource(dst->texture), false); ctx->blitting = true; pctx->clear(pctx, PIPE_CLEAR_COLOR0, &scissor, color, 0, 0); util_blitter_restore_fb_state(ctx->blitter); @@ -662,6 +665,7 @@ zink_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *dst, if (!cur_attachment) { util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state); set_clear_fb(pctx, NULL, dst); + zink_blit_barriers(ctx, NULL, zink_resource(dst->texture), false); ctx->blitting = true; } struct pipe_scissor_state scissor = {dstx, dsty, dstx + width, dsty + height}; diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 552b8ef5757..13c08f9d1c2 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -648,7 +648,7 @@ update_descriptor_state_sampler(struct zink_context *ctx, gl_shader_stage shader } } else { struct zink_surface *surface = get_imageview_for_binding(ctx, shader, type, slot); - ctx->di.textures[shader][slot].imageLayout = get_layout_for_binding(ctx, res, type, shader == MESA_SHADER_COMPUTE); + ctx->di.textures[shader][slot].imageLayout = ctx->blitting ? res->layout : get_layout_for_binding(ctx, res, type, shader == MESA_SHADER_COMPUTE); ctx->di.textures[shader][slot].imageView = surface->image_view; if (!screen->have_D24_UNORM_S8_UINT && ctx->sampler_states[shader][slot] && ctx->sampler_states[shader][slot]->sampler_clamped) { @@ -2862,6 +2862,8 @@ zink_prep_fb_attachment(struct zink_context *ctx, struct zink_surface *surf, uns if (!i) zink_update_fbfetch(ctx); } + if (ctx->blitting) + return surf->image_view; VkImageLayout layout; if (ctx->tc && zink_screen(ctx->base.screen)->driver_workarounds.track_renderpasses && !ctx->blitting) { layout = zink_tc_renderpass_info_parse(ctx, &ctx->dynamic_fb.tc_info, i < ctx->fb_state.nr_cbufs ? i : PIPE_MAX_COLOR_BUFS, &pipeline, &access); @@ -3205,7 +3207,7 @@ unbind_fb_surface(struct zink_context *ctx, struct pipe_surface *surf, unsigned check_resource_for_batch_ref(ctx, res); if (res->sampler_bind_count[0]) { update_res_sampler_layouts(ctx, res); - if (res->layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + if (res->layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && !ctx->blitting) _mesa_set_add(ctx->need_barriers[0], res); } } @@ -3727,6 +3729,7 @@ static void resource_check_defer_image_barrier(struct zink_context *ctx, struct zink_resource *res, VkImageLayout layout, VkPipelineStageFlags pipeline) { assert(!res->obj->is_buffer); + assert(!ctx->blitting); bool is_compute = pipeline == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; /* if this is a non-shader barrier and there are binds, always queue a shader barrier */ @@ -4094,6 +4097,13 @@ zink_flush(struct pipe_context *pctx, ctx->fbfetch_outputs = 0; ctx->rp_changed = true; } + if (ctx->fb_state.zsbuf) + zink_blit_barriers(ctx, NULL, zink_resource(ctx->fb_state.zsbuf->texture), false); + + for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++) { + if (ctx->fb_state.cbufs[i]) + zink_blit_barriers(ctx, NULL, zink_resource(ctx->fb_state.cbufs[i]->texture), false); + } ctx->blitting = true; /* start rp to do all the clears */ zink_batch_rp(ctx); @@ -5034,6 +5044,7 @@ zink_resource_commit(struct pipe_context *pctx, struct pipe_resource *pres, unsi static void rebind_image(struct zink_context *ctx, struct zink_resource *res) { + assert(!ctx->blitting); if (res->fb_binds) zink_rebind_framebuffer(ctx, res); if (!zink_resource_has_binds(res)) @@ -5111,6 +5122,7 @@ zink_rebind_all_buffers(struct zink_context *ctx) void zink_rebind_all_images(struct zink_context *ctx) { + assert(!ctx->blitting); rebind_fb_state(ctx, NULL, false); for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { for (unsigned j = 0; j < ctx->di.num_sampler_views[i]; j++) { @@ -5628,6 +5640,7 @@ 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) { + assert(!ctx->blitting); if (!ctx->need_barriers[is_compute]->entries) return; struct set *need_barriers = ctx->need_barriers[is_compute]; diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index 7431702aae2..c74b3ead3fe 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -364,15 +364,15 @@ zink_draw(struct pipe_context *pctx, unsigned work_count = ctx->batch.work_count; enum pipe_prim_type mode = (enum pipe_prim_type)dinfo->mode; - if (ctx->memory_barrier) + if (ctx->memory_barrier && !ctx->blitting) zink_flush_memory_barrier(ctx, false); - if (unlikely(ctx->buffer_rebind_counter < screen->buffer_rebind_counter)) { + if (unlikely(ctx->buffer_rebind_counter < screen->buffer_rebind_counter && !ctx->blitting)) { ctx->buffer_rebind_counter = screen->buffer_rebind_counter; zink_rebind_all_buffers(ctx); } - if (unlikely(ctx->image_rebind_counter < screen->image_rebind_counter)) { + if (unlikely(ctx->image_rebind_counter < screen->image_rebind_counter && !ctx->blitting)) { ctx->image_rebind_counter = screen->image_rebind_counter; zink_rebind_all_images(ctx); } @@ -423,7 +423,8 @@ 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 */ - zink_update_barriers(ctx, false, index_buffer, dindirect ? dindirect->buffer : NULL, dindirect ? dindirect->indirect_draw_count : NULL); + if (!ctx->blitting) + 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 diff --git a/src/gallium/drivers/zink/zink_render_pass.c b/src/gallium/drivers/zink/zink_render_pass.c index ed3abc34ba5..f6dbe1ef262 100644 --- a/src/gallium/drivers/zink/zink_render_pass.c +++ b/src/gallium/drivers/zink/zink_render_pass.c @@ -786,6 +786,7 @@ zink_begin_render_pass(struct zink_context *ctx) src_view = ctx->base.create_sampler_view(&ctx->base, src, &src_templ); zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES); + zink_blit_barriers(ctx, zink_resource(src), zink_resource(dst_view->texture), false); ctx->blitting = true; util_blitter_blit_generic(ctx->blitter, dst_view, &dstbox, src_view, &dstbox, ctx->fb_state.width, ctx->fb_state.height,