mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-02 03:00:24 +01:00
tc: also inline depth resolves
this catches the case where an app resolves both color and depth buffers
previously the inlining would only catch the first color buffer, then the depth
resolve which followed would cause the whole of rp tracking to desync and
explode, as seen in Transport Fever 2
Fixes: 8933b3ed39 ("tc: add resolve resource to rp info")
Acked-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36521>
This commit is contained in:
parent
71c4f13660
commit
a71b6ac41a
4 changed files with 71 additions and 54 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue