diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 4df38c98c4e..93e25e5b554 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -379,7 +379,9 @@ get_layout_for_binding(struct zink_resource *res, enum zink_descriptor_type type switch (type) { case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW: return res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_IMAGE) ? - VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VK_IMAGE_LAYOUT_GENERAL : + res->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ? + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; case ZINK_DESCRIPTOR_TYPE_IMAGE: return VK_IMAGE_LAYOUT_GENERAL; default: @@ -1149,7 +1151,7 @@ unbind_shader_image(struct zink_context *ctx, enum pipe_shader_type stage, unsig !res->image_bind_count[is_compute]) { for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) { if (res->sampler_binds[i]) { - zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + 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(i))); break; @@ -1438,6 +1440,11 @@ get_render_pass(struct zink_context *ctx) clears |= PIPE_CLEAR_DEPTH; if (state.rts[fb->nr_cbufs].clear_stencil) clears |= PIPE_CLEAR_STENCIL; + const uint64_t outputs_written = ctx->gfx_stages[PIPE_SHADER_FRAGMENT] ? + ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir->info.outputs_written : 0; + bool needs_write = (ctx->dsa_state && ctx->dsa_state->hw_state.depth_write) || + outputs_written & (BITFIELD64_BIT(FRAG_RESULT_DEPTH) | BITFIELD64_BIT(FRAG_RESULT_STENCIL)); + state.rts[fb->nr_cbufs].needs_write = needs_write || state.rts[fb->nr_cbufs].clear_color || state.rts[fb->nr_cbufs].clear_stencil; state.num_rts++; } state.have_zsbuf = fb->zsbuf != NULL; @@ -1594,11 +1601,12 @@ begin_render_pass(struct zink_context *ctx) zink_batch_reference_resource_rw(batch, zink_resource(surf->base.texture), true); zink_batch_reference_surface(batch, surf); - VkImageLayout layout = i == ctx->framebuffer->state.num_attachments - 1 && fb_state->zsbuf ? - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; struct zink_resource *res = zink_resource(surf->base.texture); - zink_resource_image_barrier(ctx, NULL, res, layout, 0, 0); + VkAccessFlags access; + VkPipelineStageFlags pipeline; + VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass, + i, &pipeline, &access); + zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline); } } diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c index 8d67e6c9f9a..bd3a4aa651d 100644 --- a/src/gallium/drivers/zink/zink_descriptors.c +++ b/src/gallium/drivers/zink/zink_descriptors.c @@ -1237,7 +1237,9 @@ update_sampler_descriptors(struct zink_context *ctx, struct zink_descriptor_set } else if (res) { imageview = sampler_view->image_view->image_view; layout = (res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_IMAGE)) ? - VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VK_IMAGE_LAYOUT_GENERAL : + res->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ? + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; sampler = ctx->sampler_states[stage][index + k]; } assert(num_resources < num_bindings); diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c index 7357c39a27c..0e70efed0de 100644 --- a/src/gallium/drivers/zink/zink_draw.c +++ b/src/gallium/drivers/zink/zink_draw.c @@ -385,7 +385,9 @@ update_barriers(struct zink_context *ctx, bool is_compute) if (res->base.b.target == PIPE_BUFFER) zink_resource_buffer_barrier(ctx, NULL, res, access, pipeline); else { - VkImageLayout layout = res->image_bind_count[is_compute] ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkImageLayout layout = res->image_bind_count[is_compute] ? VK_IMAGE_LAYOUT_GENERAL : + res->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ? + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline); } /* always barrier on draw if this resource has either multiple image write binds or diff --git a/src/gallium/drivers/zink/zink_render_pass.c b/src/gallium/drivers/zink/zink_render_pass.c index 38ddab7187c..26c19f74788 100644 --- a/src/gallium/drivers/zink/zink_render_pass.c +++ b/src/gallium/drivers/zink/zink_render_pass.c @@ -62,6 +62,8 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state) int num_attachments = state->num_cbufs; if (state->have_zsbuf) { struct zink_rt_attrib *rt = state->rts + state->num_cbufs; + bool has_clear = rt->clear_color || rt->clear_stencil; + VkImageLayout layout = rt->needs_write || has_clear ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; attachments[num_attachments].flags = 0; attachments[num_attachments].format = rt->format; attachments[num_attachments].samples = rt->samples; @@ -69,17 +71,18 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state) attachments[num_attachments].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[num_attachments].stencilLoadOp = rt->clear_stencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; attachments[num_attachments].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[num_attachments].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachments[num_attachments].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[num_attachments].initialLayout = layout; + attachments[num_attachments].finalLayout = layout; dep_pipeline |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dep_pipeline |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + if (layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; if (attachments[num_attachments].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD || attachments[num_attachments].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD) dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; zs_ref.attachment = num_attachments++; - zs_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + zs_ref.layout = layout; } VkSubpassDependency deps[] = { @@ -138,3 +141,28 @@ zink_destroy_render_pass(struct zink_screen *screen, vkDestroyRenderPass(screen->dev, rp->render_pass, NULL); FREE(rp); } + +VkImageLayout +zink_render_pass_attachment_get_barrier_info(const struct zink_render_pass *rp, unsigned idx, + VkPipelineStageFlags *pipeline, VkAccessFlags *access) +{ + *access = 0; + assert(idx < rp->state.num_rts); + const struct zink_rt_attrib *rt = &rp->state.rts[idx]; + if (idx < rp->state.num_cbufs) { + *pipeline = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + *access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + if (!rt->clear_color && (!rp->state.swapchain_init || !rt->swapchain)) + *access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + + assert(rp->state.have_zsbuf); + *pipeline = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + if (!rp->state.rts[idx].clear_color && !rp->state.rts[idx].clear_stencil) + *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + if (!rp->state.rts[idx].clear_color && !rp->state.rts[idx].clear_stencil && !rp->state.rts[idx].needs_write) + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; +} diff --git a/src/gallium/drivers/zink/zink_render_pass.h b/src/gallium/drivers/zink/zink_render_pass.h index 2525695404c..8b4441e5fe3 100644 --- a/src/gallium/drivers/zink/zink_render_pass.h +++ b/src/gallium/drivers/zink/zink_render_pass.h @@ -36,7 +36,10 @@ struct zink_rt_attrib { VkSampleCountFlagBits samples; bool clear_color; bool clear_stencil; - bool swapchain; + union { + bool swapchain; + bool needs_write; + }; }; struct zink_render_pass_state { @@ -61,4 +64,6 @@ void zink_destroy_render_pass(struct zink_screen *screen, struct zink_render_pass *rp); +VkImageLayout +zink_render_pass_attachment_get_barrier_info(const struct zink_render_pass *rp, unsigned idx, VkPipelineStageFlags *pipeline, VkAccessFlags *access); #endif diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index 084f244f022..246669b2725 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -389,6 +389,7 @@ zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso) { struct zink_context *ctx = zink_context(pctx); + bool prev_zwrite = ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false; ctx->dsa_state = cso; if (cso) { @@ -398,6 +399,10 @@ zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso) state->dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state; } } + if (prev_zwrite != (ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false)) { + ctx->rp_changed = true; + zink_batch_no_rp(ctx); + } } static void