[Mesa-dev] [PATCH 06/14] st/glsl_to_nir: split the st_glsl_to_nir() function in two

Timothy Arceri tarceri at itsqueeze.com
Tue Nov 21 03:37:27 UTC 2017


We want to be able to generate NIR then apply NIR optimisations.
Once the optimisations are done we can then apply the new post opt
function which assigns uniforms etc based on the optimised IR.
---
 src/mesa/state_tracker/st_glsl_to_nir.cpp | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp
index 8c22bde835..9a27f4ceea 100644
--- a/src/mesa/state_tracker/st_glsl_to_nir.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp
@@ -242,44 +242,53 @@ st_nir_assign_uniform_locations(struct gl_program *prog,
 
       uniform->data.driver_location = loc;
 
       max = MAX2(max, loc + type_size(uniform->type));
    }
    *size = max;
 }
 
 extern "C" {
 
-/* First half of converting glsl_to_nir.. this leaves things in a pre-
+/* First third 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)
 {
    struct pipe_screen *pscreen = st->pipe->screen;
    enum pipe_shader_type ptarget = pipe_shader_type_from_mesa(stage);
    const nir_shader_compiler_options *options;
-   nir_shader *nir;
 
    assert(pscreen->get_compiler_options);   /* drivers using NIR must implement this */
 
    options = (const nir_shader_compiler_options *)
       pscreen->get_compiler_options(pscreen, PIPE_SHADER_IR_NIR, ptarget);
    assert(options);
 
    if (prog->nir)
       return prog->nir;
 
-   nir = glsl_to_nir(shader_program, stage, options);
+   return glsl_to_nir(shader_program, stage, options);
+}
+
+/* Second third of converting glsl_to_nir. This creates uniforms, gathers
+ * info on varyings, etc after NIR link time opts have been applied.
+ */
+static void
+st_glsl_to_nir_post_opts(struct st_context *st, struct gl_program *prog,
+                         struct gl_shader_program *shader_program)
+{
+   nir_shader *nir = prog->nir;
 
    /* 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.
     */
    nir_foreach_variable(var, &nir->uniforms) {
       if (strncmp(var->name, "gl_", 3) == 0) {
@@ -306,21 +315,21 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
    _mesa_associate_uniform_storage(st->ctx, shader_program, prog, true);
 
    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);
 
    /* fragment shaders may need : */
-   if (stage == MESA_SHADER_FRAGMENT) {
+   if (prog->info.stage == MESA_SHADER_FRAGMENT) {
       static const gl_state_index wposTransformState[STATE_LENGTH] = {
          STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM
       };
       nir_lower_wpos_ytransform_options wpos_options = { { 0 } };
       struct pipe_screen *pscreen = st->pipe->screen;
 
       memcpy(wpos_options.state_tokens, wposTransformState,
              sizeof(wpos_options.state_tokens));
       wpos_options.fs_coord_origin_upper_left =
          pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT);
@@ -343,29 +352,25 @@ st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
    prog->info = nir->info;
 
    st_set_prog_affected_state_flags(prog);
 
    NIR_PASS_V(nir, st_nir_lower_builtin);
    NIR_PASS_V(nir, nir_lower_atomics, shader_program);
 
    if (st->ctx->_Shader->Flags & GLSL_DUMP) {
       _mesa_log("\n");
       _mesa_log("NIR IR for linked %s program %d:\n",
-             _mesa_shader_stage_to_string(stage),
+             _mesa_shader_stage_to_string(prog->info.stage),
              shader_program->Name);
       nir_print_shader(nir, _mesa_get_log_file());
       _mesa_log("\n\n");
    }
-
-   prog->nir = nir;
-
-   return nir;
 }
 
 /* TODO any better helper somewhere to sort a list? */
 
 static void
 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
 {
    nir_foreach_variable(var, var_list) {
       if (var->data.location > new_var->data.location) {
          exec_node_insert_node_before(&var->node, &new_var->node);
@@ -380,21 +385,21 @@ sort_varyings(struct exec_list *var_list)
 {
    struct exec_list new_list;
    exec_list_make_empty(&new_list);
    nir_foreach_variable_safe(var, var_list) {
       exec_node_remove(&var->node);
       insert_sorted(&new_list, var);
    }
    exec_list_move_nodes_to(&new_list, var_list);
 }
 
-/* Second half of preparing nir from glsl, which happens after shader
+/* Last third of preparing nir from glsl, which happens after shader
  * variant lowering.
  */
 void
 st_finalize_nir(struct st_context *st, struct gl_program *prog,
                 struct gl_shader_program *shader_program, nir_shader *nir)
 {
    struct pipe_screen *screen = st->pipe->screen;
 
    NIR_PASS_V(nir, nir_split_var_copies);
    NIR_PASS_V(nir, nir_lower_var_copies);
@@ -503,41 +508,46 @@ st_nir_get_mesa_program(struct gl_context *ctx,
       _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
       _mesa_log("\n\n");
    }
 
    prog->ExternalSamplersUsed = gl_external_samplers(prog);
    _mesa_update_shader_textures_used(shader_program, prog);
 
    nir_shader *nir = st_glsl_to_nir(st, prog, shader_program, shader->Stage);
 
    set_st_program(prog, shader_program, nir);
+   prog->nir = nir;
 
    return nir;
 }
 
 bool
 st_link_nir(struct gl_context *ctx,
             struct gl_shader_program *shader_program)
 {
+   struct st_context *st = st_context(ctx);
+
    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);
    }
 
    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
       struct gl_linked_shader *shader = shader_program->_LinkedShaders[i];
       if (shader == NULL)
          continue;
 
+      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;
       }
    }
 
    return true;
-- 
2.14.3



More information about the mesa-dev mailing list