From 8a9cad6384c61670e96165ad8c5f6ade927c6fa0 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 17 Nov 2011 16:40:02 -0700 Subject: [PATCH] svga: use dummy shaders when translation fails Before, if shader translation failed for any reason we'd keep trying to translate the shader over and over again during state validation. The dummy fragment shader emits solid red so that might be visual clue that translation is failing. Reviewed-by: Jose Fonseca --- src/gallium/drivers/svga/svga_state_fs.c | 50 +++++++++++++++++++++++- src/gallium/drivers/svga/svga_state_vs.c | 49 ++++++++++++++++++++++- 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index c95d82fc00e..8503b03eed4 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -26,7 +26,9 @@ #include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" +#include "util/u_memory.h" #include "util/u_bitmask.h" +#include "tgsi/tgsi_ureg.h" #include "svga_context.h" #include "svga_state.h" @@ -66,6 +68,38 @@ static struct svga_shader_result *search_fs_key( struct svga_fragment_shader *fs } +/** + * If we fail to compile a fragment shader (because it uses too many + * registers, for example) we'll use a dummy/fallback shader that + * simply emits a constant color. + */ +static const struct tgsi_token * +get_dummy_fragment_shader(void) +{ + static const float red[4] = { 1.0, 0.0, 0.0, 0.0 }; + struct ureg_program *ureg; + const struct tgsi_token *tokens; + struct ureg_src src; + struct ureg_dst dst; + unsigned num_tokens; + + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!ureg) + return NULL; + + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + src = ureg_DECL_immediate(ureg, red, 4); + ureg_MOV(ureg, dst, src); + ureg_END(ureg); + + tokens = ureg_get_tokens(ureg, &num_tokens); + + ureg_destroy(ureg); + + return tokens; +} + + static enum pipe_error compile_fs( struct svga_context *svga, struct svga_fragment_shader *fs, const struct svga_fs_compile_key *key, @@ -76,8 +110,20 @@ static enum pipe_error compile_fs( struct svga_context *svga, result = svga_translate_fragment_program( fs, key ); if (result == NULL) { - ret = PIPE_ERROR; /* some problem during translation */ - goto fail; + /* some problem during translation, try the dummy shader */ + const struct tgsi_token *dummy = get_dummy_fragment_shader(); + if (!dummy) { + ret = PIPE_ERROR_OUT_OF_MEMORY; + goto fail; + } + debug_printf("Failed to compile fragment shader, using dummy shader instead.\n"); + FREE((void *) fs->base.tokens); + fs->base.tokens = dummy; + result = svga_translate_fragment_program(fs, key); + if (result == NULL) { + ret = PIPE_ERROR; + goto fail; + } } result->id = util_bitmask_add(svga->fs_bm); diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c index b82e68556e4..3cb0cdb9697 100644 --- a/src/gallium/drivers/svga/svga_state_vs.c +++ b/src/gallium/drivers/svga/svga_state_vs.c @@ -27,8 +27,10 @@ #include "pipe/p_defines.h" #include "util/u_format.h" #include "util/u_math.h" +#include "util/u_memory.h" #include "util/u_bitmask.h" #include "translate/translate.h" +#include "tgsi/tgsi_ureg.h" #include "svga_context.h" #include "svga_state.h" @@ -65,6 +67,37 @@ static struct svga_shader_result *search_vs_key( struct svga_vertex_shader *vs, } +/** + * If we fail to compile a vertex shader we'll use a dummy/fallback shader + * that simply emits a (0,0,0,1) vertex position. + */ +static const struct tgsi_token * +get_dummy_vertex_shader(void) +{ + static const float zero[4] = { 0.0, 0.0, 0.0, 1.0 }; + struct ureg_program *ureg; + const struct tgsi_token *tokens; + struct ureg_src src; + struct ureg_dst dst; + unsigned num_tokens; + + ureg = ureg_create(TGSI_PROCESSOR_VERTEX); + if (!ureg) + return NULL; + + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + src = ureg_DECL_immediate(ureg, zero, 4); + ureg_MOV(ureg, dst, src); + ureg_END(ureg); + + tokens = ureg_get_tokens(ureg, &num_tokens); + + ureg_destroy(ureg); + + return tokens; +} + + static enum pipe_error compile_vs( struct svga_context *svga, struct svga_vertex_shader *vs, const struct svga_vs_compile_key *key, @@ -75,8 +108,20 @@ static enum pipe_error compile_vs( struct svga_context *svga, result = svga_translate_vertex_program( vs, key ); if (result == NULL) { - ret = PIPE_ERROR_OUT_OF_MEMORY; - goto fail; + /* some problem during translation, try the dummy shader */ + const struct tgsi_token *dummy = get_dummy_vertex_shader(); + if (!dummy) { + ret = PIPE_ERROR_OUT_OF_MEMORY; + goto fail; + } + debug_printf("Failed to compile vertex shader, using dummy shader instead.\n"); + FREE((void *) vs->base.tokens); + vs->base.tokens = dummy; + result = svga_translate_vertex_program(vs, key); + if (result == NULL) { + ret = PIPE_ERROR; + goto fail; + } } result->id = util_bitmask_add(svga->vs_bm); -- 2.30.2