Skip to contentSkip to conversation

gallium: add support for NIR as alternate IR

RFC In review Rob Clark 2 participants 10 messages Oct 19, 2015

lore
Share & tools
lore

Rob Clark

author
#0 lore raw

cover gallium: add support for NIR as alternate IR

From: Rob Clark <[email protected]>

Still quite rough around the edges, but now it's at the point of sorta- kinda-working-sometimes. So I guess time to get wider feedback.

The initial goal is to figure out things that glsl_to_nir does differently from tgsi_to_nir, so we can fix them up and have better likelyhood of drivers being able to consume NIR from multiple sources. Eventually I'd like to be able to re-use spriv->nir for compute/ clover support, for example. And at some point I'd like to be able to bypass the conversion from glsl->tgsi for mesa st. But for now, being able to track down and fix differences between glsl_to_nir vs tgsi_to_nir is a good start.

With what I've added to pipe_shader_state (which is, I suppose, missing some doc updates), the intention is that drivers can ask for an IR other than TGSI. And what they actually get will be either TGSI or their preferred IR. Drivers will have to always handle the TGSI case, so the intention isn't to port all the different state trackers (or internally generated shaders, etc).

I suppose pipe_compute_state needs similar treatment, but I've skipped that for now.

Currently only the direct GLSL->NIR path is implemented for vertex shaders, which results in a huge hack at the end of the series. It isn't ever intended for drivers to mix/match glsl->nir vs glsl->tgsi-> nir across shader stages. But this is sufficient for now for me to debug other issues.

Shader variant handling will be completely broken at the moment, without having a nir_clone()[1]. (Ian, depending on how far that is from the top of your TODO list, I can take a stab at that, since I might be the first consumer.)

Also, there is some trivial shader variant handling in mesa st which would have to be ported to NIR. Or, perhaps, just somehow expose the shader key to the driver. (Currently most drivers are doing much more variant handling within the driver, and having two levels of variants does seem a bit silly.)

[1] https://bugs.freedesktop.org/show_bug.cgi?id=89436

(First patch isn't actually RFC.. just an issue that I noticed in the process.)

Rob Clark (8):
nir: add nir_var_all enum
gallium: refactor pipe_shader_state to support multiple IR's
gallium: add NIR as a possible IR
mesa/st: add support for NIR as possible driver IR freedreno/ir3: drop tokens arg
freedreno/ir3: add support for NIR as preferred IR freedreno/ir3: fix const_index handling for uniforms
HACK: freedreno/ir3: hack for mismatch on varying slots for

    glsl->tgsi->nir vs glsl->nir
 src/gallium/auxiliary/hud/hud_context.c            |  14 +-
 src/gallium/auxiliary/postprocess/pp_run.c         |   4 +-
 src/gallium/auxiliary/tgsi/tgsi_ureg.c             |   6 +-
 src/gallium/auxiliary/util/u_simple_shaders.c      |  42 +++-
 src/gallium/auxiliary/util/u_tests.c               |   7 +-
 src/gallium/drivers/freedreno/freedreno_screen.c   |   5 +-
 src/gallium/drivers/freedreno/freedreno_util.h     |   1 +
 .../drivers/freedreno/ir3/ir3_compiler_nir.c       |  38 +++-
 src/gallium/drivers/freedreno/ir3/ir3_shader.c     |  30 ++-
 src/gallium/drivers/freedreno/ir3/ir3_shader.h     |   3 +
 src/gallium/include/pipe/p_defines.h               |  13 +-
 src/gallium/include/pipe/p_state.h                 |  21 +-
 src/glsl/nir/nir.c                                 |   4 +
 src/glsl/nir/nir.h                                 |   1 +
 src/glsl/nir/nir_lower_io.c                        |   2 +-
 src/mesa/drivers/dri/i965/brw_nir.c                |   3 +-
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp         | 223 ++++++++++++++++++++-
 src/mesa/state_tracker/st_program.c                |  43 +++-
 18 files changed, 422 insertions(+), 38 deletions(-)
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#1 lore raw

PATCH 1/8 nir: add nir_var_all enum

Otherwise, passing -1 gets you:

error: invalid conversion from 'int' to 'nir_variable_mode' [-fpermissive]

---
 src/glsl/nir/nir.c                  | 4 ++++
 src/glsl/nir/nir.h                  | 1 +
 src/glsl/nir/nir_lower_io.c         | 2 +-
 src/mesa/drivers/dri/i965/brw_nir.c | 3 ++-
 4 files changed, 8 insertions(+), 2 deletions(-)
src/glsl/nir/nir.c +4 -0
index 793bdaf..caa9ffc 100644
@@ -107,6 +107,10 @@ void
 nir_shader_add_variable(nir_shader *shader, nir_variable *var)
 {
    switch (var->data.mode) {
+   case nir_var_all:
+      assert(!"invalid mode");
+      break;
+
    case nir_var_local:
       assert(!"nir_shader_add_variable cannot be used for local variables");
       break;
src/glsl/nir/nir.h +1 -0
index c867e6d..2a84cb0 100644
@@ -82,6 +82,7 @@ typedef struct {
 } nir_state_slot;
 
 typedef enum {
+   nir_var_all = -1,
    nir_var_shader_in,
    nir_var_shader_out,
    nir_var_global,
src/glsl/nir/nir_lower_io.c +1 -1
index 688b48f..b4ed857 100644
@@ -176,7 +176,7 @@ nir_lower_io_block(nir_block *block, void *void_state)
 
       nir_variable_mode mode = intrin->variables[0]->var->data.mode;
 
-      if (state->mode != -1 && state->mode != mode)
+      if (state->mode != nir_var_all && state->mode != mode)
          continue;
 
       switch (intrin->intrinsic) {
src/mesa/drivers/dri/i965/brw_nir.c +2 -1
index af9d041..e22f5fa 100644
@@ -219,7 +219,8 @@ brw_create_nir(struct brw_context *brw,
    nir_assign_var_locations(&nir->uniforms,
                             &nir->num_uniforms,
                             is_scalar ? type_size_scalar : type_size_vec4);
-   nir_lower_io(nir, -1, is_scalar ? type_size_scalar : type_size_vec4);
+   nir_lower_io(nir, nir_var_all,
+                is_scalar ? type_size_scalar : type_size_vec4);
    nir_validate_shader(nir);
 
    nir_remove_dead_variables(nir);
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#2 lore raw

RFC 2/8 gallium: refactor pipe_shader_state to support multiple IR's

In reply to Rob Clark

The goal is to allow the pipe driver to request something other than TGSI, but detect whether what is getting is TGSI vs what it requested. The pipe drivers will always have to support TGSI (and convert that into whatever it is that they prefer), but in some cases we should be able to skip the TGSI intermediate step (such as glsl->nir vs glsl->tgsi->nir).

I think pipe_compute_state should get similar treatment. Currently, afaict, it has one user and one consumer, which has allowed it to be sloppy wrt. supporting alternative IR's.

---
 src/gallium/auxiliary/hud/hud_context.c       | 14 +++++++--
 src/gallium/auxiliary/postprocess/pp_run.c    |  4 ++-
 src/gallium/auxiliary/tgsi/tgsi_ureg.c        |  6 ++--
 src/gallium/auxiliary/util/u_simple_shaders.c | 42 +++++++++++++++++++++++----
 src/gallium/auxiliary/util/u_tests.c          |  7 ++++-
 src/gallium/include/pipe/p_defines.h          | 12 ++++++--
 src/gallium/include/pipe/p_state.h            | 20 +++++++++++--
 7 files changed, 89 insertions(+), 16 deletions(-)
src/gallium/auxiliary/hud/hud_context.c +12 -2
index 95eed26..9f39abd 100644
@@ -1179,7 +1179,12 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
       };
 
       struct tgsi_token tokens[1000];
-      struct pipe_shader_state state = {tokens};
+      struct pipe_shader_state state;
+
+      memset(&state, 0, sizeof(state));
+
+      state.ir = PIPE_SHADER_IR_TGSI;
+      state.tokens = tokens;
 
       if (!tgsi_text_translate(fragment_shader_text, tokens, Elements(tokens))) {
          assert(0);
@@ -1226,7 +1231,12 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
       };
 
       struct tgsi_token tokens[1000];
-      struct pipe_shader_state state = {tokens};
+      struct pipe_shader_state state;
+
+      memset(&state, 0, sizeof(state));
+
+      state.ir = PIPE_SHADER_IR_TGSI;
+      state.tokens = tokens;
 
       if (!tgsi_text_translate(vertex_shader_text, tokens, Elements(tokens))) {
          assert(0);
src/gallium/auxiliary/postprocess/pp_run.c +3 -1
index caa2062..6cd2b70 100644
@@ -272,8 +272,10 @@ pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
       return NULL;
    }
 
+   memset(&state, 0, sizeof(state));
+
+   state.ir = PIPE_SHADER_IR_TGSI;
    state.tokens = tokens;
-   memset(&state.stream_output, 0, sizeof(state.stream_output));
 
    if (isvs) {
       ret_state = pipe->create_vs_state(pipe, &state);
src/gallium/auxiliary/tgsi/tgsi_ureg.c +4 -2
index 3d21319..96a51c4 100644
@@ -1777,14 +1777,16 @@ void *ureg_create_shader( struct ureg_program *ureg,
 {
    struct pipe_shader_state state;
 
+   memset(&state, 0, sizeof(state));
+
+   state.ir = PIPE_SHADER_IR_TGSI;
+
    state.tokens = ureg_finalize(ureg);
    if(!state.tokens)
       return NULL;
 
    if (so)
       state.stream_output = *so;
-   else
-      memset(&state.stream_output, 0, sizeof(state.stream_output));
 
    switch (ureg->processor) {
    case TGSI_PROCESSOR_VERTEX:
src/gallium/auxiliary/util/u_simple_shaders.c +36 -6

78 lines not on this page · raw message

src/gallium/auxiliary/util/u_tests.c +6 -1
index a94e5cc..3790011 100644
@@ -422,7 +422,12 @@ null_constant_buffer(struct pipe_context *ctx)
             "MOV OUT[0], CONST[0]\n"
             "END\n";
       struct tgsi_token tokens[1000];
-      struct pipe_shader_state state = {tokens};
+      struct pipe_shader_state state;
+
+      memset(&state, 0, sizeof(state));
+
+      state.ir = PIPE_SHADER_IR_TGSI;
+      state.tokens = tokens;
 
       if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
          puts("Can't compile a fragment shader.");
src/gallium/include/pipe/p_defines.h +10 -2
index a494715..29b0bfb 100644
@@ -701,12 +701,20 @@ enum pipe_shader_cap
 
 /**
  * Shader intermediate representation.
+ *
+ * Note that if the driver requests something other than TGSI, it must
+ * always be prepared to receive TGSI in addition to it's preferred IR.
+ * If the driver requests TGSI as it's preferred IR, it will *always*
+ * get TGSI.
+ *
+ * Note that PIPE_SHADER_IR_TGSI should be zero for backwards compat with
+ * state trackers that only understand TGSI.
  */
 enum pipe_shader_ir
 {
-   PIPE_SHADER_IR_TGSI,
+   PIPE_SHADER_IR_TGSI = 0,
    PIPE_SHADER_IR_LLVM,
-   PIPE_SHADER_IR_NATIVE
+   PIPE_SHADER_IR_NATIVE,
 };
 
 /**
src/gallium/include/pipe/p_state.h +18 -2
index 4bf8d46..50bfc4a 100644
@@ -211,10 +211,26 @@ struct pipe_stream_output_info
    } output[PIPE_MAX_SO_OUTPUTS];
 };
 
-
+/**
+ * The 'ir' parameter identifies whether the shader state contains TGSI
+ * tokens, etc.  If the driver returns 'PIPE_SHADER_IR_TGSI' for the
+ * 'PIPE_SHADER_CAP_PREFERRED_IR' shader param, the ir will *always* be
+ * 'PIPE_SHADER_IR_TGSI' and the tokens ptr will be valid.  If the driver
+ * requests a different 'pipe_shader_ir' type, then it must check the 'ir'
+ * enum to see if it is getting TGSI tokens or it's preferred IR.
+ *
+ * TODO pipe_compute_state should probably get similar treatment to handle
+ * multiple IR's in a cleaner way..
+ */
 struct pipe_shader_state
 {
-   const struct tgsi_token *tokens;
+   enum pipe_shader_ir ir;
+   /* TODO are anon unions allowed? */
+   union {
+      const struct tgsi_token *tokens;
+      void *llvm;
+      void *native;
+   };
    struct pipe_stream_output_info stream_output;
 };
 
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#3 lore raw

RFC 3/8 gallium: add NIR as a possible IR

In reply to Rob Clark
---
 src/gallium/include/pipe/p_defines.h | 1 +
 src/gallium/include/pipe/p_state.h   | 1 +
 2 files changed, 2 insertions(+)
src/gallium/include/pipe/p_defines.h +1 -0
index 29b0bfb..0dbc54c 100644
@@ -715,6 +715,7 @@ enum pipe_shader_ir
    PIPE_SHADER_IR_TGSI = 0,
    PIPE_SHADER_IR_LLVM,
    PIPE_SHADER_IR_NATIVE,
+   PIPE_SHADER_IR_NIR,
 };
 
 /**
src/gallium/include/pipe/p_state.h +1 -0
index 50bfc4a..54ca31f 100644
@@ -230,6 +230,7 @@ struct pipe_shader_state
       const struct tgsi_token *tokens;
       void *llvm;
       void *native;
+      void *nir;
    };
    struct pipe_stream_output_info stream_output;
 };
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#4 lore raw

RFC 4/8 mesa/st: add support for NIR as possible driver IR

In reply to Rob Clark
---
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 223 ++++++++++++++++++++++++++++-
 src/mesa/state_tracker/st_program.c        |  43 +++++-
 2 files changed, 260 insertions(+), 6 deletions(-)
src/mesa/state_tracker/st_glsl_to_tgsi.cpp +220 -3
index 06f510d..49f496f 100644
@@ -35,6 +35,9 @@
 #include "glsl_parser_extras.h"
 #include "ir_optimization.h"
 
+#include "nir.h"
+#include "glsl_to_nir.h"
+
 #include "main/errors.h"
 #include "main/shaderobj.h"
 #include "main/uniforms.h"
@@ -5486,9 +5489,9 @@ out:
  * generating Mesa IR.
  */
 static struct gl_program *
-get_mesa_program(struct gl_context *ctx,
-                 struct gl_shader_program *shader_program,
-                 struct gl_shader *shader)
+get_mesa_program_tgsi(struct gl_context *ctx,
+                      struct gl_shader_program *shader_program,
+                      struct gl_shader *shader)
 {
    glsl_to_tgsi_visitor* v;
    struct gl_program *prog;
@@ -5680,6 +5683,220 @@ get_mesa_program(struct gl_context *ctx,
    return prog;
 }
 
+/* TODO dup'd from brw_vec4_vistor.cpp..  what should we do? */
+static int
+type_size_vec4(const struct glsl_type *type)
+{
+   unsigned int i;
+   int size;
+
+   switch (type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      if (type->is_matrix()) {
+	 return type->matrix_columns;
+      } else {
+	 /* Regardless of size of vector, it gets a vec4. This is bad
+	  * packing for things like floats, but otherwise arrays become a
+	  * mess.  Hopefully a later pass over the code can pack scalars
+	  * down if appropriate.
+	  */
+	 return 1;
+      }
+   case GLSL_TYPE_ARRAY:
+      assert(type->length > 0);
+      return type_size_vec4(type->fields.array) * type->length;
+   case GLSL_TYPE_STRUCT:
+      size = 0;
+      for (i = 0; i < type->length; i++) {
+	 size += type_size_vec4(type->fields.structure[i].type);
+      }
+      return size;
+   case GLSL_TYPE_SUBROUTINE:
+      return 1;
+
+   case GLSL_TYPE_SAMPLER:
+      /* Samplers take up no register space, since they're baked in at
+       * link time.
+       */
+      return 0;
+   case GLSL_TYPE_ATOMIC_UINT:
+      return 0;
+   case GLSL_TYPE_IMAGE:
+//      return DIV_ROUND_UP(BRW_IMAGE_PARAM_SIZE, 4);
+   case GLSL_TYPE_VOID:
+   case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_ERROR:
+   case GLSL_TYPE_INTERFACE:
+      unreachable("not reached");
+   }
+
+   return 0;
+}
+
+static struct gl_program *
+get_mesa_program_nir(struct gl_context *ctx,
+                     struct gl_shader_program *shader_program,
+                     struct gl_shader *shader)
+{
+   struct gl_program *prog;
+   GLenum target = _mesa_shader_stage_to_program(shader->Stage);
+   struct gl_shader_compiler_options *options =
+         &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)];
+   struct pipe_screen *pscreen = ctx->st->pipe->screen;
+   unsigned ptarget = st_shader_stage_to_ptarget(shader->Stage);
+   nir_shader_compiler_options nir_options = {0};
+   nir_shader *nir;
+
+   /* TODO maybe options marked with 'XXX' should be PIPE_SHADER_CAP_x's */
+   nir_options.lower_ffma =
+      !pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED);
+   nir_options.lower_flrp = true;      // XXX
+   nir_options.lower_fpow = options->EmitNoPow;
+   nir_options.lower_fsat = options->EmitNoSat;
+   nir_options.lower_fsqrt =
+      !pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED);
+   nir_options.lower_negate = false;   // XXX
+   nir_options.lower_sub = false;      // XXX
+   nir_options.lower_scmp = true;      // XXX
+   nir_options.fdot_replicates = false;// XXX
+   nir_options.lower_ffract = true;    // XXX
+   nir_options.native_integers = ctx->Const.NativeIntegers;
+
+   validate_ir_tree(shader->ir);
+
+   prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name);
+   if (!prog)
+      return NULL;
+   prog->Parameters = _mesa_new_parameter_list();
+
+   _mesa_copy_linked_program_data(shader->Stage, shader_program, prog);
+   _mesa_generate_parameters_list_for_uniforms(shader_program, shader,
+                                               prog->Parameters);
+
+//   /* Remove reads from output registers. */
+//   lower_output_reads(shader->Stage, shader->ir);
+
+   /* Make a pass over the IR to add state references for any built-in
+    * uniforms that are used.  This has to be done now (during linking).
+    * Code generation doesn't happen until the first time this shader is
+    * used for rendering.  Waiting until then to generate the parameters is
+    * too late.  At that point, the values for the built-in uniforms won't
+    * get sent to the shader.
+    */
+   foreach_in_list(ir_instruction, node, shader->ir) {
+      ir_variable *var = node->as_variable();
+
+      if ((var == NULL) || (var->data.mode != ir_var_uniform) ||
+          (strncmp(var->name, "gl_", 3) != 0))
+         continue;
+
+      const ir_state_slot *const slots = var->get_state_slots();
+      assert(slots != NULL);
+
+      for (unsigned int i = 0; i < var->get_num_state_slots(); i++) {
+         _mesa_add_state_reference(prog->Parameters,
+                                   (gl_state_index *) slots[i].tokens);
+      }
+   }
+
+   if (ctx->_Shader->Flags & GLSL_DUMP) {
+      _mesa_log("\n");
+      _mesa_log("GLSL IR for linked %s program %d:\n",
+             _mesa_shader_stage_to_string(shader->Stage),
+             shader_program->Name);
+      _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
+      _mesa_log("\n\n");
+   }
+
+   prog->Instructions = NULL;
+   prog->NumInstructions = 0;
+
+   do_set_program_inouts(shader->ir, prog, shader->Stage);
+
+   prog->SamplersUsed = shader->active_samplers;
+   prog->ShadowSamplers = shader->shadow_samplers;
+   _mesa_update_shader_textures_used(shader_program, prog);
+
+   _mesa_reference_program(ctx, &shader->Program, prog);
+
+   nir = glsl_to_nir(shader_program, shader->Stage, &nir_options);
+   prog->nir = nir;
+
+   nir_validate_shader(nir);
+
+   if (shader->Stage == MESA_SHADER_GEOMETRY) {
+      nir_lower_gs_intrinsics(nir);
+      nir_validate_shader(nir);
+   }
+
+   nir_print_shader(nir, _mesa_get_log_file());
+
+   nir_lower_global_vars_to_local(nir);
+   nir_validate_shader(nir);
+
+   nir_lower_var_copies(nir);
+   nir_validate_shader(nir);
+
+   nir_assign_var_locations(&nir->inputs,
+                            &nir->num_inputs,
+                            type_size_vec4);
+   nir_assign_var_locations(&nir->outputs,
+                            &nir->num_outputs,
+                            type_size_vec4);
+   nir_assign_var_locations(&nir->uniforms,
+                            &nir->num_uniforms,
+                            type_size_vec4);
+
+   nir_lower_io(nir, nir_var_all, type_size_vec4);
+   nir_validate_shader(nir);
+
+
+   // XXX do we need anything else from brw_create_nir().. and what
+   // is best way to split up which things should be here vs driver?
+   // currently just trying to make the result here similar to what
+   // we get from tgsi_to_nir().. so lower_io, etc..
+
+   // XXX new flag, probably?
+   if (ctx->_Shader->Flags & GLSL_DUMP) {
+      _mesa_log("\n");
+      _mesa_log("NIR IR for linked %s program %d:\n",
+             _mesa_shader_stage_to_string(shader->Stage),
+             shader_program->Name);
+      nir_print_shader(nir, _mesa_get_log_file());
+      _mesa_log("\n\n");
+   }
+
+   /* This has to be done last.  Any operation the can cause
+    * prog->ParameterValues to get reallocated (e.g., anything that adds a
+    * program constant) has to happen before creating this linkage.
+    */
+   _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters);
+
+   return prog;
+}
+
+static struct gl_program *
+get_mesa_program(struct gl_context *ctx,
+                 struct gl_shader_program *shader_program,
+                 struct gl_shader *shader)
+{
+   struct pipe_screen *pscreen = ctx->st->pipe->screen;
+   unsigned ptarget = st_shader_stage_to_ptarget(shader->Stage);
+   enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
+      pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_PREFERRED_IR);
+   /* TODO: only do this for VERTEX stage for now: */
+   if ((preferred_ir == PIPE_SHADER_IR_NIR) &&
+       (shader->Type == GL_VERTEX_SHADER)) {
+      return get_mesa_program_nir(ctx, shader_program, shader);
+   } else {
+      return get_mesa_program_tgsi(ctx, shader_program, shader);
+   }
+}
+
+
 extern "C" {
 
 static void
src/mesa/state_tracker/st_program.c +40 -3

70 lines not on this page · raw message

Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#5 lore raw

RFC 5/8 freedreno/ir3: drop tokens arg

In reply to Rob Clark

We can get the tokens from variant->shader so drop the extra arg. This will make things easier to support either getting TGSI or NIR as input.

---
 src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c +6 -8
index 8c9234b..b4e5483 100644
@@ -126,8 +126,8 @@ struct ir3_compile {
 static struct ir3_instruction * create_immed(struct ir3_block *block, uint32_t val);
 static struct ir3_block * get_block(struct ir3_compile *ctx, nir_block *nblock);
 
-static struct nir_shader *to_nir(struct ir3_compile *ctx,
-		const struct tgsi_token *tokens, struct ir3_shader_variant *so)
+static struct nir_shader *
+to_nir(struct ir3_compile *ctx, struct ir3_shader_variant *so)
 {
 	static const nir_shader_compiler_options options = {
 			.lower_fpow = true,
@@ -164,7 +164,7 @@ static struct nir_shader *to_nir(struct ir3_compile *ctx,
 		tex_options.lower_txp = (1 << GLSL_SAMPLER_DIM_3D);
 	}
 
-	struct nir_shader *s = tgsi_to_nir(tokens, &options);
+	struct nir_shader *s = tgsi_to_nir(so->shader->tokens, &options);
 
 	if (fd_mesa_debug & FD_DBG_OPTMSGS) {
 		debug_printf("----------------------\n");
@@ -214,9 +214,7 @@ static struct nir_shader *to_nir(struct ir3_compile *ctx,
 }
 
 static struct ir3_compile *
-compile_init(struct ir3_compiler *compiler,
-		struct ir3_shader_variant *so,
-		const struct tgsi_token *tokens)
+compile_init(struct ir3_compiler *compiler, struct ir3_shader_variant *so)
 {
 	struct ir3_compile *ctx = rzalloc(NULL, struct ir3_compile);
 
@@ -245,7 +243,7 @@ compile_init(struct ir3_compiler *compiler,
 	ctx->block_ht = _mesa_hash_table_create(ctx,
 			_mesa_hash_pointer, _mesa_key_pointer_equal);
 
-	ctx->s = to_nir(ctx, tokens, so);
+	ctx->s = to_nir(ctx, so);
 
 	so->first_driver_param = so->first_immediate = ctx->s->num_uniforms;
 
@@ -2432,7 +2430,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
 
 	assert(!so->ir);
 
-	ctx = compile_init(compiler, so, so->shader->tokens);
+	ctx = compile_init(compiler, so);
 	if (!ctx) {
 		DBG("INIT failed!");
 		ret = -1;
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#6 lore raw

RFC 6/8 freedreno/ir3: add support for NIR as preferred IR

In reply to Rob Clark

For now under debug flag, since only suitable for debugging/testing.

---
 src/gallium/drivers/freedreno/freedreno_screen.c   |  5 +++-
 src/gallium/drivers/freedreno/freedreno_util.h     |  1 +
 .../drivers/freedreno/ir3/ir3_compiler_nir.c       | 15 ++++++++++-
 src/gallium/drivers/freedreno/ir3/ir3_shader.c     | 30 +++++++++++++++++++---
 src/gallium/drivers/freedreno/ir3/ir3_shader.h     |  3 +++
 5 files changed, 48 insertions(+), 6 deletions(-)
src/gallium/drivers/freedreno/freedreno_screen.c +4 -1
index b64f78c..30def8e 100644
@@ -71,6 +71,7 @@ static const struct debug_named_value debug_options[] = {
 		{"glsl120",   FD_DBG_GLSL120,"Temporary flag to force GLSL 1.20 (rather than 1.30) on a3xx+"},
 		{"shaderdb",  FD_DBG_SHADERDB, "Enable shaderdb output"},
 		{"flush",     FD_DBG_FLUSH,  "Force flush after every draw"},
+		{"nir",       FD_DBG_NIR,    "Prefer NIR as native IR"},
 		DEBUG_NAMED_VALUE_END
 };
 
@@ -398,7 +399,7 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
 	case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
 	case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
 	case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
-        case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
+	case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
 		return 0;
 	case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
 		return 1;
@@ -410,6 +411,8 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
 	case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
 		return 16;
 	case PIPE_SHADER_CAP_PREFERRED_IR:
+		if ((fd_mesa_debug & FD_DBG_NIR) && is_ir3(screen))
+			return PIPE_SHADER_IR_NIR;
 		return PIPE_SHADER_IR_TGSI;
 	}
 	debug_printf("unknown shader param %d\n", param);
src/gallium/drivers/freedreno/freedreno_util.h +1 -0
index 0d2418e..56d3235 100644
@@ -73,6 +73,7 @@ enum adreno_stencil_op fd_stencil_op(unsigned op);
 #define FD_DBG_GLSL120  0x0400
 #define FD_DBG_SHADERDB 0x0800
 #define FD_DBG_FLUSH    0x1000
+#define FD_DBG_NIR      0x2000
 
 extern int fd_mesa_debug;
 extern bool fd_binning_enabled;
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c +14 -1
index b4e5483..5a53e32 100644
@@ -164,7 +164,14 @@ to_nir(struct ir3_compile *ctx, struct ir3_shader_variant *so)
 		tex_options.lower_txp = (1 << GLSL_SAMPLER_DIM_3D);
 	}
 
-	struct nir_shader *s = tgsi_to_nir(so->shader->tokens, &options);
+	struct nir_shader *s;
+
+	if (so->shader->nir) {
+		// XXX need nir_clone() here..
+		s = so->shader->nir;
+	} else {
+		s = tgsi_to_nir(so->shader->tokens, &options);
+	}
 
 	if (fd_mesa_debug & FD_DBG_OPTMSGS) {
 		debug_printf("----------------------\n");
@@ -292,6 +299,12 @@ compile_error(struct ir3_compile *ctx, const char *format, ...)
 static void
 compile_free(struct ir3_compile *ctx)
 {
+	/* TODO .. probably need a ralloc_free(ctx->s) here, at least
+	 * for the tgsi_to_nir case.. right now in the case we get
+	 * NIR directly, we want to skip this since the nir_shader isn't
+	 * getting cloned..  and/or if it was we might be wanting to
+	 * free it in ir3_shader_destroy()??
+	 */
 	ralloc_free(ctx);
 }
 
src/gallium/drivers/freedreno/ir3/ir3_shader.c +26 -4
index 7b56533..0cbf8fe 100644
@@ -39,6 +39,7 @@
 
 #include "ir3_shader.h"
 #include "ir3_compiler.h"
+#include "ir3_nir.h"
 
 
 static void
@@ -188,9 +189,15 @@ create_variant(struct ir3_shader *shader, struct ir3_shader_key key)
 	v->type = shader->type;
 
 	if (fd_mesa_debug & FD_DBG_DISASM) {
-		DBG("dump tgsi: type=%d, k={bp=%u,cts=%u,hp=%u}", shader->type,
-			key.binning_pass, key.color_two_side, key.half_precision);
-		tgsi_dump(shader->tokens, 0);
+		if (shader->nir) {
+			DBG("dump nir: type=%d, k={bp=%u,cts=%u,hp=%u}", shader->type,
+					key.binning_pass, key.color_two_side, key.half_precision);
+			nir_print_shader(shader->nir, stderr);
+		} else {
+			DBG("dump tgsi: type=%d, k={bp=%u,cts=%u,hp=%u}", shader->type,
+					key.binning_pass, key.color_two_side, key.half_precision);
+			tgsi_dump(shader->tokens, 0);
+		}
 	}
 
 	ret = ir3_compile_shader_nir(shader->compiler, v);
@@ -267,7 +274,9 @@ ir3_shader_destroy(struct ir3_shader *shader)
 		v = v->next;
 		delete_variant(t);
 	}
+
 	free((void *)shader->tokens);
+	/* XXX ralloc_free(shader->nir); */
 	free(shader);
 }
 
@@ -281,7 +290,20 @@ ir3_shader_create(struct pipe_context *pctx,
 	shader->id = ++shader->compiler->shader_count;
 	shader->pctx = pctx;
 	shader->type = type;
-	shader->tokens = tgsi_dup_tokens(cso->tokens);
+	if (cso->ir == PIPE_SHADER_IR_NIR) {
+		/* TODO might need nir_clone() here.. Depends a bit on how we
+		 * define the lifecycle of cso->nir.  If we could assume that it
+		 * always sticks around until the cso is destroyed, then we'd
+		 * only need to clone in to_nir() (for the variant specific
+		 * lowering), rather than both here and to_nir().  This is a bit
+		 * different from the lifetime of cso->tokens which sometimes
+		 * but not always goes away after the pipe->pipe_create_xyz_state()
+		 * call (which is unfortunate, and maybe worth fixing).
+		 */
+		shader->nir = cso->nir;
+	} else {
+		shader->tokens = tgsi_dup_tokens(cso->tokens);
+	}
 	shader->stream_output = cso->stream_output;
 	if (fd_mesa_debug & FD_DBG_SHADERDB) {
 		/* if shader-db run, create a standard variant immediately
src/gallium/drivers/freedreno/ir3/ir3_shader.h +3 -0
index 7e2c27d..9ef3277 100644
@@ -220,6 +220,8 @@ struct ir3_shader_variant {
 	struct ir3_shader *shader;
 };
 
+typedef struct nir_shader nir_shader;
+
 struct ir3_shader {
 	enum shader_t type;
 
@@ -230,6 +232,7 @@ struct ir3_shader {
 	struct ir3_compiler *compiler;
 
 	struct pipe_context *pctx;
+	nir_shader *nir;
 	const struct tgsi_token *tokens;
 	struct pipe_stream_output_info stream_output;
 
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#7 lore raw

RFC 7/8 freedreno/ir3: fix const_index handling for uniforms

In reply to Rob Clark

When coming directly from glsl_to_nir (rather than via TGSI where information about, for example, mat4's is lost), both const_index fields will be used (vs. tgsi_to_nir where the 2nd is always zero).

For example:

decl_var uniform INTERP_QUALIFIER_NONE mat4 ModelViewProjectionMatrix (0, 0) decl_var uniform INTERP_QUALIFIER_NONE mat4 NormalMatrix (4, 4)
...

	vec4 ssa_54 = intrinsic load_uniform () () (4, 0)	/* NormalMatrix */
	vec4 ssa_56 = intrinsic load_uniform () () (4, 1)	/* NormalMatrix */

vs:

decl_var uniform INTERP_QUALIFIER_NONE vec4[8] uniform_0 (0, 0)
...

	vec4 ssa_54 = intrinsic load_uniform () () (4, 0)
	vec4 ssa_56 = intrinsic load_uniform () () (5, 0)
---
 src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c +4 -1
index 5a53e32..2b9a841 100644
@@ -1377,7 +1377,10 @@ emit_intrinisic(struct ir3_compile *ctx, nir_intrinsic_instr *intr)
 	const nir_intrinsic_info *info = &nir_intrinsic_infos[intr->intrinsic];
 	struct ir3_instruction **dst, **src;
 	struct ir3_block *b = ctx->block;
-	unsigned idx = intr->const_index[0];
+	unsigned idx = 0;
+
+	for (unsigned i = 0; i < nir_intrinsic_infos[intr->intrinsic].num_indices; i++)
+		idx += intr->const_index[i];
 
 	if (info->has_dest) {
 		dst = get_dst(ctx, &intr->dest, intr->num_components);
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
author
#8 lore raw

RFC 8/8 freedreno/ir3: hack for mismatch on varying slots for glsl->tgsi->nir vs glsl->nir

In reply to Rob Clark

Complete hack just for debugging. It isn't intended that mixing and matching glsl->tgsi->nir vs glsl->nir between shader stages should actually work.

---
 src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c | 6 ++++++
 1 file changed, 6 insertions(+)
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c +6 -0
index 2b9a841..317ed79 100644
@@ -2232,6 +2232,12 @@ setup_output(struct ir3_compile *ctx, nir_variable *out)
 	unsigned slot = out->data.location;
 	unsigned comp = 0;
 
+	// XXX temporary hack for NIR vs and TGSI fs.. since there is
+	// some disagreement about varying slots..
+	if (ctx->so->shader->nir)
+		if (slot >= VARYING_SLOT_VAR0)
+			slot += 9;
+
 	DBG("; out: slot=%u, len=%ux%u, drvloc=%u",
 			slot, array_len, ncomp, n);
 
Signature · 6 lines
2.5.0

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#9 lore raw
In reply to Rob Clark
Quoted 5 lines · Rob Clark

Also, there is some trivial shader variant handling in mesa st which would have to be ported to NIR. Or, perhaps, just somehow expose the shader key to the driver. (Currently most drivers are doing much more variant handling within the driver, and having two levels of variants does seem a bit silly.)

With Marek's latest series, the are no more variants in st/mesa (well, except for glDrawPixels/glBitmap-related shaders) provided that your driver exposes the right caps.

-ilia
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel