On 21/11/17 15:02, Ilia Mirkin wrote:
Should this work out of the box for freedreno and vc4 as well? Or will
those need changes like radeonsi did?

I'm hopeful they shouldn't need any big changes as the radeonsi changes are due to expecting everything to be a vec4 because it code shares with the tgsi backend. However I have done 0 testing so any testing on those drivers is appreciated.



On Mon, Nov 20, 2017 at 10:37 PM, Timothy Arceri <[email protected]> wrote:
---
  src/mesa/state_tracker/st_glsl_to_nir.cpp | 77 +++++++++++++++++++++++++++++++
  1 file changed, 77 insertions(+)

diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp 
b/src/mesa/state_tracker/st_glsl_to_nir.cpp
index 27e36bd306..53e07a78e2 100644
--- a/src/mesa/state_tracker/st_glsl_to_nir.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp
@@ -468,36 +468,107 @@ st_nir_get_mesa_program(struct gl_context *ctx,
     NIR_PASS_V(nir, nir_lower_io_to_temporaries,
                nir_shader_get_entrypoint(nir),
                true, true);
     NIR_PASS_V(nir, nir_lower_global_vars_to_local);
     NIR_PASS_V(nir, nir_split_var_copies);
     NIR_PASS_V(nir, nir_lower_var_copies);

     return nir;
  }

+static void
+st_nir_link_shaders(nir_shader **producer, nir_shader **consumer)
+{
+   nir_lower_io_arrays_to_elements(*producer, *consumer);
+
+   NIR_PASS_V(*producer, nir_remove_dead_variables, nir_var_shader_out);
+   NIR_PASS_V(*consumer, nir_remove_dead_variables, nir_var_shader_in);
+
+   if (nir_remove_unused_varyings(*producer, *consumer)) {
+      NIR_PASS_V(*producer, nir_lower_global_vars_to_local);
+      NIR_PASS_V(*consumer, nir_lower_global_vars_to_local);
+
+      /* The backend might not be able to handle indirects on
+       * temporaries so we need to lower indirects on any of the
+       * varyings we have demoted here.
+       *
+       * TODO: radeonsi shouldn't need to do this, however LLVM isn't
+       * currently smart enough to handle indirects without causing excess
+       * spilling causing the gpu to hang.
+       *
+       * See the following thread for more details of the problem:
+       * https://lists.freedesktop.org/archives/mesa-dev/2017-July/162106.html
+       */
+      nir_variable_mode indirect_mask = nir_var_local;
+
+      NIR_PASS_V(*producer, nir_lower_indirect_derefs, indirect_mask);
+      NIR_PASS_V(*consumer, nir_lower_indirect_derefs, indirect_mask);
+
+      st_nir_opts(*producer);
+      st_nir_opts(*consumer);
+   }
+}
+
  extern "C" {

  bool
  st_link_nir(struct gl_context *ctx,
              struct gl_shader_program *shader_program)
  {
     struct st_context *st = st_context(ctx);

+   /* Determine first and last stage. */
+   unsigned first = MESA_SHADER_STAGES;
+   unsigned last = 0;
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      if (!shader_program->_LinkedShaders[i])
+         continue;
+      if (first == MESA_SHADER_STAGES)
+         first = i;
+      last = i;
+   }
+
     for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
        struct gl_linked_shader *shader = shader_program->_LinkedShaders[i];
        if (shader == NULL)
           continue;

        nir_shader *nir = st_nir_get_mesa_program(ctx, shader_program, shader);
+
+      nir_variable_mode mask = (nir_variable_mode) 0;
+      if (i != first)
+         mask = (nir_variable_mode)(mask | nir_var_shader_in);
+
+      if (i != last)
+         mask = (nir_variable_mode)(mask | nir_var_shader_out);
+
+      nir_lower_io_to_scalar_early(nir, mask);
+      st_nir_opts(nir);
+   }
+
+   /* Linking the stages in the opposite order (from fragment to vertex)
+    * ensures that inter-shader outputs written to in an earlier stage
+    * are eliminated if they are (transitively) not used in a later
+    * stage.
+    */
+   int next = last;
+   for (int i = next - 1; i >= 0; i--) {
+      struct gl_linked_shader *shader = shader_program->_LinkedShaders[i];
+      if (shader == NULL)
+         continue;
+
+      st_nir_link_shaders(&shader->Program->nir,
+                          &shader_program->_LinkedShaders[next]->Program->nir);
+      next = i;
     }

+   int prev = -1;
     for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
        struct gl_linked_shader *shader = shader_program->_LinkedShaders[i];
        if (shader == NULL)
           continue;

        nir_shader *nir = shader->Program->nir;

        /* fragment shaders may need : */
        if (nir->info.stage == MESA_SHADER_FRAGMENT) {
           static const gl_state_index wposTransformState[STATE_LENGTH] = {
@@ -526,20 +597,26 @@ st_link_nir(struct gl_context *ctx,
              _mesa_add_state_reference(shader->Program->Parameters,
                                        wposTransformState);
           }
        }

        NIR_PASS_V(nir, nir_lower_system_values);

        nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
        shader->Program->info = nir->info;

+      if (prev != -1) {
+         
nir_compact_varyings(shader_program->_LinkedShaders[prev]->Program->nir,
+                              nir, ctx->API != API_OPENGL_COMPAT);
+      }
+      prev = i;
+
        st_glsl_to_nir_post_opts(st, shader->Program, shader_program);

        assert(shader->Program);
        if (!ctx->Driver.ProgramStringNotify(ctx,
                                             _mesa_shader_stage_to_program(i),
                                             shader->Program)) {
           _mesa_reference_program(ctx, &shader->Program, NULL);
           return false;
        }
     }
--
2.14.3

_______________________________________________
mesa-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
_______________________________________________
mesa-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to