[Mesa-dev] [PATCH 5/7] glsl: rework the way varying location are assigned to prepare varying packing
Vincent Lejeune
vljn at ovi.com
Thu Feb 16 13:03:11 PST 2012
---
src/glsl/linker.cpp | 125 ++++++++++++++++++++++++++++++---------------------
1 files changed, 74 insertions(+), 51 deletions(-)
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 8e690ac..4a5e3bb 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1813,6 +1813,36 @@ assign_varying_location(ir_variable *input_var, ir_variable *output_var,
}
}
+namespace pack {
+
+class varying_info : public exec_node
+{
+public:
+ ir_variable *produced;
+ ir_variable *consumed;
+ varying_info( ir_variable *p, ir_variable *c)
+ : produced(p), consumed(c)
+ {
+
+ }
+};
+
+bool
+varying_pack_avoid(exec_list *lst, gl_shader_program *prog, unsigned max_varyings)
+{
+ unsigned input_index = FRAG_ATTRIB_VAR0, output_index = VERT_RESULT_VAR0;
+ foreach_list_const(node, lst) {
+ const varying_info *vi = (class varying_info *) node;
+ assign_varying_location(vi->consumed, vi->produced, &input_index, &output_index);
+ }
+
+ unsigned varyings_count = MAX2(input_index - FRAG_ATTRIB_VAR0, output_index - VERT_RESULT_VAR0);
+ if (varyings_count > max_varyings) {
+ linker_error(prog, "This driver does not support packing, too much varyings.");
+ return false;
+ }
+ return true;
+}
/**
* Assign locations for all variables that are produced in one pipeline stage
@@ -1841,10 +1871,9 @@ assign_varying_locations(struct gl_context *ctx,
unsigned num_tfeedback_decls,
tfeedback_decl *tfeedback_decls)
{
- /* FINISHME: Set dynamically when geometry shader support is added. */
- unsigned output_index = VERT_RESULT_VAR0;
- unsigned input_index = FRAG_ATTRIB_VAR0;
-
+ void *rctx = ralloc_context(NULL);
+ exec_list *delayed_assignment = new (rctx) exec_list();
+
/* Operate in a total of three passes.
*
* 1. Assign locations for any matching inputs and outputs.
@@ -1872,26 +1901,58 @@ assign_varying_locations(struct gl_context *ctx,
if (input_var && input_var->mode != ir_var_in)
input_var = NULL;
+ varying_info *vi = NULL;
+
if (input_var) {
- assign_varying_location(input_var, output_var, &input_index,
- &output_index);
+ vi = new (rctx) varying_info (output_var, input_var);
+ delayed_assignment->push_tail(vi);
}
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
if (!tfeedback_decls[i].is_assigned() &&
tfeedback_decls[i].matches_var(output_var)) {
- if (output_var->location == -1) {
- assign_varying_location(input_var, output_var, &input_index,
- &output_index);
+ if (output_var->location != -1) {
+ if (!tfeedback_decls[i].assign_location(ctx, prog, output_var)) {
+ ralloc_free(rctx);
+ return false;
+ }
+ } else if (!vi) {
+ vi = new (rctx) varying_info (output_var, NULL);
+ delayed_assignment->push_tail(vi);
}
- if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
- return false;
}
}
}
- unsigned varying_vectors = 0;
+ bool (* varying_pack)(exec_list *, gl_shader_program *, unsigned);
+
+ switch (ctx->ShaderCompilerOptions[0].VaryingsPackingConstraint) {
+ default:
+ varying_pack = varying_pack_avoid;
+ break;
+ }
+ if (!varying_pack(delayed_assignment, prog, ctx->Const.MaxVarying)) {
+ ralloc_free(rctx);
+ return false;
+ }
+
+ // Do TFB assignments
+ foreach_list(node, delayed_assignment) {
+ varying_info *vi = (varying_info *) node;
+ for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+ printf("name is %s, at %d,%d\n", vi->produced->name, vi->produced->location, vi->produced->horizontal_location);
+ printf("assigned is %d\n",tfeedback_decls[i].matches_var(vi->produced));
+ if (!tfeedback_decls[i].is_assigned() &&
+ tfeedback_decls[i].matches_var(vi->produced)) {
+ if (!tfeedback_decls[i].assign_location(ctx, prog, vi->produced)) {
+ ralloc_free(rctx);
+ return false;
+ }
+ }
+ }
+ }
+
if (consumer) {
foreach_list(node, consumer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
@@ -1922,48 +1983,10 @@ assign_varying_locations(struct gl_context *ctx,
* value is written by the previous stage.
*/
var->mode = ir_var_auto;
- } else {
- /* The packing rules are used for vertex shader inputs are also
- * used for fragment shader inputs.
- */
- varying_vectors += count_attribute_slots(var->type);
}
}
}
-
- if (ctx->API == API_OPENGLES2 || prog->Version == 100) {
- if (varying_vectors > ctx->Const.MaxVarying) {
- if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) {
- linker_warning(prog, "shader uses too many varying vectors "
- "(%u > %u), but the driver will try to optimize "
- "them out; this is non-portable out-of-spec "
- "behavior\n",
- varying_vectors, ctx->Const.MaxVarying);
- } else {
- linker_error(prog, "shader uses too many varying vectors "
- "(%u > %u)\n",
- varying_vectors, ctx->Const.MaxVarying);
- return false;
- }
- }
- } else {
- const unsigned float_components = varying_vectors * 4;
- if (float_components > ctx->Const.MaxVarying * 4) {
- if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) {
- linker_warning(prog, "shader uses too many varying components "
- "(%u > %u), but the driver will try to optimize "
- "them out; this is non-portable out-of-spec "
- "behavior\n",
- float_components, ctx->Const.MaxVarying * 4);
- } else {
- linker_error(prog, "shader uses too many varying components "
- "(%u > %u)\n",
- float_components, ctx->Const.MaxVarying * 4);
- return false;
- }
- }
- }
-
+ ralloc_free(rctx);
return true;
}
--
1.7.7
More information about the mesa-dev
mailing list