Mesa (master): glsl: use NIR function inlining for drivers that use glsl_to_nir()

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Mar 7 00:33:44 UTC 2019


Module: Mesa
Branch: master
Commit: 7e60d5a501f311fa5e7bca5335adc6013dc1aeb9
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7e60d5a501f311fa5e7bca5335adc6013dc1aeb9

Author: Timothy Arceri <tarceri at itsqueeze.com>
Date:   Wed Feb 20 17:13:49 2019 +1100

glsl: use NIR function inlining for drivers that use glsl_to_nir()

glsl_to_nir() is still missing support for converting certain
functions to NIR, so for those we use the GLSL IR optimisations
to remove the functions.

Reviewed-by: Eric Anholt <eric at anholt.net>

---

 src/compiler/glsl/glsl_to_nir.cpp               | 82 ++++++++++++++++++++++++-
 src/compiler/glsl/glsl_to_nir.h                 |  3 +-
 src/gallium/drivers/freedreno/ir3/ir3_cmdline.c |  2 +-
 src/gallium/drivers/panfrost/midgard/cmdline.c  |  6 +-
 src/mesa/drivers/dri/i965/brw_program.c         |  2 +-
 src/mesa/state_tracker/st_glsl_to_nir.cpp       |  2 +-
 6 files changed, 89 insertions(+), 8 deletions(-)

diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp
index 062434d066b..004a430d124 100644
--- a/src/compiler/glsl/glsl_to_nir.cpp
+++ b/src/compiler/glsl/glsl_to_nir.cpp
@@ -30,6 +30,7 @@
 #include "ir_visitor.h"
 #include "ir_hierarchical_visitor.h"
 #include "ir.h"
+#include "ir_optimization.h"
 #include "program.h"
 #include "compiler/nir/nir_control_flow.h"
 #include "compiler/nir/nir_builder.h"
@@ -133,15 +134,74 @@ private:
    nir_visitor *visitor;
 };
 
+/* glsl_to_nir can only handle converting certain function paramaters
+ * to NIR. This visitor checks for parameters it can't currently handle.
+ */
+class ir_function_param_visitor : public ir_hierarchical_visitor
+{
+public:
+   ir_function_param_visitor()
+      : unsupported(false)
+   {
+   }
+
+   virtual ir_visitor_status visit_enter(ir_function_signature *ir)
+   {
+
+      if (ir->is_intrinsic())
+         return visit_continue;
+
+      foreach_in_list(ir_variable, param, &ir->parameters) {
+         if (!param->type->is_vector() || !param->type->is_scalar()) {
+            unsupported = true;
+            return visit_stop;
+         }
+
+         if (param->data.mode == ir_var_function_inout) {
+            unsupported = true;
+            return visit_stop;
+         }
+      }
+
+      return visit_continue;
+   }
+
+   bool unsupported;
+};
+
 } /* end of anonymous namespace */
 
+
+static bool
+has_unsupported_function_param(exec_list *ir)
+{
+   ir_function_param_visitor visitor;
+   visit_list_elements(&visitor, ir);
+   return visitor.unsupported;
+}
+
 nir_shader *
-glsl_to_nir(const struct gl_shader_program *shader_prog,
+glsl_to_nir(struct gl_context *ctx,
+            const struct gl_shader_program *shader_prog,
             gl_shader_stage stage,
             const nir_shader_compiler_options *options)
 {
    struct gl_linked_shader *sh = shader_prog->_LinkedShaders[stage];
 
+   const struct gl_shader_compiler_options *gl_options =
+      &ctx->Const.ShaderCompilerOptions[stage];
+
+   /* glsl_to_nir can only handle converting certain function paramaters
+    * to NIR. If we find something we can't handle then we get the GLSL IR
+    * opts to remove it before we continue on.
+    *
+    * TODO: add missing glsl ir to nir support and remove this loop.
+    */
+   while (has_unsupported_function_param(sh->ir)) {
+      do_common_optimization(sh->ir, true, true, gl_options,
+                             ctx->Const.NativeIntegers);
+   }
+
    nir_shader *shader = nir_shader_create(NULL, stage, options,
                                           &sh->Program->info);
 
@@ -150,7 +210,27 @@ glsl_to_nir(const struct gl_shader_program *shader_prog,
    v2.run(sh->ir);
    visit_exec_list(sh->ir, &v1);
 
+   nir_validate_shader(shader, "after glsl to nir, before function inline");
+
+   /* We have to lower away local constant initializers right before we
+    * inline functions.  That way they get properly initialized at the top
+    * of the function and not at the top of its caller.
+    */
    nir_lower_constant_initializers(shader, (nir_variable_mode)~0);
+   nir_lower_returns(shader);
+   nir_inline_functions(shader);
+   nir_opt_deref(shader);
+
+   nir_validate_shader(shader, "after function inlining and return lowering");
+
+   /* Now that we have inlined everything remove all of the functions except
+    * main().
+    */
+   foreach_list_typed_safe(nir_function, function, node, &(shader)->functions){
+      if (strcmp("main", function->name) != 0) {
+         exec_node_remove(&function->node);
+      }
+   }
 
    /* Remap the locations to slots so those requiring two slots will occupy
     * two locations. For instance, if we have in the IR code a dvec3 attr0 in
diff --git a/src/compiler/glsl/glsl_to_nir.h b/src/compiler/glsl/glsl_to_nir.h
index 115c8e1270b..38728d3ff26 100644
--- a/src/compiler/glsl/glsl_to_nir.h
+++ b/src/compiler/glsl/glsl_to_nir.h
@@ -36,7 +36,8 @@ extern "C" {
 
 struct gl_shader_program;
 
-nir_shader *glsl_to_nir(const struct gl_shader_program *shader_prog,
+nir_shader *glsl_to_nir(struct gl_context *ctx,
+                        const struct gl_shader_program *shader_prog,
                         gl_shader_stage stage,
                         const nir_shader_compiler_options *options);
 
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c
index 0850618bc3d..a8120578283 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c
@@ -116,7 +116,7 @@ load_glsl(unsigned num_files, char* const* files, gl_shader_stage stage)
 	if (!prog)
 		errx(1, "couldn't parse `%s'", files[0]);
 
-	nir_shader *nir = glsl_to_nir(prog, stage, nir_options);
+	nir_shader *nir = glsl_to_nir(&local_ctx, prog, stage, nir_options);
 
 	/* required NIR passes: */
 	if (nir_options->lower_all_io_to_temps ||
diff --git a/src/gallium/drivers/panfrost/midgard/cmdline.c b/src/gallium/drivers/panfrost/midgard/cmdline.c
index 7326402dd09..acd810b2f34 100644
--- a/src/gallium/drivers/panfrost/midgard/cmdline.c
+++ b/src/gallium/drivers/panfrost/midgard/cmdline.c
@@ -66,11 +66,11 @@ compile_shader(char **argv)
         }
 
         midgard_program compiled;
-        nir = glsl_to_nir(prog, MESA_SHADER_VERTEX, &midgard_nir_options);
+        nir = glsl_to_nir(&local_ctx, prog, MESA_SHADER_VERTEX, &midgard_nir_options);
         midgard_compile_shader_nir(nir, &compiled, false);
         finalise_to_disk("vertex.bin", &compiled.compiled);
 
-        nir = glsl_to_nir(prog, MESA_SHADER_FRAGMENT, &midgard_nir_options);
+        nir = glsl_to_nir(&local_ctx, prog, MESA_SHADER_FRAGMENT, &midgard_nir_options);
         midgard_compile_shader_nir(nir, &compiled, false);
         finalise_to_disk("fragment.bin", &compiled.compiled);
 }
@@ -91,7 +91,7 @@ compile_blend(char **argv)
         prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->info.stage = MESA_SHADER_FRAGMENT;
 
         midgard_program program;
-        nir = glsl_to_nir(prog, MESA_SHADER_FRAGMENT, &midgard_nir_options);
+        nir = glsl_to_nir(&local_ctx, prog, MESA_SHADER_FRAGMENT, &midgard_nir_options);
         midgard_compile_shader_nir(nir, &program, true);
         finalise_to_disk("blend.bin", &program.compiled);
 }
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index ffb49c35cd4..e58ed7c8e48 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -93,7 +93,7 @@ brw_create_nir(struct brw_context *brw,
       if (shader_prog->data->spirv) {
          nir = _mesa_spirv_to_nir(ctx, shader_prog, stage, options);
       } else {
-         nir = glsl_to_nir(shader_prog, stage, options);
+         nir = glsl_to_nir(ctx, shader_prog, stage, options);
       }
       assert (nir);
 
diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp
index fa0cdf771e4..7b339e9e043 100644
--- a/src/mesa/state_tracker/st_glsl_to_nir.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp
@@ -361,7 +361,7 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
    if (prog->nir)
       return prog->nir;
 
-   nir_shader *nir = glsl_to_nir(shader_program, stage, options);
+   nir_shader *nir = glsl_to_nir(st->ctx, shader_program, stage, options);
 
    /* Set the next shader stage hint for VS and TES. */
    if (!nir->info.separate_shader &&




More information about the mesa-commit mailing list