r300: skip draws instead of using a dummy vertex shader

When we fail to compile some vertex shader, we currently use a very
simple dummy one, setting gl_Position to (0,0,0,1), effectively
rendering nothing. Unfortunately, the dummy vertex shader leads to
hangs with RV370 in some rare circumstances. Instead of trying to
fix the shader, just skip the draws altogether when the compilation
fails.

Signed-off-by: Pavel Ondračka <pavel.ondracka@gmail.com>
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5870
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16387>
This commit is contained in:
Pavel Ondračka 2022-05-08 18:04:37 +02:00 committed by Marge Bot
parent 23cde71bb9
commit c6aa639ba9
3 changed files with 15 additions and 39 deletions

View File

@ -40,6 +40,7 @@
#include "r300_screen_buffer.h"
#include "r300_emit.h"
#include "r300_reg.h"
#include "r300_vs.h"
#include <limits.h>
@ -815,6 +816,10 @@ static void r300_draw_vbo(struct pipe_context* pipe,
r300_update_derived_state(r300);
/* Skip draw if we failed to compile the vertex shader. */
if (r300_vs(r300)->shader->dummy)
return;
/* Draw. */
if (info.index_size) {
unsigned max_count = r300_max_vertex_count(r300);

View File

@ -1074,7 +1074,8 @@ static void r300_pick_vertex_shader(struct r300_context *r300)
vs->first = vs->shader = CALLOC_STRUCT(r300_vertex_shader_code);
vs->first->wpos = wpos;
r300_translate_vertex_shader(r300, vs);
r300_mark_atom_dirty(r300, &r300->rs_block_state);
if (!vs->first->dummy)
r300_mark_atom_dirty(r300, &r300->rs_block_state);
return;
}
/* Pick the vertex shader based on whether we need wpos */
@ -1091,7 +1092,8 @@ static void r300_pick_vertex_shader(struct r300_context *r300)
vs->shader->wpos = wpos;
r300_translate_vertex_shader(r300, vs);
}
r300_mark_atom_dirty(r300, &r300->rs_block_state);
if (!vs->first->dummy)
r300_mark_atom_dirty(r300, &r300->rs_block_state);
}
}
}

View File

@ -178,30 +178,6 @@ void r300_init_vs_outputs(struct r300_context *r300,
r300_shader_read_vs_outputs(r300, &vs->shader->info, &vs->shader->outputs);
}
static void r300_dummy_vertex_shader(
struct r300_context* r300,
struct r300_vertex_shader* vs)
{
struct ureg_program *ureg;
struct ureg_dst dst;
struct ureg_src imm;
/* Make a simple vertex shader which outputs (0, 0, 0, 1),
* effectively rendering nothing. */
ureg = ureg_create(PIPE_SHADER_VERTEX);
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
imm = ureg_imm4f(ureg, 0, 0, 0, 1);
ureg_MOV(ureg, dst, imm);
ureg_END(ureg);
vs->state.tokens = tgsi_dup_tokens(ureg_finalize(ureg));
ureg_destroy(ureg);
vs->shader->dummy = TRUE;
r300_translate_vertex_shader(r300, vs);
}
void r300_translate_vertex_shader(struct r300_context *r300,
struct r300_vertex_shader *shader)
{
@ -219,8 +195,7 @@ void r300_translate_vertex_shader(struct r300_context *r300,
DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0;
compiler.code = &vs->code;
compiler.UserData = vs;
if (!vs->dummy)
compiler.Base.debug = &r300->debug;
compiler.Base.debug = &r300->debug;
compiler.Base.is_r500 = r300->screen->caps.is_r500;
compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT);
compiler.Base.has_half_swizzles = FALSE;
@ -245,8 +220,8 @@ void r300_translate_vertex_shader(struct r300_context *r300,
if (ttr.error) {
fprintf(stderr, "r300 VP: Cannot translate a shader. "
"Using a dummy shader instead.\n");
r300_dummy_vertex_shader(r300, shader);
"Corresponding draws will be skipped.\n");
vs->dummy = TRUE;
return;
}
@ -264,17 +239,11 @@ void r300_translate_vertex_shader(struct r300_context *r300,
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);
if (compiler.Base.Error) {
fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader"
" instead.\n", compiler.Base.ErrorMsg);
if (vs->dummy) {
fprintf(stderr, "r300 VP: Cannot compile the dummy shader! "
"Giving up...\n");
abort();
}
fprintf(stderr, "r300 VP: Compiler error:\n%sCorresponding draws will be"
" skipped.\n", compiler.Base.ErrorMsg);
rc_destroy(&compiler.Base);
r300_dummy_vertex_shader(r300, shader);
vs->dummy = TRUE;
return;
}