--- 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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev