zink: rewrite clears on fb bind if only the format has changed

in some apps (hl2), there's a weird sequence like:
* bind attachment with srgb view
* clear
* bind attachment with base format
* draw

rewriting the clear color like this avoids unnecessarily triggering
a renderpass

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18627>
This commit is contained in:
Mike Blumenkrantz
2022-09-01 09:16:01 -04:00
committed by Marge Bot
parent 13a19ad90c
commit 95ea41dff9
3 changed files with 43 additions and 3 deletions
+24
View File
@@ -784,3 +784,27 @@ zink_fb_clears_apply_region(struct zink_context *ctx, struct pipe_resource *pres
}
}
}
void
zink_fb_clear_rewrite(struct zink_context *ctx, unsigned idx, enum pipe_format before, enum pipe_format after)
{
/* if the values for the clear color are incompatible, they must be rewritten;
* this occurs if:
* - the formats' srgb-ness does not match
* - the formats' signedness does not match
*/
const struct util_format_description *bdesc = util_format_description(before);
const struct util_format_description *adesc = util_format_description(after);
bool bsigned = bdesc->channel[util_format_get_first_non_void_channel(before)].type == UTIL_FORMAT_TYPE_SIGNED;
bool asigned = adesc->channel[util_format_get_first_non_void_channel(after)].type == UTIL_FORMAT_TYPE_SIGNED;
if (util_format_is_srgb(before) == util_format_is_srgb(after) &&
bsigned == asigned)
return;
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[idx];
for (int j = 0; j < zink_fb_clear_count(fb_clear); j++) {
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, j);
uint32_t data[4];
util_format_pack_rgba(before, data, clear->color.ui, 1);
util_format_unpack_rgba(after, clear->color.ui, data, 1);
}
}
+3
View File
@@ -110,3 +110,6 @@ zink_fb_clears_apply_or_discard(struct zink_context *ctx, struct pipe_resource *
void
zink_fb_clears_apply_region(struct zink_context *ctx, struct pipe_resource *pres, struct u_rect region);
void
zink_fb_clear_rewrite(struct zink_context *ctx, unsigned idx, enum pipe_format before, enum pipe_format after);
+16 -3
View File
@@ -2853,9 +2853,22 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
bool flush_clears = ctx->clears_enabled &&
(ctx->dynamic_fb.info.layerCount != layers ||
state->width != w || state->height != h);
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (i >= state->nr_cbufs || ctx->fb_state.cbufs[i] != state->cbufs[i])
flush_clears |= zink_fb_clear_enabled(ctx, i);
if (ctx->clears_enabled && !flush_clears) {
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (i >= state->nr_cbufs || !ctx->fb_state.cbufs[i] || !state->cbufs[i])
flush_clears |= zink_fb_clear_enabled(ctx, i);
else if (zink_fb_clear_enabled(ctx, i) && ctx->fb_state.cbufs[i] != state->cbufs[i]) {
struct zink_surface *a = zink_csurface(ctx->fb_state.cbufs[i]);
struct zink_surface *b = zink_csurface(state->cbufs[i]);
if (a == b)
continue;
if (memcmp(&a->base.u.tex, &b->base.u.tex, sizeof(b->base.u.tex)) ||
a->base.texture != b->base.texture)
flush_clears = true;
else if (a->base.format != b->base.format)
zink_fb_clear_rewrite(ctx, i, a->base.format, b->base.format);
}
}
}
if (ctx->fb_state.zsbuf != state->zsbuf)
flush_clears |= zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS);