From e1aac4f7e00dce017b7ebaa9600811efbae74a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Mon, 2 Feb 2026 11:39:26 -0300 Subject: [PATCH] vc4: fail VS compilation on divergent loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VC4 hardware doesn't have a dispatch mask for the VS, so divergent loops can have undefined/garbage contents in some execution channels, potentially causing infinite loops and GPU hangs. Fail shader linking instead of hanging the GPU when a divergent loop is detected in a vertex shader. Reviewed-by: Iago Toral Quiroga Signed-off-by: MaĆ­ra Canal Part-of: --- src/gallium/drivers/vc4/vc4_program.c | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index 8eaf96a296b..7c6f6bbb0a5 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -2465,6 +2465,17 @@ vc4_shader_precompile(struct vc4_context *vc4, } } +static bool +vc4_check_divergent_loops(nir_shader *s) +{ + nir_foreach_block(block, nir_shader_get_entrypoint(s)) { + nir_loop *loop = nir_block_get_following_loop(block); + if (loop && nir_loop_is_divergent(loop)) + return true; + } + return false; +} + static void * vc4_shader_state_create(struct pipe_context *pctx, const struct pipe_shader_state *cso) @@ -2514,6 +2525,26 @@ vc4_shader_state_create(struct pipe_context *pctx, /* Garbage collect dead instructions */ nir_sweep(s); + /* VC4 hardware doesn't have a dispatch mask for the VS. This means + * that, if we submit a divergent loop to the hardware, some execution + * channels can have undefined/garbage contents and cause infinite + * loops and GPU hangs. + * + * Instead of potentially hanging the GPU, refuse shader linking. + */ + if (s->info.stage == MESA_SHADER_VERTEX) { + nir_divergence_analysis(s); + + if (vc4_check_divergent_loops(s) && cso->report_compile_error) { + ((struct pipe_shader_state *)cso)->error_message = + strdup("Non-uniform loops are unsupported " + "in the vertex shader."); + ralloc_free(s); + free(so); + return NULL; + } + } + so->base.type = PIPE_SHADER_IR_NIR; so->base.ir.nir = s;