[v2] i965: Combine both gl_PatchVerticesIn lowering passes.

Submitted by Kenneth Graunke on July 19, 2018, 2:24 a.m.

Details

Message ID 20180719022404.16907-1-kenneth@whitecape.org
State New
Headers show
Series "i965: Combine both gl_PatchVerticesIn lowering passes." ( rev: 2 ) in Mesa

Not browsing as part of any series.

Commit Message

Kenneth Graunke July 19, 2018, 2:24 a.m.
Until now, we had separate passes for lowering gl_PatchVerticesIn to
a statically known constant (for TES inputs when linked against a TCS),
and a uniform in the other cases.  Annoyingly, one had to be run before
nir_lower_system_values, and the other afterward.  This simplified the
passes, but made life painful for the callers.

This patch combines both into a single pass.  If you give it a non-zero
static count, it uses that.  If you give it Mesa state slots, it turns
it back into a built-in uniform.  Otherwise, it does nothing.

This also moves the i965 uniform lowering out to shared code.

v2: Make token arrays const.
---
 src/compiler/nir/nir.h                        |  3 +-
 src/compiler/nir/nir_lower_patch_vertices.c   | 68 +++++++++++++++++--
 src/intel/compiler/brw_nir.h                  |  2 -
 src/intel/vulkan/anv_pipeline.c               |  4 +-
 .../drivers/dri/i965/brw_nir_uniforms.cpp     | 28 --------
 src/mesa/drivers/dri/i965/brw_program.c       | 41 +++++------
 6 files changed, 84 insertions(+), 62 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 3bfe7d7f7bf..fe3b4a9c9cc 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2806,7 +2806,8 @@  void nir_lower_two_sided_color(nir_shader *shader);
 bool nir_lower_clamp_color_outputs(nir_shader *shader);
 
 void nir_lower_passthrough_edgeflags(nir_shader *shader);
-void nir_lower_tes_patch_vertices(nir_shader *tes, unsigned patch_vertices);
+bool nir_lower_patch_vertices(nir_shader *nir, unsigned static_count,
+                              const gl_state_index16 *uniform_state_tokens);
 
 typedef struct nir_lower_wpos_ytransform_options {
    gl_state_index16 state_tokens[STATE_LENGTH];
diff --git a/src/compiler/nir/nir_lower_patch_vertices.c b/src/compiler/nir/nir_lower_patch_vertices.c
index d196576b993..8e89268ca41 100644
--- a/src/compiler/nir/nir_lower_patch_vertices.c
+++ b/src/compiler/nir/nir_lower_patch_vertices.c
@@ -22,11 +22,52 @@ 
  */
 
 #include "nir_builder.h"
+#include "program/prog_instruction.h"
 
-void
-nir_lower_tes_patch_vertices(nir_shader *tes_nir, unsigned patch_vertices)
+static nir_variable *
+make_uniform(nir_shader *nir, const gl_state_index16 *tokens)
 {
-   nir_foreach_function(function, tes_nir) {
+   /* Note: name must be prefixed with "gl_" to trigger slot based
+    * special handling in uniform setup.
+    */
+   nir_variable *var =
+      nir_variable_create(nir, nir_var_uniform, glsl_int_type(),
+                          "gl_PatchVerticesIn");
+   var->num_state_slots = 1;
+   var->state_slots = ralloc_array(var, nir_state_slot, var->num_state_slots);
+   memcpy(var->state_slots[0].tokens, tokens, sizeof(*tokens) * STATE_LENGTH);
+   var->state_slots[0].swizzle = SWIZZLE_XXXX;
+
+   return var;
+}
+
+/**
+ * This pass lowers the load_patch_vertices_in intrinsic.
+ *
+ * - If we statically know the value, we lower it to a constant.
+ *   (If a TES is linked against a TCS, the TCS tells us the TES input count.)
+ *
+ * - If not, and we're given Mesa state slots, we lower it to a uniform.
+ *
+ * - Otherwise, we leave it as a system value.
+ *
+ * This pass must be run after nir_lower_system_values().
+ */
+bool
+nir_lower_patch_vertices(nir_shader *nir,
+                         unsigned static_count,
+                         const gl_state_index16 *uniform_state_tokens)
+{
+   bool progress = false;
+   nir_variable *var = NULL;
+
+   /* If there's no static count and we don't want uniforms, there's no
+    * lowering to do...just bail early.
+    */
+   if (static_count == 0 && !uniform_state_tokens)
+      return false;
+
+   nir_foreach_function(function, nir) {
       if (function->impl) {
          nir_foreach_block(block, function->impl) {
             nir_builder b;
@@ -38,7 +79,18 @@  nir_lower_tes_patch_vertices(nir_shader *tes_nir, unsigned patch_vertices)
                      continue;
 
                   b.cursor = nir_before_instr(&intr->instr);
-                  nir_ssa_def *val = nir_imm_int(&b, patch_vertices);
+
+                  nir_ssa_def *val = NULL;
+                  if (static_count) {
+                     val = nir_imm_int(&b, static_count);
+                  } else {
+                     if (!var)
+                        var = make_uniform(nir, uniform_state_tokens);
+
+                     val = nir_load_var(&b, var);
+                  }
+
+                  progress = true;
                   nir_ssa_def_rewrite_uses(&intr->dest.ssa,
                                            nir_src_for_ssa(val));
                   nir_instr_remove(instr);
@@ -46,8 +98,12 @@  nir_lower_tes_patch_vertices(nir_shader *tes_nir, unsigned patch_vertices)
             }
          }
 
-         nir_metadata_preserve(function->impl, nir_metadata_block_index |
-                                               nir_metadata_dominance);
+         if (progress) {
+            nir_metadata_preserve(function->impl, nir_metadata_block_index |
+                                                  nir_metadata_dominance);
+         }
       }
    }
+
+   return progress;
 }
diff --git a/src/intel/compiler/brw_nir.h b/src/intel/compiler/brw_nir.h
index 19442b47eae..6e8152dde64 100644
--- a/src/intel/compiler/brw_nir.h
+++ b/src/intel/compiler/brw_nir.h
@@ -144,8 +144,6 @@  void brw_nir_setup_arb_uniforms(void *mem_ctx, nir_shader *shader,
                                 struct gl_program *prog,
                                 struct brw_stage_prog_data *stage_prog_data);
 
-void brw_nir_lower_patch_vertices_in_to_uniform(nir_shader *nir);
-
 void brw_nir_analyze_ubo_ranges(const struct brw_compiler *compiler,
                                 nir_shader *nir,
                                 struct brw_ubo_range out_ranges[4]);
diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
index 95a686f7833..5ddb3aec207 100644
--- a/src/intel/vulkan/anv_pipeline.c
+++ b/src/intel/vulkan/anv_pipeline.c
@@ -683,8 +683,8 @@  anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
       }
 
-      nir_lower_tes_patch_vertices(tes_nir,
-                                   tcs_nir->info.tess.tcs_vertices_out);
+      nir_lower_patch_vertices(tes_nir, tcs_nir->info.tess.tcs_vertices_out,
+                               NULL);
 
       /* Copy TCS info into the TES info */
       merge_tess_info(&tes_nir->info, &tcs_nir->info);
diff --git a/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp b/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp
index 28a60691926..54f9f9b1a6b 100644
--- a/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp
+++ b/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp
@@ -267,31 +267,3 @@  brw_nir_setup_arb_uniforms(void *mem_ctx, nir_shader *shader,
          stage_prog_data->param[4 * p + i] = BRW_PARAM_BUILTIN_ZERO;
    }
 }
-
-void
-brw_nir_lower_patch_vertices_in_to_uniform(nir_shader *nir)
-{
-   nir_foreach_variable_safe(var, &nir->system_values) {
-      if (var->data.location != SYSTEM_VALUE_VERTICES_IN)
-         continue;
-
-      gl_state_index16 tokens[STATE_LENGTH] = {
-         STATE_INTERNAL,
-         nir->info.stage == MESA_SHADER_TESS_CTRL ?
-            (gl_state_index16)STATE_TCS_PATCH_VERTICES_IN :
-            (gl_state_index16)STATE_TES_PATCH_VERTICES_IN,
-      };
-      var->num_state_slots = 1;
-      var->state_slots =
-         ralloc_array(var, nir_state_slot, var->num_state_slots);
-      memcpy(var->state_slots[0].tokens, tokens, sizeof(tokens));
-      var->state_slots[0].swizzle = SWIZZLE_XXXX;
-
-      var->data.mode = nir_var_uniform;
-      var->data.location = -1;
-      exec_node_remove(&var->node);
-      exec_list_push_tail(&nir->uniforms, &var->node);
-   }
-
-   nir_fixup_deref_modes(nir);
-}
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 9fa1b4b9bb7..7adb75d0eaa 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -74,6 +74,7 @@  brw_create_nir(struct brw_context *brw,
                gl_shader_stage stage,
                bool is_scalar)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    const nir_shader_compiler_options *options =
       ctx->Const.ShaderCompilerOptions[stage].NirOptions;
@@ -99,32 +100,26 @@  brw_create_nir(struct brw_context *brw,
    }
    nir_validate_shader(nir);
 
-   /* Lower PatchVerticesIn from system value to uniform. This needs to
-    * happen before brw_preprocess_nir, since that will lower system values
-    * to intrinsics.
-    *
-    * We only do this for TES if no TCS is present, since otherwise we know
-    * the number of vertices in the patch at link time and we can lower it
-    * directly to a constant. We do this in nir_lower_patch_vertices, which
-    * needs to run after brw_nir_preprocess has turned the system values
-    * into intrinsics.
-    */
-   const bool lower_patch_vertices_in_to_uniform =
-      (stage == MESA_SHADER_TESS_CTRL && brw->screen->devinfo.gen >= 8) ||
-      (stage == MESA_SHADER_TESS_EVAL &&
-       !shader_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL]);
-
-   if (lower_patch_vertices_in_to_uniform)
-      brw_nir_lower_patch_vertices_in_to_uniform(nir);
-
    nir = brw_preprocess_nir(brw->screen->compiler, nir);
 
-   if (stage == MESA_SHADER_TESS_EVAL && !lower_patch_vertices_in_to_uniform) {
-      assert(shader_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL]);
-      struct gl_linked_shader *linked_tcs =
+   if (stage == MESA_SHADER_TESS_CTRL) {
+      /* Lower gl_PatchVerticesIn from a sys. value to a uniform on Gen8+. */
+      static const gl_state_index16 tokens[STATE_LENGTH] =
+         { STATE_INTERNAL, STATE_TCS_PATCH_VERTICES_IN };
+      nir_lower_patch_vertices(nir, 0, devinfo->gen >= 8 ? tokens : NULL);
+   }
+
+   if (stage == MESA_SHADER_TESS_EVAL) {
+      /* Lower gl_PatchVerticesIn to a constant if we have a TCS, or
+       * a uniform if we don't.
+       */
+      struct gl_linked_shader *tcs =
          shader_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL];
-      uint32_t patch_vertices = linked_tcs->Program->info.tess.tcs_vertices_out;
-      nir_lower_tes_patch_vertices(nir, patch_vertices);
+      uint32_t static_patch_vertices =
+         tcs ? tcs->Program->info.tess.tcs_vertices_out : 0;
+      static const gl_state_index16 tokens[STATE_LENGTH] =
+         { STATE_INTERNAL, STATE_TES_PATCH_VERTICES_IN };
+      nir_lower_patch_vertices(nir, static_patch_vertices, tokens);
    }
 
    if (stage == MESA_SHADER_FRAGMENT) {