aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/brw_shader.cpp
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2012-01-06 16:26:49 -0800
committerIan Romanick <[email protected]>2012-01-11 12:51:24 -0800
commit1c177452005a0366db01629d875da553f7949ddd (patch)
tree386f2547dbd9698c9fc1411fdffc2ae860d98056 /src/mesa/drivers/dri/i965/brw_shader.cpp
parentefdc8bf1894790a85c118881395a998cbae34c1a (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.cpp92
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;