diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c index 497ee5d652a..3b8227bb170 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.c +++ b/src/gallium/auxiliary/util/u_threaded_context.c @@ -232,21 +232,23 @@ tc_batch_increment_renderpass_info(struct threaded_context *tc, unsigned batch_i /* copy the previous data in its entirety: this is still the same renderpass */ if (tc->renderpass_info_recording) { tc_info[batch->renderpass_info_idx].info.data = tc->renderpass_info_recording->data; - tc_info[batch->renderpass_info_idx].info.resolve = tc->renderpass_info_recording->resolve; - tc->renderpass_info_recording->resolve = NULL; + memcpy(tc_info[batch->renderpass_info_idx].info.resolve, tc->renderpass_info_recording->resolve, sizeof(tc->renderpass_info_recording->resolve)); + memset(tc->renderpass_info_recording->resolve, 0, sizeof(tc->renderpass_info_recording->resolve)); tc_batch_rp_info(tc->renderpass_info_recording)->next = &tc_info[batch->renderpass_info_idx]; tc_info[batch->renderpass_info_idx].prev = tc_batch_rp_info(tc->renderpass_info_recording); /* guard against deadlock scenario */ assert(&tc_batch_rp_info(tc->renderpass_info_recording)->next->info != tc->renderpass_info_recording); } else { tc_info[batch->renderpass_info_idx].info.data = 0; - pipe_resource_reference(&tc_info[batch->renderpass_info_idx].info.resolve, NULL); + for (unsigned i = 0; i < ARRAY_SIZE(tc_info[batch->renderpass_info_idx].info.resolve); i++) + pipe_resource_reference(&tc_info[batch->renderpass_info_idx].info.resolve[i], NULL); tc_info[batch->renderpass_info_idx].prev = NULL; } } else { /* selectively copy: only the CSO metadata is copied, and a new framebuffer state will be added later */ tc_info[batch->renderpass_info_idx].info.data = 0; - pipe_resource_reference(&tc_info[batch->renderpass_info_idx].info.resolve, NULL); + for (unsigned i = 0; i < ARRAY_SIZE(tc_info[batch->renderpass_info_idx].info.resolve); i++) + pipe_resource_reference(&tc_info[batch->renderpass_info_idx].info.resolve[i], NULL); if (tc->renderpass_info_recording) { tc_info[batch->renderpass_info_idx].info.data16[2] = tc->renderpass_info_recording->data16[2]; tc_batch_rp_info(tc->renderpass_info_recording)->next = NULL; @@ -1513,7 +1515,8 @@ tc_set_framebuffer_state(struct pipe_context *_pipe, tc->batch_slots[tc->next].renderpass_info_idx = 0; tc->renderpass_info_recording->has_resolve = false; } - assert(!tc->renderpass_info_recording->resolve); + assert(!tc->renderpass_info_recording->resolve[0] && + !tc->renderpass_info_recording->resolve[1]); tc->seen_fb_state = true; } /* ref for cmd */ @@ -4579,11 +4582,11 @@ tc_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info) info->src.box.width != info->dst.box.width || info->src.box.height != info->dst.box.height || info->src.box.depth != info->dst.box.depth || + !tc->in_renderpass || #if TC_RESOLVE_STRICT info->src.box.width != tc->fb_width || info->src.box.height != tc->fb_height || #endif - tc->renderpass_info_recording->ended || (info->dst.resource->array_size && info->dst.resource->array_size != tc->fb_layers) || (!tc->renderpass_info_recording->has_draw && !tc->renderpass_info_recording->cbuf_clear && !tc->renderpass_info_recording->zsbuf_clear)) { if (tc->options.parse_renderpass_info && tc->in_renderpass) @@ -4592,7 +4595,9 @@ tc_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info) return; } - struct pipe_resource *src = tc->nr_cbufs ? tc->fb_resources[0] : tc->fb_resources[PIPE_MAX_COLOR_BUFS]; + bool is_depth = util_format_is_depth_or_stencil(info->src.format); + struct pipe_resource *src = !is_depth ? tc->fb_resources[0] : tc->fb_resources[PIPE_MAX_COLOR_BUFS]; + bool is_resolve = false; if (tc->fb_resolve == info->dst.resource) { #if TC_DEBUG >= 3 tc_printf("WSI RESOLVE MERGE"); @@ -4600,24 +4605,29 @@ tc_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info) /* optimize out this blit entirely */ tc->renderpass_info_recording->has_resolve = true; tc->renderpass_info_recording->ended = true; - tc_signal_renderpass_info_ready(tc); - } else if (src == info->src.resource && - (!tc->renderpass_info_recording->has_resolve || - tc->renderpass_info_recording->resolve == info->dst.resource)) { + is_resolve = true; + } else if (src == info->src.resource) { #if TC_DEBUG >= 3 tc_printf("RESOLVE MERGE"); #endif - /* can only optimize out the first resolve */ - tc->renderpass_info_recording->has_resolve = true; - pipe_resource_reference(&tc->renderpass_info_recording->resolve, info->dst.resource); + /* only optimizing out one depth and one color resolve */ + assert(!tc->renderpass_info_recording->resolve[is_depth] || tc->renderpass_info_recording->resolve[is_depth] == info->dst.resource); + pipe_resource_reference(&tc->renderpass_info_recording->resolve[is_depth], info->dst.resource); tc_set_resource_batch_usage(tc, info->dst.resource); + if (tc->renderpass_info_recording->has_resolve) { + assert(tc->renderpass_info_recording->ended); + /* driver will already expect a rp-terminating resolve, don't send a second one */ + return; + } + tc->renderpass_info_recording->has_resolve = true; tc->renderpass_info_recording->ended = true; - tc_signal_renderpass_info_ready(tc); + is_resolve = true; } else if (tc->in_renderpass) { tc_check_fb_access(tc, info->src.resource, info->dst.resource); } struct tc_blit_call *blit = tc_blit_enqueue(tc, info); - blit->base.call_id = TC_CALL_resolve; + if (is_resolve) + blit->base.call_id = TC_CALL_resolve; } struct tc_generate_mipmap { diff --git a/src/gallium/auxiliary/util/u_threaded_context.h b/src/gallium/auxiliary/util/u_threaded_context.h index 932967a85f7..4cad69edea4 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.h +++ b/src/gallium/auxiliary/util/u_threaded_context.h @@ -476,7 +476,7 @@ struct tc_renderpass_info { uint8_t data8[8]; }; /* only valid if has_resolve is true and the resolve member of pipe_framebuffer_state is NULL */ - struct pipe_resource *resolve; + struct pipe_resource *resolve[2]; //[color, depth] }; static inline bool diff --git a/src/gallium/drivers/zink/zink_blit.c b/src/gallium/drivers/zink/zink_blit.c index 7c519ab3942..b2970d4c9a9 100644 --- a/src/gallium/drivers/zink/zink_blit.c +++ b/src/gallium/drivers/zink/zink_blit.c @@ -348,9 +348,10 @@ zink_blit(struct pipe_context *pctx, bool needs_present_readback = false; if (ctx->awaiting_resolve && ctx->in_rp && ctx->dynamic_fb.tc_info.has_resolve) { + bool is_depth = util_format_is_depth_or_stencil(info->src.format); struct pipe_resource *resolve = ctx->fb_state.resolve; if (!resolve) - resolve = ctx->dynamic_fb.tc_info.resolve; + resolve = ctx->dynamic_fb.tc_info.resolve[is_depth]; if (resolve == info->dst.resource) { zink_batch_no_rp_safe(ctx); ctx->awaiting_resolve = false; diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 6331e9a1fe8..6bc248a84a7 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -71,8 +71,7 @@ update_tc_info(struct zink_context *ctx) if (ctx->track_renderpasses) { const struct tc_renderpass_info *info = threaded_context_get_renderpass_info(ctx->tc); ctx->rp_changed |= ctx->dynamic_fb.tc_info.data != info->data; - ctx->dynamic_fb.tc_info.data = info->data; - ctx->dynamic_fb.tc_info.resolve = info->resolve; + ctx->dynamic_fb.tc_info = *info; ctx->awaiting_resolve = ctx->dynamic_fb.tc_info.has_resolve; } else { struct tc_renderpass_info info = ctx->dynamic_fb.tc_info; @@ -3163,41 +3162,48 @@ begin_rendering(struct zink_context *ctx, bool check_msaa_expand) } } if (use_tc_info && ctx->dynamic_fb.tc_info.has_resolve) { - struct zink_resource *res = zink_resource(ctx->fb_state.resolve); - if (!res) - res = zink_resource(ctx->dynamic_fb.tc_info.resolve); - assert(res); - zink_batch_resource_usage_set(ctx->bs, res, true, false); - bool is_depth = util_format_is_depth_or_stencil(res->base.b.format); - enum pipe_format format = res->base.b.format; - if (!ctx->fb_state.resolve) - format = is_depth ? ctx->fb_state.zsbuf.format : ctx->fb_state.cbufs[0].format; - if (zink_format_needs_mutable(res->base.b.format, format)) - /* mutable not set by default */ - zink_resource_object_init_mutable(ctx, res); - struct pipe_surface tmpl = { - .format = format, - .texture = &res->base.b + struct zink_resource *resolves[3] = { + zink_resource(ctx->fb_state.resolve), + zink_resource(ctx->dynamic_fb.tc_info.resolve[1]), }; - if (zink_is_swapchain(res)) { - if (!zink_kopper_acquire(ctx, res, UINT64_MAX)) - return 0; - } - VkImageViewCreateInfo ivci = create_ivci(screen, res, &tmpl, ctx->dynamic_fb.info.layerCount > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D); - struct zink_surface *surf = zink_get_surface(ctx, &tmpl, &ivci); - VkImageLayout layout = is_depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - if (screen->driver_workarounds.general_layout) - layout = VK_IMAGE_LAYOUT_GENERAL; - unsigned idx = util_format_is_depth_or_stencil(res->base.b.format) ? PIPE_MAX_COLOR_BUFS : 0; - screen->image_barrier(ctx, res, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - res->obj->unordered_read = res->obj->unordered_write = false; - ctx->dynamic_fb.attachments[idx].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; - ctx->dynamic_fb.attachments[idx].resolveImageLayout = res->layout; - ctx->dynamic_fb.attachments[idx].resolveImageView = surf->image_view; - if (idx == PIPE_MAX_COLOR_BUFS) { - ctx->dynamic_fb.attachments[idx + 1].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; - ctx->dynamic_fb.attachments[idx + 1].resolveImageLayout = res->layout; - ctx->dynamic_fb.attachments[idx + 1].resolveImageView = surf->image_view; + if (!resolves[0]) + resolves[0] = zink_resource(ctx->dynamic_fb.tc_info.resolve[0]); + for (unsigned i = 0; i < ARRAY_SIZE(resolves); i++) { + struct zink_resource *res = resolves[i]; + if (!res) + continue; + zink_batch_resource_usage_set(ctx->bs, res, true, false); + bool is_depth = util_format_is_depth_or_stencil(res->base.b.format); + enum pipe_format format = res->base.b.format; + if (!ctx->fb_state.resolve) + format = is_depth ? ctx->fb_state.zsbuf.format : ctx->fb_state.cbufs[0].format; + if (zink_format_needs_mutable(res->base.b.format, format)) + /* mutable not set by default */ + zink_resource_object_init_mutable(ctx, res); + struct pipe_surface tmpl = { + .format = format, + .texture = &res->base.b + }; + if (zink_is_swapchain(res)) { + if (!zink_kopper_acquire(ctx, res, UINT64_MAX)) + return 0; + } + VkImageViewCreateInfo ivci = create_ivci(screen, res, &tmpl, ctx->dynamic_fb.info.layerCount > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D); + struct zink_surface *surf = zink_get_surface(ctx, &tmpl, &ivci); + VkImageLayout layout = is_depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + if (screen->driver_workarounds.general_layout) + layout = VK_IMAGE_LAYOUT_GENERAL; + unsigned idx = is_depth ? PIPE_MAX_COLOR_BUFS : 0; + screen->image_barrier(ctx, res, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + res->obj->unordered_read = res->obj->unordered_write = false; + ctx->dynamic_fb.attachments[idx].resolveMode = is_depth ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_AVERAGE_BIT; + ctx->dynamic_fb.attachments[idx].resolveImageLayout = res->layout; + ctx->dynamic_fb.attachments[idx].resolveImageView = surf->image_view; + if (idx == PIPE_MAX_COLOR_BUFS) { + ctx->dynamic_fb.attachments[idx + 1].resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; + ctx->dynamic_fb.attachments[idx + 1].resolveImageLayout = res->layout; + ctx->dynamic_fb.attachments[idx + 1].resolveImageView = surf->image_view; + } } } ctx->zsbuf_unused = !zsbuf_used;