panfrost: Fix NULL derefs in pan_cmdstream.c

Auditing nr_cbufs. Note we have to augment the blending logic a bit to
use the same 'no blend' case for missing RTs as we do for depth-only
passes.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9164>
This commit is contained in:
Alyssa Rosenzweig 2021-02-19 09:57:26 -05:00 committed by Marge Bot
parent 4f17852474
commit a124c47b9f
1 changed files with 46 additions and 38 deletions

View File

@ -245,15 +245,15 @@ static bool
panfrost_fs_required(
struct panfrost_shader_state *fs,
struct panfrost_blend_final *blend,
unsigned rt_count)
struct pipe_framebuffer_state *state)
{
/* If we generally have side effects */
if (fs->info.fs.sidefx)
return true;
/* If colour is written we need to execute */
for (unsigned i = 0; i < rt_count; ++i) {
if (!blend[i].no_colour)
for (unsigned i = 0; i < state->nr_cbufs; ++i) {
if (!blend[i].no_colour && state->cbufs[i])
return true;
}
@ -292,20 +292,21 @@ panfrost_emit_bifrost_blend(struct panfrost_batch *batch,
void *rts)
{
unsigned rt_count = batch->key.nr_cbufs;
if (rt_count == 0) {
/* Disable blending for depth-only */
pan_pack(rts, BLEND, cfg) {
cfg.enable = false;
cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OFF;
}
return;
}
const struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
struct panfrost_shader_state *fs = panfrost_get_shader_state(batch->ctx, PIPE_SHADER_FRAGMENT);
for (unsigned i = 0; i < rt_count; ++i) {
/* Always have at least one render target for depth-only passes */
for (unsigned i = 0; i < MAX2(rt_count, 1); ++i) {
/* Disable blending for unbacked render targets */
if (rt_count == 0 || !batch->key.cbufs[i]) {
pan_pack(rts, BLEND, cfg) {
cfg.enable = false;
cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OFF;
}
continue;
}
pan_pack(rts + i * MALI_BLEND_LENGTH, BLEND, cfg) {
if (blend[i].no_colour) {
cfg.enable = false;
@ -374,21 +375,23 @@ panfrost_emit_midgard_blend(struct panfrost_batch *batch,
{
unsigned rt_count = batch->key.nr_cbufs;
if (rt_count == 0) {
/* Disable blending for depth-only */
pan_pack(rts, BLEND, cfg) {
cfg.midgard.equation.color_mask = 0xf;
cfg.midgard.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC;
cfg.midgard.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC;
cfg.midgard.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO;
cfg.midgard.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC;
cfg.midgard.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC;
cfg.midgard.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO;
}
return;
}
/* Always have at least one render target for depth-only passes */
for (unsigned i = 0; i < MAX2(rt_count, 1); ++i) {
/* Disable blending for unbacked render targets */
if (rt_count == 0 || !batch->key.cbufs[i]) {
pan_pack(rts, BLEND, cfg) {
cfg.midgard.equation.color_mask = 0xf;
cfg.midgard.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC;
cfg.midgard.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC;
cfg.midgard.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO;
cfg.midgard.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC;
cfg.midgard.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC;
cfg.midgard.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO;
}
continue;
}
for (unsigned i = 0; i < rt_count; ++i) {
pan_pack(rts + i * MALI_BLEND_LENGTH, BLEND, cfg) {
if (blend[i].no_colour) {
cfg.enable = false;
@ -421,7 +424,7 @@ panfrost_emit_blend(struct panfrost_batch *batch, void *rts,
panfrost_emit_midgard_blend(batch, blend, rts);
for (unsigned i = 0; i < batch->key.nr_cbufs; ++i) {
if (!blend[i].no_colour)
if (!blend[i].no_colour && batch->key.cbufs[i])
batch->draws |= (PIPE_CLEAR_COLOR0 << i);
}
}
@ -433,10 +436,9 @@ panfrost_prepare_bifrost_fs_state(struct panfrost_context *ctx,
{
const struct panfrost_device *dev = pan_device(ctx->base.screen);
struct panfrost_shader_state *fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
unsigned rt_count = ctx->pipe_framebuffer.nr_cbufs;
bool alpha_to_coverage = ctx->blend->base.alpha_to_coverage;
if (!panfrost_fs_required(fs, blend, rt_count)) {
if (!panfrost_fs_required(fs, blend, &ctx->pipe_framebuffer)) {
state->properties.uniform_buffer_count = 32;
state->properties.bifrost.shader_modifies_coverage = true;
state->properties.bifrost.allow_forward_pixel_to_kill = true;
@ -449,8 +451,10 @@ panfrost_prepare_bifrost_fs_state(struct panfrost_context *ctx,
bool no_blend = true;
for (unsigned i = 0; i < rt_count; ++i)
no_blend &= (!blend[i].load_dest | blend[i].no_colour);
for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) {
no_blend &= (!blend[i].load_dest || blend[i].no_colour)
|| (!ctx->pipe_framebuffer.cbufs[i]);
}
state->properties.bifrost.allow_forward_pixel_to_kill =
!fs->info.fs.writes_depth &&
@ -474,7 +478,7 @@ panfrost_prepare_midgard_fs_state(struct panfrost_context *ctx,
unsigned rt_count = ctx->pipe_framebuffer.nr_cbufs;
bool alpha_to_coverage = ctx->blend->base.alpha_to_coverage;
if (!panfrost_fs_required(fs, blend, rt_count)) {
if (!panfrost_fs_required(fs, blend, &ctx->pipe_framebuffer)) {
state->shader.shader = 0x1;
state->properties.midgard.work_register_count = 1;
state->properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION;
@ -668,9 +672,13 @@ panfrost_emit_frag_shader_meta(struct panfrost_batch *batch)
unsigned shader_offset = 0;
struct panfrost_bo *shader_bo = NULL;
for (unsigned c = 0; c < ctx->pipe_framebuffer.nr_cbufs; ++c)
blend[c] = panfrost_get_blend_for_context(ctx, c, &shader_bo,
&shader_offset);
for (unsigned c = 0; c < ctx->pipe_framebuffer.nr_cbufs; ++c) {
if (ctx->pipe_framebuffer.cbufs[c]) {
blend[c] = panfrost_get_blend_for_context(ctx, c,
&shader_bo, &shader_offset);
}
}
panfrost_emit_frag_shader(ctx, (struct mali_renderer_state_packed *) xfer.cpu, blend);
if (!(dev->quirks & MIDGARD_SFBD))
@ -979,7 +987,7 @@ panfrost_upload_rt_conversion_sysval(struct panfrost_batch *batch, unsigned rt,
struct panfrost_context *ctx = batch->ctx;
struct panfrost_device *dev = pan_device(ctx->base.screen);
if (rt < batch->key.nr_cbufs) {
if (rt < batch->key.nr_cbufs && batch->key.cbufs[rt]) {
enum pipe_format format = batch->key.cbufs[rt]->format;
uniform->u[0] = bifrost_get_blend_desc(dev, format, rt, 32) >> 32;
} else {