diff options
author | Ian Romanick <[email protected]> | 2012-01-06 16:26:49 -0800 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2012-01-11 12:51:24 -0800 |
commit | 1c177452005a0366db01629d875da553f7949ddd (patch) | |
tree | 386f2547dbd9698c9fc1411fdffc2ae860d98056 /src/mesa/drivers/dri/i965/brw_shader.cpp | |
parent | efdc8bf1894790a85c118881395a998cbae34c1a (diff) |
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 <[email protected]>
Acked-by: Kenneth Graunke <[email protected]>
Acked-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_shader.cpp')
-rw-r--r-- | 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 1845c3d7618..ef0f09d9ebb 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; |