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:
committed by
Marge Bot
parent
13a19ad90c
commit
95ea41dff9
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user