From dbf9a4b072bb7e5cd558e79f639b5859f5dfb0a9 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 15 Apr 2021 18:25:54 -0400 Subject: [PATCH] panfrost: Don't allow FPK if a RT is missing A fragment shader that forgets to write to one of the bound render targets (in the presence of MRT) invalidates a core FPK invariant. Check for this and add it to the naughty list. I don't think this needs a backport since FPK isn't really used yet. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Boris Brezillon Part-of: --- src/gallium/drivers/panfrost/pan_cmdstream.c | 10 ++++++++-- src/panfrost/lib/pan_shader.c | 5 +++++ src/panfrost/util/pan_ir.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 36b4c5a8e47..2d7f0810142 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -448,11 +448,16 @@ panfrost_prepare_bifrost_fs_state(struct panfrost_context *ctx, fs->bo ? fs->bo->ptr.gpu : 0, state); + /* Track if any colour buffer is reused across draws, either + * from reading it directly, or from failing to write it */ bool blend_reads_dest = false; + unsigned rt_mask = 0; for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) { - blend_reads_dest |= (blend[i].load_dest && - ctx->pipe_framebuffer.cbufs[i]); + if (ctx->pipe_framebuffer.cbufs[i]) { + rt_mask |= (1 << i); + blend_reads_dest |= blend[i].load_dest; + } } state->properties.bifrost.allow_forward_pixel_to_kill = @@ -461,6 +466,7 @@ panfrost_prepare_bifrost_fs_state(struct panfrost_context *ctx, !fs->info.fs.writes_coverage && !fs->info.fs.can_discard && !fs->info.fs.outputs_read && + !(rt_mask & ~fs->info.outputs_written) && !alpha_to_coverage && !blend_reads_dest; } diff --git a/src/panfrost/lib/pan_shader.c b/src/panfrost/lib/pan_shader.c index 2f6e30f58a8..8a42e29bc9e 100644 --- a/src/panfrost/lib/pan_shader.c +++ b/src/panfrost/lib/pan_shader.c @@ -178,10 +178,15 @@ pan_shader_compile(const struct panfrost_device *dev, info->fs.writes_coverage = true; uint64_t outputs_read = s->info.outputs_read; + uint64_t outputs_written = s->info.outputs_written; + if (outputs_read & BITFIELD64_BIT(FRAG_RESULT_COLOR)) outputs_read |= BITFIELD64_BIT(FRAG_RESULT_DATA0); + if (outputs_written & BITFIELD64_BIT(FRAG_RESULT_COLOR)) + outputs_written |= BITFIELD64_BIT(FRAG_RESULT_DATA0); info->fs.outputs_read = outputs_read >> FRAG_RESULT_DATA0; + info->fs.outputs_written = outputs_written >> FRAG_RESULT_DATA0; /* EXT_shader_framebuffer_fetch requires per-sample */ info->fs.sample_shading = s->info.fs.uses_sample_shading || diff --git a/src/panfrost/util/pan_ir.h b/src/panfrost/util/pan_ir.h index aca6d7ba9cf..cf8e2577702 100644 --- a/src/panfrost/util/pan_ir.h +++ b/src/panfrost/util/pan_ir.h @@ -175,6 +175,7 @@ struct pan_shader_info { bool sample_shading; bool early_fragment_tests; BITSET_WORD outputs_read; + BITSET_WORD outputs_written; } fs; struct {