freedreno/a6xx: Don't disable LRZ for invalid channels

Similar idea to commit ("c9db71c8ba1 turnip: Don't disable LRZ for color
write mask channels beyond the format's"), but different implementation.
If the blend state masks writes to a color channel that doesn't exist,
that doesn't mean we need to disable LRZ write.  In particular, this
scenario will come up with z-prepasses (doh!)

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19710>
This commit is contained in:
Rob Clark 2022-11-13 08:35:54 -08:00 committed by Marge Bot
parent 4e9d913f81
commit 0132c22de7
5 changed files with 35 additions and 15 deletions

View file

@ -167,27 +167,16 @@ fd6_blend_state_create(struct pipe_context *pctx,
so->use_dual_src_blend =
cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0);
STATIC_ASSERT((4 * PIPE_MAX_COLOR_BUFS) == (8 * sizeof(so->all_mrt_write_mask)));
so->all_mrt_write_mask = 0;
unsigned nr = cso->independent_blend_enable ? cso->max_rt : 0;
for (unsigned i = 0; i <= nr; i++) {
const struct pipe_rt_blend_state *rt = &cso->rt[i];
so->reads_dest |= rt->blend_enable;
/* From the PoV of LRZ, having masked color channels is
* the same as having blend enabled, in that the draw will
* care about the fragments from an earlier draw.
*
* NOTE we actually don't care about masked color channels
* that don't actually exist in the render target, but we
* don't know the render target format here to determine
* that. It is probably not worth worrying about, but if
* we find a game/benchmark that goes out of it's way to
* mask off non-existent channels, we should fixup the
* pipe_blend_state to give us more info.
*/
if (rt->blend_enable || (rt->colormask != 0xf)) {
so->reads_dest = true;
}
so->all_mrt_write_mask |= rt->colormask << (4 * i);
}
util_dynarray_init(&so->variants, so);

View file

@ -51,6 +51,7 @@ struct fd6_blend_stateobj {
struct fd_context *ctx;
bool reads_dest;
uint32_t all_mrt_write_mask;
struct util_dynarray variants;
};

View file

@ -433,6 +433,14 @@ compute_lrz_state(struct fd6_emit *emit) assert_dt
lrz.write = false;
}
/* Unwritten channels *that actually exist* are a form of blending
* reading the dest from the PoV of LRZ, but the valid dst channels
* isn't known when blend CSO is constructed so we need to handle
* that here.
*/
if (ctx->all_mrt_channel_mask & ~blend->all_mrt_write_mask)
lrz.write = false;
/* if we change depthfunc direction, bail out on using LRZ. The
* LRZ buffer encodes a min/max depth value per block, but if
* we switch from GT/GE <-> LT/LE, those values cannot be

View file

@ -399,8 +399,11 @@ struct fd_context {
struct pipe_stencil_ref stencil_ref dt;
unsigned sample_mask dt;
unsigned min_samples dt;
/* local context fb state, for when ctx->batch is null: */
struct pipe_framebuffer_state framebuffer dt;
uint32_t all_mrt_channel_mask dt;
struct pipe_poly_stipple stipple dt;
struct pipe_viewport_state viewport[PIPE_MAX_VIEWPORTS] dt;
struct pipe_scissor_state viewport_scissor[PIPE_MAX_VIEWPORTS] dt;

View file

@ -289,6 +289,25 @@ fd_set_framebuffer_state(struct pipe_context *pctx,
util_copy_framebuffer_state(cso, framebuffer);
STATIC_ASSERT((4 * PIPE_MAX_COLOR_BUFS) == (8 * sizeof(ctx->all_mrt_channel_mask)));
ctx->all_mrt_channel_mask = 0;
/* Generate a bitmask of all valid channels for all MRTs. Blend
* state with unwritten channels essentially acts as blend enabled,
* which disables LRZ write. But only if the cbuf *has* the masked
* channels, which is not known at the time the blend state is
* created.
*/
for (unsigned i = 0; i < framebuffer->nr_cbufs; i++) {
if (!framebuffer->cbufs[i])
continue;
enum pipe_format format = framebuffer->cbufs[i]->format;
unsigned nr = util_format_get_nr_components(format);
ctx->all_mrt_channel_mask |= BITFIELD_MASK(nr) << (4 * i);
}
cso->samples = util_framebuffer_get_num_samples(cso);
if (ctx->screen->reorder) {