[Mesa-dev] [PATCH 16/16] mesa/st: add support for NIR as possible driver IR

Emil Velikov emil.l.velikov at gmail.com
Tue Apr 5 17:37:36 UTC 2016


Hi Rob,

Not sure if there's a series that split things up ? I believe my
comments will be applicable either way.

On 26 March 2016 at 21:02, Rob Clark <robdclark at gmail.com> wrote:
> From: Rob Clark <robclark at freedesktop.org>
>
> Signed-off-by: Rob Clark <robclark at freedesktop.org>
> ---
>  src/compiler/nir/nir.h                             |   2 +
>  .../drivers/freedreno/ir3/ir3_compiler_nir.c       |   8 +
>  src/mesa/Makefile.sources                          |   1 +
>  src/mesa/state_tracker/st_glsl_to_nir.cpp          | 425 +++++++++++++++++++++
>  src/mesa/state_tracker/st_glsl_to_tgsi.cpp         |  40 +-
>  src/mesa/state_tracker/st_glsl_to_tgsi.h           |   5 +
>  src/mesa/state_tracker/st_nir.h                    |  32 ++
>  src/mesa/state_tracker/st_program.c                | 148 ++++++-
>  src/mesa/state_tracker/st_program.h                |   6 +
>  9 files changed, 643 insertions(+), 24 deletions(-)
>  create mode 100644 src/mesa/state_tracker/st_glsl_to_nir.cpp
>

> --- a/src/mesa/Makefile.sources
> +++ b/src/mesa/Makefile.sources
> @@ -487,6 +487,7 @@ STATETRACKER_FILES = \
>         state_tracker/st_gen_mipmap.c \
>         state_tracker/st_gen_mipmap.h \
>         state_tracker/st_gl_api.h \
> +       state_tracker/st_glsl_to_nir.cpp \
Add this to the new list (variable) as mentioned in earlier patch.


> --- /dev/null
> +++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp

> +extern "C" {
> +
> +/* First half of converting glsl_to_nir.. this leaves things in a pre-
> + * nir_lower_io state, so that shader variants can more easily insert/
> + * replace variables, etc.
> + */
> +nir_shader *
> +st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
> +               struct gl_shader_program *shader_program,
> +               gl_shader_stage stage)
Personally I'd annotate the 2-3 functions as extern "C" individually,
but that's just me ;-)





> +void
> +st_finalize_nir(struct st_context *st, struct gl_program *prog, nir_shader *nir)

> +struct gl_program *
> +st_nir_get_mesa_program(struct gl_context *ctx,
> +                        struct gl_shader_program *shader_program,
> +                        struct gl_shader *shader)



> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index fa03c16..631ce3c 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -53,6 +53,7 @@
>  #include "st_mesa_to_tgsi.h"
>  #include "st_format.h"
>  #include "st_glsl_types.h"
> +#include "st_nir.h"
>
>
>  #define PROGRAM_ANY_CONST ((1 << PROGRAM_STATE_VAR) |    \
> @@ -6376,9 +6377,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;
> @@ -6586,6 +6587,29 @@ get_mesa_program(struct gl_context *ctx,
>     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);
> +   if (preferred_ir == PIPE_SHADER_IR_NIR) {
> +      /* TODO only for GLSL VS/FS for now: */
> +      switch (shader->Type) {
> +      case GL_VERTEX_SHADER:
> +      case GL_FRAGMENT_SHADER:
> +         return st_nir_get_mesa_program(ctx, shader_program, shader);
> +      default:
> +         break;
> +      }
> +   }
> +   return get_mesa_program_tgsi(ctx, shader_program, shader);
> +}
> +
> +
>  extern "C" {
>
>  static void
> @@ -6788,9 +6812,17 @@ st_translate_stream_output_info(glsl_to_tgsi_visitor *glsl_to_tgsi,
>                                  const GLuint outputMapping[],
>                                  struct pipe_stream_output_info *so)
>  {
> -   unsigned i;
>     struct gl_transform_feedback_info *info =
>        &glsl_to_tgsi->shader_program->LinkedTransformFeedback;
> +   st_translate_stream_output_info2(info, outputMapping, so);
> +}
> +
> +void
> +st_translate_stream_output_info2(struct gl_transform_feedback_info *info,
> +                                const GLuint outputMapping[],
> +                                struct pipe_stream_output_info *so)
> +{
> +   unsigned i;
>
>     for (i = 0; i < info->NumOutputs; i++) {
>        so->output[i].register_index =
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.h b/src/mesa/state_tracker/st_glsl_to_tgsi.h
> index 729295b..1986025 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.h
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.h
> @@ -63,6 +63,11 @@ st_translate_stream_output_info(struct glsl_to_tgsi_visitor *glsl_to_tgsi,
>                                  const GLuint outputMapping[],
>                                  struct pipe_stream_output_info *so);
>
> +void
> +st_translate_stream_output_info2(struct gl_transform_feedback_info *info,
> +                                const GLuint outputMapping[],
> +                                struct pipe_stream_output_info *so);
> +
>  extern const unsigned _mesa_sysval_to_semantic[SYSTEM_VALUE_MAX];
>
>  #ifdef __cplusplus
> diff --git a/src/mesa/state_tracker/st_nir.h b/src/mesa/state_tracker/st_nir.h
> index 1c07c4c..8c8a1d5 100644
> --- a/src/mesa/state_tracker/st_nir.h
> +++ b/src/mesa/state_tracker/st_nir.h
> @@ -23,6 +23,38 @@
>
>  #pragma once
>
> +#include "st_context.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
>  typedef struct nir_shader nir_shader;
>
>  void st_nir_lower_builtin(nir_shader *shader);
> +
> +#include "compiler/shader_enums.h"
Please move any header inclusions before the extern C guard/wrapper.

> +
> +nir_shader * st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
> +                            struct gl_shader_program *shader_program,
> +                            gl_shader_stage stage);
> +
> +void st_finalize_nir(struct st_context *st, struct gl_program *prog, nir_shader *nir);
> +
> +struct gl_program *
> +st_nir_get_mesa_program(struct gl_context *ctx,
> +                        struct gl_shader_program *shader_program,
> +                        struct gl_shader *shader);
> +
> +
> +#define OPT(nir, pass, ...) ({                             \
> +   bool this_progress = false;                             \
> +   NIR_PASS(this_progress, nir, pass, ##__VA_ARGS__);      \
> +   this_progress;                                          \
> +})
Not 100% sure but I believe the above usage to be GCC extension.
Although we nuked non gcc/clang, I'm not sure how MSVC will cope (will
it even bother if we're not building any code that uses the macro).
>From memory there were a handful of similar hunks elsewhere in nir
(related) code.

> +
> +#define OPT_V(nir, pass, ...) NIR_PASS_V(nir, pass, ##__VA_ARGS__)
> +
Please add namespace for the OPT macros - ST_NIR_OPT, just NIR_OPT or otherwise.

> +#ifdef __cplusplus
> +}
> +#endif
> diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
> index 80dcfd8..048fe4b 100644
> --- a/src/mesa/state_tracker/st_program.c
> +++ b/src/mesa/state_tracker/st_program.c
> @@ -38,6 +38,8 @@
>  #include "program/prog_print.h"
>  #include "program/programopt.h"
>
> +#include "compiler/nir/nir.h"
> +
>  #include "pipe/p_context.h"
>  #include "pipe/p_defines.h"
>  #include "pipe/p_shader_tokens.h"
> @@ -53,6 +55,7 @@
>  #include "st_context.h"
>  #include "st_program.h"
>  #include "st_mesa_to_tgsi.h"
> +#include "st_nir.h"
>  #include "cso_cache/cso_context.h"
>
>
> @@ -69,10 +72,10 @@ delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
>
>     if (vpv->draw_shader)
>        draw_delete_vertex_shader( st->draw, vpv->draw_shader );
> -
> -   if (vpv->tgsi.tokens)
> +
> +   if (((vpv->tgsi.type == PIPE_SHADER_IR_TGSI)) && vpv->tgsi.tokens)
>        ureg_free_tokens(vpv->tgsi.tokens);
> -
> +
>     free( vpv );
>  }
>
> @@ -95,7 +98,7 @@ st_release_vp_variants( struct st_context *st,
>
>     stvp->variants = NULL;
>
> -   if (stvp->tgsi.tokens) {
> +   if ((stvp->tgsi.type == PIPE_SHADER_IR_TGSI) && stvp->tgsi.tokens) {
>        tgsi_free_tokens(stvp->tgsi.tokens);
>        stvp->tgsi.tokens = NULL;
>     }
> @@ -132,7 +135,7 @@ st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp)
>
>     stfp->variants = NULL;
>
> -   if (stfp->tgsi.tokens) {
> +   if ((stfp->tgsi.type == PIPE_SHADER_IR_TGSI) && stfp->tgsi.tokens) {
>        ureg_free_tokens(stfp->tgsi.tokens);
>        stfp->tgsi.tokens = NULL;
>     }
> @@ -355,9 +358,23 @@ st_translate_vertex_program(struct st_context *st,
>     output_semantic_name[num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
>     output_semantic_index[num_outputs] = 0;
>
> -   if (!stvp->glsl_to_tgsi)
> +   if (!stvp->glsl_to_tgsi && !stvp->shader_program)
>        _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
>

> +   if (stvp->shader_program) {
> +      nir_shader *nir = st_glsl_to_nir(st, &stvp->Base.Base,
> +                                       stvp->shader_program,
> +                                       MESA_SHADER_VERTEX);
> +
> +      stvp->tgsi.type = PIPE_SHADER_IR_NIR;
> +      stvp->tgsi.ir.nir = nir;
> +
> +      st_translate_stream_output_info2(&stvp->shader_program->LinkedTransformFeedback,
> +                                       stvp->result_to_output,
> +                                       &stvp->tgsi.stream_output);
> +      return true;
> +   }
> +

In general you one might get away with adding a few stubs for
st_glsl_to_nir/nir_shader_clone when building without NIR, to avoid
polluting the code with #ifdef. Not too sure though...

> +   if (stvp->tgsi.type == PIPE_SHADER_IR_NIR) {
> +      vpv->tgsi.type = PIPE_SHADER_IR_NIR;
> +      vpv->tgsi.ir.nir = nir_shader_clone(NULL, stvp->tgsi.ir.nir);
> +      if (key->clamp_color)
> +         OPT_V(vpv->tgsi.ir.nir, nir_lower_clamp_color_outputs);
> +      if (key->passthrough_edgeflags)
> +         OPT_V(vpv->tgsi.ir.nir, nir_lower_passthrough_edgeflags);
> +
> +      st_finalize_nir(st, &stvp->Base.Base, vpv->tgsi.ir.nir);
> +
> +      vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
> +      /* driver takes ownership of IR: */
> +      vpv->tgsi.ir.nir = NULL;
> +      return vpv;
> +   }
> +
Esp. for hunks like this one.

-Emil


More information about the mesa-dev mailing list