svga: use dummy shaders when translation fails
authorBrian Paul <brianp@vmware.com>
Thu, 17 Nov 2011 23:40:02 +0000 (16:40 -0700)
committerBrian Paul <brianp@vmware.com>
Thu, 23 Feb 2012 14:49:06 +0000 (07:49 -0700)
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 <jfonseca@vmware.com>
src/gallium/drivers/svga/svga_state_fs.c
src/gallium/drivers/svga/svga_state_vs.c

index c95d82fc00e7705263d384c329b16f35b28beafb..8503b03eed417039e484e28e82203e7cfdeaba33 100644 (file)
@@ -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);
index b82e68556e419242e21b794c1301c07f8683f74e..3cb0cdb96979cd1fd5848ccd6ced5909143e57c1 100644 (file)
 #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);