gallium/u_blitter: add a new fs_color_clear variant

The referenced commit switched from a passthrough shader
to fs_clear_color[write_all_cbufs=0]. It shouldn't matter since
the shader isn't supposed to be executed - it's only setup to get
the first color output active.

On some chips (gfx8) it seems to cause issues (hangs or page fault)
for some piglit tests, eg:
  framebuffer-blit-levels draw stencil

To fix this, introduce a 3rd variant, where a constant buffer isn't
required and instead the color is hardcoded in the shader.

Fixes: ca09c173f6 ("gallium/u_blitter: remove UTIL_BLITTER_ATTRIB_COLOR, use a constant buffer")
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40486>
This commit is contained in:
Pierre-Eric Pelloux-Prayer 2026-03-17 17:00:22 +01:00 committed by Marge Bot
parent be65d69b02
commit 2ff9fa8b72
3 changed files with 37 additions and 17 deletions

View file

@ -57,6 +57,13 @@
#define NUM_RESOLVE_FRAG_SHADERS 5 /* MSAA 2x, 4x, 8x, 16x, 32x */
#define GET_MSAA_RESOLVE_FS_IDX(nr_samples) (util_logbase2(nr_samples)-1)
enum blitter_fs_clear_color {
BLITTER_FS_CLEAR_COL_ALL_CBUF = 0,
BLITTER_FS_CLEAR_COL_ONE_CBUF,
BLITTER_FS_CLEAR_COL_ONE_CBUF_USE_CONST_BUF,
BLITTER_FS_CLEAR_COL_NUM
};
struct blitter_context_priv
{
struct blitter_context base;
@ -75,7 +82,7 @@ struct blitter_context_priv
/* Fragment shaders. */
void *fs_empty;
void *fs_clear_color[2];
void *fs_clear_color[BLITTER_FS_CLEAR_COL_NUM];
/* FS which outputs a color from a texture where
* the 1st index indicates the texture type / destination type,
@ -415,17 +422,21 @@ static void bind_fs_empty(struct blitter_context_priv *ctx)
}
static void bind_fs_clear_color(struct blitter_context_priv *ctx,
bool write_all_cbufs)
enum blitter_fs_clear_color fs)
{
struct pipe_context *pipe = ctx->base.pipe;
if (!ctx->fs_clear_color[write_all_cbufs]) {
if (!ctx->fs_clear_color[fs]) {
assert(!ctx->cached_all_shaders);
ctx->fs_clear_color[write_all_cbufs] =
util_make_fs_clear_color(pipe, write_all_cbufs);
ctx->fs_clear_color[fs] =
util_make_fs_clear_color(
pipe,
fs == BLITTER_FS_CLEAR_COL_ALL_CBUF,
fs == BLITTER_FS_CLEAR_COL_ALL_CBUF ||
fs == BLITTER_FS_CLEAR_COL_ONE_CBUF_USE_CONST_BUF);
}
ctx->bind_fs_state(pipe, ctx->fs_clear_color[write_all_cbufs]);
ctx->bind_fs_state(pipe, ctx->fs_clear_color[fs]);
}
void util_blitter_destroy(struct blitter_context *blitter)
@ -1351,8 +1362,12 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter)
ctx->fs_empty = util_make_empty_fragment_shader(pipe);
ctx->fs_clear_color[0] = util_make_fs_clear_color(pipe, false);
ctx->fs_clear_color[1] = util_make_fs_clear_color(pipe, true);
ctx->fs_clear_color[BLITTER_FS_CLEAR_COL_ONE_CBUF] =
util_make_fs_clear_color(pipe, false, false);
ctx->fs_clear_color[BLITTER_FS_CLEAR_COL_ONE_CBUF_USE_CONST_BUF] =
util_make_fs_clear_color(pipe, false, true);
ctx->fs_clear_color[BLITTER_FS_CLEAR_COL_ALL_CBUF] =
util_make_fs_clear_color(pipe, true, true);
ctx->cached_all_shaders = true;
}
@ -1581,7 +1596,7 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
};
pipe->set_constant_buffer(pipe, MESA_SHADER_FRAGMENT, blitter->cb_slot,
&cb);
bind_fs_clear_color(ctx, true);
bind_fs_clear_color(ctx, BLITTER_FS_CLEAR_COL_ALL_CBUF);
} else {
bind_fs_empty(ctx);
}
@ -2436,7 +2451,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
/* bind states */
pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
bind_fs_clear_color(ctx, false);
bind_fs_clear_color(ctx, BLITTER_FS_CLEAR_COL_ONE_CBUF_USE_CONST_BUF);
/* set a framebuffer state */
pipe_surface_size(dstsurf, &fb_state.width, &fb_state.height);
@ -2584,7 +2599,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
ctx->blend[0][0]);
pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
if (cbsurf)
bind_fs_clear_color(ctx, false);
bind_fs_clear_color(ctx, BLITTER_FS_CLEAR_COL_ONE_CBUF);
else
bind_fs_empty(ctx);
@ -2638,7 +2653,7 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter,
/* bind states */
pipe->bind_blend_state(pipe, custom_blend);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
bind_fs_clear_color(ctx, false);
bind_fs_clear_color(ctx, BLITTER_FS_CLEAR_COL_ONE_CBUF);
pipe->set_sample_mask(pipe, sample_mask);
if (pipe->set_min_samples)
pipe->set_min_samples(pipe, 1);
@ -2699,7 +2714,7 @@ void util_blitter_custom_color(struct blitter_context *blitter,
pipe->bind_blend_state(pipe, custom_blend ? custom_blend
: ctx->blend[PIPE_MASK_RGBA][0]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
bind_fs_clear_color(ctx, false);
bind_fs_clear_color(ctx, BLITTER_FS_CLEAR_COL_ONE_CBUF);
/* set a framebuffer state */
pipe_surface_size(dstsurf, &fb_state.width, &fb_state.height);

View file

@ -1329,19 +1329,24 @@ util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src, bool has_txq
}
void *
util_make_fs_clear_color(struct pipe_context *pipe, bool write_all_cbufs)
util_make_fs_clear_color(struct pipe_context *pipe,
bool write_all_cbufs,
bool use_const_buf)
{
static const char text_templ[] =
"FRAG\n"
"PROPERTY FS_COLOR0_WRITES_ALL_CBUFS %u\n"
"DCL OUT[0], COLOR[0]\n"
"DCL CONST[0][0]\n"
"IMM[0] INT32 {0, 0, 0, 0}\n"
"MOV OUT[0], CONST[0][0]\n"
"MOV OUT[0], %s\n"
"END\n";
char text[1000];
snprintf(text, ARRAY_SIZE(text), text_templ, write_all_cbufs);
snprintf(text, ARRAY_SIZE(text), text_templ,
write_all_cbufs,
use_const_buf ? "CONST[0][0]" : "IMM[0]");
struct tgsi_token tokens[1000];
struct pipe_shader_state state = { 0 };

View file

@ -172,7 +172,7 @@ void *
util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src, bool has_txq);
void *
util_make_fs_clear_color(struct pipe_context *pipe, bool write_all_cbufs);
util_make_fs_clear_color(struct pipe_context *pipe, bool write_all_cbufs, bool use_const_buf);
#ifdef __cplusplus
}