From 74c27c774e012989297dfe6843ed7491b51bd85c Mon Sep 17 00:00:00 2001 From: Bryan Cain Date: Sat, 28 Jul 2012 16:49:03 -0500 Subject: [PATCH] glsl: add get_pipeline_stage to linker and use it in link_shaders Fixes segfault in glxgears, and should also make it easier to add new shader types such as tesselation shaders in the future. --- src/glsl/linker.cpp | 69 ++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 358b4cb2200..09d18f08df6 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -243,6 +243,23 @@ link_invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode, } +/** + * Gets the shader type (MESA_SHADER_*) at the specified position in the + * pipeline, from 0 to MESA_SHADER_TYPES. + */ +unsigned +get_pipeline_stage(unsigned pos) +{ + unsigned shader_types[MESA_SHADER_TYPES] = { + MESA_SHADER_VERTEX, + MESA_SHADER_GEOMETRY, + MESA_SHADER_FRAGMENT + }; + assert(pos >= 0 && pos < MESA_SHADER_TYPES); + return shader_types[pos]; +} + + /** * Determine the number of attribute slots required for a particular type * @@ -2623,27 +2640,25 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) unsigned prev; for (prev = 0; prev < MESA_SHADER_TYPES; prev++) { - if (prog->_LinkedShaders[prev] != NULL) + if (prog->_LinkedShaders[get_pipeline_stage(prev)] != NULL) break; } /* Validate the inputs of each stage with the output of the preceding * stage. */ - if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { - if (!cross_validate_outputs_to_inputs(prog, - prog->_LinkedShaders[MESA_SHADER_VERTEX], - prog->_LinkedShaders[MESA_SHADER_GEOMETRY])) - goto done; - if (!cross_validate_outputs_to_inputs(prog, - prog->_LinkedShaders[MESA_SHADER_GEOMETRY], - prog->_LinkedShaders[MESA_SHADER_FRAGMENT])) - goto done; - } else { + for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) { + unsigned type = get_pipeline_stage(i); + unsigned type_prev = get_pipeline_stage(prev); + if (prog->_LinkedShaders[type] == NULL) + continue; + if (!cross_validate_outputs_to_inputs(prog, - prog->_LinkedShaders[MESA_SHADER_VERTEX], - prog->_LinkedShaders[MESA_SHADER_FRAGMENT])) + prog->_LinkedShaders[type_prev], + prog->_LinkedShaders[type])) goto done; + + prev = i; } prog->LinkStatus = true; @@ -2699,7 +2714,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) unsigned prev; for (prev = 0; prev < MESA_SHADER_TYPES; prev++) { - if (prog->_LinkedShaders[prev] != NULL) + if (prog->_LinkedShaders[get_pipeline_stage(prev)] != NULL) break; } @@ -2725,23 +2740,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { - if (!assign_varying_locations( - ctx, prog, prog->_LinkedShaders[MESA_SHADER_VERTEX], - prog->_LinkedShaders[MESA_SHADER_GEOMETRY], - 0, tfeedback_decls)) - goto done; - if (!assign_varying_locations( - ctx, prog, prog->_LinkedShaders[MESA_SHADER_GEOMETRY], - prog->_LinkedShaders[MESA_SHADER_FRAGMENT], - num_tfeedback_decls, tfeedback_decls)) - goto done; - } else { + for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) { + unsigned type = get_pipeline_stage(i); + unsigned type_prev = get_pipeline_stage(prev); + if (prog->_LinkedShaders[type] == NULL) + continue; + if (!assign_varying_locations( - ctx, prog, prog->_LinkedShaders[MESA_SHADER_VERTEX], - prog->_LinkedShaders[MESA_SHADER_FRAGMENT], - num_tfeedback_decls, tfeedback_decls)) + ctx, prog, prog->_LinkedShaders[type_prev], prog->_LinkedShaders[type], + type == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, + tfeedback_decls)) goto done; + + prev = i; } if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL && num_tfeedback_decls != 0) {