Mesa (master): i965: Don't use _mesa_ir_link_shader to do our dirty work

Ian Romanick idr at kemper.freedesktop.org
Wed Jan 11 20:52:25 UTC 2012


Module: Mesa
Branch: master
Commit: 1c177452005a0366db01629d875da553f7949ddd
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1c177452005a0366db01629d875da553f7949ddd

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Fri Jan  6 16:26:49 2012 -0800

i965: Don't use _mesa_ir_link_shader to do our dirty work

Instead, do the uniform setting and input / output mapping directly in
brw_link_shader.  Hurray for not generating Mesa IR!  However, once
the i965 driver stops calling _mesa_ir_link_shader, UsesClipDistance
and UsesKill are no longer set.

Ideally gen6_upload_vs_push_constants should use the
gl_shader_program, but I don't see a way to propagate the information
there.  The other alternative, since this is the only usage, is to
move gl_vertex_program::UsesClipDistance to brw_vertex_program.

The compile (and precompile) stages use UsesKill to determine the
cache key for the shader.  This is then used to determine whether or
not to compile the shader.  Calculating this data during compilation
is too late.

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
Acked-by: Kenneth Graunke <kenneth at whitecape.org>
Acked-by: Eric Anholt <eric at anholt.net>

---

 src/mesa/drivers/dri/i965/brw_shader.cpp |   92 +++++++++++++++++++++++++++--
 1 files changed, 85 insertions(+), 7 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index 1845c3d..ef0f09d 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -77,22 +77,63 @@ brw_shader_precompile(struct gl_context *ctx, struct gl_shader_program *prog)
 }
 
 GLboolean
-brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
+brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg)
 {
    struct brw_context *brw = brw_context(ctx);
    struct intel_context *intel = &brw->intel;
    unsigned int stage;
 
-   if (!_mesa_ir_link_shader(ctx, prog))
-      return false;
-
-   for (stage = 0; stage < ARRAY_SIZE(prog->_LinkedShaders); stage++) {
+   for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) {
       struct brw_shader *shader =
-	 (struct brw_shader *)prog->_LinkedShaders[stage];
+	 (struct brw_shader *)shProg->_LinkedShaders[stage];
+      static const GLenum targets[] = {
+	 GL_VERTEX_PROGRAM_ARB,
+	 GL_FRAGMENT_PROGRAM_ARB,
+	 GL_GEOMETRY_PROGRAM_NV
+      };
 
       if (!shader)
 	 continue;
 
+      struct gl_program *prog =
+	 ctx->Driver.NewProgram(ctx, targets[stage], shader->base.Name);
+      if (!prog)
+	return NULL;
+      prog->Parameters = _mesa_new_parameter_list();
+
+      _mesa_generate_parameters_list_for_uniforms(shProg, &shader->base,
+						  prog->Parameters);
+
+      if (stage == 0) {
+	 struct gl_vertex_program *vp = (struct gl_vertex_program *) prog;
+	 vp->UsesClipDistance = shProg->Vert.UsesClipDistance;
+      }
+
+      if (stage == 1) {
+	 class uses_kill_visitor : public ir_hierarchical_visitor {
+	 public:
+	    uses_kill_visitor() : uses_kill(false)
+	    {
+	       /* empty */
+	    }
+
+	    virtual ir_visitor_status visit_enter(class ir_discard *ir)
+	    {
+	       this->uses_kill = true;
+	       return visit_stop;
+	    }
+
+	    bool uses_kill;
+	 };
+
+	 uses_kill_visitor v;
+
+	 v.run(shader->base.ir);
+
+	 struct gl_fragment_program *fp = (struct gl_fragment_program *) prog;
+	 fp->UsesKill = v.uses_kill;
+      }
+
       void *mem_ctx = ralloc_context(NULL);
       bool progress;
 
@@ -147,13 +188,50 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
 	   || progress;
       } while (progress);
 
+      /* 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 informs won't
+       * get sent to the shader.
+       */
+      foreach_list(node, shader->ir) {
+	 ir_variable *var = ((ir_instruction *) node)->as_variable();
+
+	 if ((var == NULL) || (var->mode != ir_var_uniform)
+	     || (strncmp(var->name, "gl_", 3) != 0))
+	    continue;
+
+	 const ir_state_slot *const slots = var->state_slots;
+	 assert(var->state_slots != NULL);
+
+	 for (unsigned int i = 0; i < var->num_state_slots; i++) {
+	    _mesa_add_state_reference(prog->Parameters,
+				      (gl_state_index *) slots[i].tokens);
+	 }
+      }
+
       validate_ir_tree(shader->ir);
 
       reparent_ir(shader->ir, shader->ir);
       ralloc_free(mem_ctx);
+
+      do_set_program_inouts(shader->ir, prog,
+			    shader->base.Type == GL_FRAGMENT_SHADER);
+
+      prog->SamplersUsed = shader->base.active_samplers;
+      _mesa_update_shader_textures_used(shProg, prog);
+
+      _mesa_reference_program(ctx, &shader->base.Program, prog);
+
+      /* This has to be done last.  Any operation that 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, shProg, prog->Parameters);
    }
 
-   if (!brw_shader_precompile(ctx, prog))
+   if (!brw_shader_precompile(ctx, shProg))
       return false;
 
    return true;




More information about the mesa-commit mailing list