Module: Mesa
Branch: main
Commit: 4f78c273307585a0cd3f0367f4d77b53dc4d45c5
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=4f78c273307585a0cd3f0367f4d77b53dc4d45c5

Author: Emma Anholt <[email protected]>
Date:   Tue Oct  3 12:53:24 2023 -0700

i915: Do a test compile at glLinkShader() time.

This lets us throw errors back to the app for shaders that are too
complex.  The X server would really like to have this instead of guessing
based on renderer strings when shaders might be too complicated.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25533>

---

 src/gallium/drivers/i915/i915_fpc.h           |  3 +++
 src/gallium/drivers/i915/i915_fpc_translate.c | 15 ++++++-----
 src/gallium/drivers/i915/i915_screen.c        |  7 ++++-
 src/gallium/drivers/i915/i915_state.c         | 38 ++++++++++++++++++++++++---
 4 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/src/gallium/drivers/i915/i915_fpc.h 
b/src/gallium/drivers/i915/i915_fpc.h
index a1d85604534..4762d54862a 100644
--- a/src/gallium/drivers/i915/i915_fpc.h
+++ b/src/gallium/drivers/i915/i915_fpc.h
@@ -281,6 +281,9 @@ struct i915_token_list {
    unsigned NumTokens;
 };
 
+char *i915_test_fragment_shader_compile(struct pipe_screen *screen,
+                                        struct nir_shader *s);
+
 extern struct i915_token_list *i915_optimize(const struct tgsi_token *tokens);
 
 extern void i915_optimize_free(struct i915_token_list *tokens);
diff --git a/src/gallium/drivers/i915/i915_fpc_translate.c 
b/src/gallium/drivers/i915/i915_fpc_translate.c
index d6201cc45ae..72eb73ed3c2 100644
--- a/src/gallium/drivers/i915/i915_fpc_translate.c
+++ b/src/gallium/drivers/i915/i915_fpc_translate.c
@@ -1039,12 +1039,15 @@ i915_fini_compile(struct i915_context *i915, struct 
i915_fp_compile *p)
       memcpy(&ifs->program[decl_size], p->program,
              program_size * sizeof(uint32_t));
 
-      util_debug_message(
-         &i915->debug, SHADER_INFO,
-         "%s shader: %d inst, %d tex, %d tex_indirect, %d temps, %d const",
-         _mesa_shader_stage_to_abbrev(MESA_SHADER_FRAGMENT), (int)program_size,
-         p->nr_tex_insn, p->nr_tex_indirect,
-         p->shader->info.file_max[TGSI_FILE_TEMPORARY] + 1, 
ifs->num_constants);
+      if (i915) {
+         util_debug_message(
+            &i915->debug, SHADER_INFO,
+            "%s shader: %d inst, %d tex, %d tex_indirect, %d temps, %d const",
+            _mesa_shader_stage_to_abbrev(MESA_SHADER_FRAGMENT),
+            (int)program_size, p->nr_tex_insn, p->nr_tex_indirect,
+            p->shader->info.file_max[TGSI_FILE_TEMPORARY] + 1,
+            ifs->num_constants);
+      }
    }
 
    if (strlen(p->error) != 0)
diff --git a/src/gallium/drivers/i915/i915_screen.c 
b/src/gallium/drivers/i915/i915_screen.c
index 6462ced9992..8c81bd7c588 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -27,6 +27,7 @@
 
 #include "compiler/nir/nir.h"
 #include "draw/draw_context.h"
+#include "nir/nir_to_tgsi.h"
 #include "util/format/u_format.h"
 #include "util/format/u_format_s3tc.h"
 #include "util/os_misc.h"
@@ -37,6 +38,7 @@
 
 #include "i915_context.h"
 #include "i915_debug.h"
+#include "i915_fpc.h"
 #include "i915_public.h"
 #include "i915_reg.h"
 #include "i915_resource.h"
@@ -277,7 +279,10 @@ i915_finalize_nir(struct pipe_screen *pscreen, void *nir)
    if (msg)
       return strdup(msg);
 
-   return NULL;
+   if (s->info.stage == MESA_SHADER_FRAGMENT)
+      return i915_test_fragment_shader_compile(pscreen, s);
+   else
+      return NULL;
 }
 
 static int
diff --git a/src/gallium/drivers/i915/i915_state.c 
b/src/gallium/drivers/i915/i915_state.c
index 151d1c7928e..8d8c3527823 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -534,6 +534,10 @@ i915_set_polygon_stipple(struct pipe_context *pipe,
 {
 }
 
+static const struct nir_to_tgsi_options ntt_options = {
+   .lower_fabs = true,
+};
+
 static void *
 i915_create_fs_state(struct pipe_context *pipe,
                      const struct pipe_shader_state *templ)
@@ -549,9 +553,6 @@ i915_create_fs_state(struct pipe_context *pipe,
       nir_shader *s = templ->ir.nir;
       ifs->internal = s->info.internal;
 
-      static const struct nir_to_tgsi_options ntt_options = {
-         .lower_fabs = true,
-      };
       ifs->state.tokens = nir_to_tgsi_options(s, pipe->screen, &ntt_options);
    } else {
       assert(templ->type == PIPE_SHADER_IR_TGSI);
@@ -606,6 +607,37 @@ i915_delete_fs_state(struct pipe_context *pipe, void 
*shader)
    FREE(ifs);
 }
 
+/* Does a test compile at link time to see if we'll be able to run this shader
+ * at runtime.  Return a string to the GLSL compiler for anything we should
+ * report as link failure.
+ */
+char *
+i915_test_fragment_shader_compile(struct pipe_screen *screen, nir_shader *s)
+{
+   struct i915_fragment_shader *ifs = CALLOC_STRUCT(i915_fragment_shader);
+   if (!ifs)
+      return NULL;
+
+   /* NTT takes ownership of the shader, give it a clone. */
+   s = nir_shader_clone(NULL, s);
+
+   ifs->internal = s->info.internal;
+   ifs->state.tokens = nir_to_tgsi_options(s, screen, &ntt_options);
+   ifs->state.type = PIPE_SHADER_IR_TGSI;
+
+   tgsi_scan_shader(ifs->state.tokens, &ifs->info);
+
+   i915_translate_fragment_program(NULL, ifs);
+
+   char *msg = NULL;
+   if (ifs->error)
+      msg = strdup(ifs->error);
+
+   i915_delete_fs_state(NULL, ifs);
+
+   return msg;
+}
+
 static void *
 i915_create_vs_state(struct pipe_context *pipe,
                      const struct pipe_shader_state *templ)

Reply via email to