[Mesa-dev] [PATCH 2/2] svga: check shader size against max command buffer size

Brian Paul brianp at vmware.com
Fri Jan 31 16:24:19 PST 2014


If the shader is too large, plug in a dummy shader.  This patch also
reworks the existing dummy shader code.
---
 src/gallium/drivers/svga/include/svga_reg.h |    1 +
 src/gallium/drivers/svga/svga_state_fs.c    |   60 +++++++++++++++++++++------
 2 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/svga/include/svga_reg.h b/src/gallium/drivers/svga/include/svga_reg.h
index 1b96c2e..dee719d 100644
--- a/src/gallium/drivers/svga/include/svga_reg.h
+++ b/src/gallium/drivers/svga/include/svga_reg.h
@@ -889,6 +889,7 @@ typedef enum {
 } SVGAFifoCmdId;
 
 #define SVGA_CMD_MAX_ARGS           64
+#define SVGA_CB_MAX_COMMAND_SIZE (32 * 1024) // 32 KB
 
 
 /*
diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c
index 860a0c8..7119a19 100644
--- a/src/gallium/drivers/svga/svga_state_fs.c
+++ b/src/gallium/drivers/svga/svga_state_fs.c
@@ -76,12 +76,18 @@ search_fs_key(const 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.
+ * simply emits a constant color (red for debug, black for release).
+ * We hit this with the Unigine/Heaven demo when Shaders = High.
+ * With black, the demo still looks good.
  */
 static const struct tgsi_token *
 get_dummy_fragment_shader(void)
 {
-   static const float red[4] = { 1.0, 0.0, 0.0, 0.0 };
+#ifdef DEBUG
+   static const float color[4] = { 1.0, 0.0, 0.0, 0.0 }; /* red */
+#else
+   static const float color[4] = { 0.0, 0.0, 0.0, 0.0 }; /* black */
+#endif
    struct ureg_program *ureg;
    const struct tgsi_token *tokens;
    struct ureg_src src;
@@ -93,7 +99,7 @@ get_dummy_fragment_shader(void)
       return NULL;
 
    dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
-   src = ureg_DECL_immediate(ureg, red, 4);
+   src = ureg_DECL_immediate(ureg, color, 4);
    ureg_MOV(ureg, dst, src);
    ureg_END(ureg);
 
@@ -106,6 +112,29 @@ get_dummy_fragment_shader(void)
 
 
 /**
+ * Replace the given shader's instruction with a simple constant-color
+ * shader.  We use this when normal shader translation fails.
+ */
+static struct svga_shader_variant *
+get_compiled_dummy_shader(struct svga_fragment_shader *fs,
+                          const struct svga_fs_compile_key *key)
+{
+   const struct tgsi_token *dummy = get_dummy_fragment_shader();
+   struct svga_shader_variant *variant;
+
+   if (!dummy) {
+      return NULL;
+   }
+
+   FREE((void *) fs->base.tokens);
+   fs->base.tokens = dummy;
+
+   variant = svga_translate_fragment_program(fs, key);
+   return variant;
+}
+
+
+/**
  * Translate TGSI shader into an svga shader variant.
  */
 static enum pipe_error
@@ -119,17 +148,24 @@ compile_fs(struct svga_context *svga,
 
    variant = svga_translate_fragment_program( fs, key );
    if (variant == NULL) {
-      /* 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;
+      debug_printf("Failed to compile fragment shader,"
+                   " using dummy shader instead.\n");
+      variant = get_compiled_dummy_shader(fs, key);
+      if (!variant) {
+         ret = PIPE_ERROR;
          goto fail;
       }
-      debug_printf("Failed to compile fragment shader, using dummy shader instead.\n");
-      FREE((void *) fs->base.tokens);
-      fs->base.tokens = dummy;
-      variant = svga_translate_fragment_program(fs, key);
-      if (variant == NULL) {
+   }
+
+   if (variant->nr_tokens * sizeof(variant->tokens[0])
+       + sizeof(SVGA3dCmdDefineShader) + sizeof(SVGA3dCmdHeader)
+       >= SVGA_CB_MAX_COMMAND_SIZE) {
+      /* too big, use dummy shader */
+      debug_printf("Shader too large (%lu bytes),"
+                   " using dummy shader instead.\n",
+                   (unsigned long ) variant->nr_tokens * sizeof(variant->tokens[0]));
+      variant = get_compiled_dummy_shader(fs, key);
+      if (!variant) {
          ret = PIPE_ERROR;
          goto fail;
       }
-- 
1.7.10.4



More information about the mesa-dev mailing list