diff options
Diffstat (limited to 'src/glsl/link_varyings.cpp')
-rw-r--r-- | src/glsl/link_varyings.cpp | 175 |
1 files changed, 94 insertions, 81 deletions
diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp index 4ceb1d33e92..0368de9d575 100644 --- a/src/glsl/link_varyings.cpp +++ b/src/glsl/link_varyings.cpp @@ -41,6 +41,98 @@ /** + * Validate the types and qualifiers of an output from one stage against the + * matching input to another stage. + */ +static void +cross_validate_types_and_qualifiers(struct gl_shader_program *prog, + const ir_variable *input, + const ir_variable *output, + GLenum consumer_type, + GLenum producer_type) +{ + /* Check that the types match between stages. + */ + const glsl_type *type_to_match = input->type; + if (consumer_type == GL_GEOMETRY_SHADER) { + assert(type_to_match->is_array()); /* Enforced by ast_to_hir */ + type_to_match = type_to_match->element_type(); + } + if (type_to_match != output->type) { + /* There is a bit of a special case for gl_TexCoord. This + * built-in is unsized by default. Applications that variable + * access it must redeclare it with a size. There is some + * language in the GLSL spec that implies the fragment shader + * and vertex shader do not have to agree on this size. Other + * driver behave this way, and one or two applications seem to + * rely on it. + * + * Neither declaration needs to be modified here because the array + * sizes are fixed later when update_array_sizes is called. + * + * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec: + * + * "Unlike user-defined varying variables, the built-in + * varying variables don't have a strict one-to-one + * correspondence between the vertex language and the + * fragment language." + */ + if (!output->type->is_array() + || (strncmp("gl_", output->name, 3) != 0)) { + linker_error(prog, + "%s shader output `%s' declared as type `%s', " + "but %s shader input declared as type `%s'\n", + _mesa_glsl_shader_target_name(producer_type), + output->name, + output->type->name, + _mesa_glsl_shader_target_name(consumer_type), + input->type->name); + return; + } + } + + /* Check that all of the qualifiers match between stages. + */ + if (input->centroid != output->centroid) { + linker_error(prog, + "%s shader output `%s' %s centroid qualifier, " + "but %s shader input %s centroid qualifier\n", + _mesa_glsl_shader_target_name(producer_type), + output->name, + (output->centroid) ? "has" : "lacks", + _mesa_glsl_shader_target_name(consumer_type), + (input->centroid) ? "has" : "lacks"); + return; + } + + if (input->invariant != output->invariant) { + linker_error(prog, + "%s shader output `%s' %s invariant qualifier, " + "but %s shader input %s invariant qualifier\n", + _mesa_glsl_shader_target_name(producer_type), + output->name, + (output->invariant) ? "has" : "lacks", + _mesa_glsl_shader_target_name(consumer_type), + (input->invariant) ? "has" : "lacks"); + return; + } + + if (input->interpolation != output->interpolation) { + linker_error(prog, + "%s shader output `%s' specifies %s " + "interpolation qualifier, " + "but %s shader input specifies %s " + "interpolation qualifier\n", + _mesa_glsl_shader_target_name(producer_type), + output->name, + output->interpolation_string(), + _mesa_glsl_shader_target_name(consumer_type), + input->interpolation_string()); + return; + } +} + +/** * Validate that outputs from one stage match inputs of another */ void @@ -48,10 +140,6 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer) { glsl_symbol_table parameters; - const char *const producer_stage = - _mesa_glsl_shader_target_name(producer->Type); - const char *const consumer_stage = - _mesa_glsl_shader_target_name(consumer->Type); /* Find all shader outputs in the "producer" stage. */ @@ -81,83 +169,8 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, ir_variable *const output = parameters.get_variable(input->name); if (output != NULL) { - /* Check that the types match between stages. - */ - const glsl_type *type_to_match = input->type; - if (consumer->Type == GL_GEOMETRY_SHADER) { - assert(type_to_match->is_array()); /* Enforced by ast_to_hir */ - type_to_match = type_to_match->element_type(); - } - if (type_to_match != output->type) { - /* There is a bit of a special case for gl_TexCoord. This - * built-in is unsized by default. Applications that variable - * access it must redeclare it with a size. There is some - * language in the GLSL spec that implies the fragment shader - * and vertex shader do not have to agree on this size. Other - * driver behave this way, and one or two applications seem to - * rely on it. - * - * Neither declaration needs to be modified here because the array - * sizes are fixed later when update_array_sizes is called. - * - * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec: - * - * "Unlike user-defined varying variables, the built-in - * varying variables don't have a strict one-to-one - * correspondence between the vertex language and the - * fragment language." - */ - if (!output->type->is_array() - || (strncmp("gl_", output->name, 3) != 0)) { - linker_error(prog, - "%s shader output `%s' declared as type `%s', " - "but %s shader input declared as type `%s'\n", - producer_stage, output->name, - output->type->name, - consumer_stage, input->type->name); - return; - } - } - - /* Check that all of the qualifiers match between stages. - */ - if (input->centroid != output->centroid) { - linker_error(prog, - "%s shader output `%s' %s centroid qualifier, " - "but %s shader input %s centroid qualifier\n", - producer_stage, - output->name, - (output->centroid) ? "has" : "lacks", - consumer_stage, - (input->centroid) ? "has" : "lacks"); - return; - } - - if (input->invariant != output->invariant) { - linker_error(prog, - "%s shader output `%s' %s invariant qualifier, " - "but %s shader input %s invariant qualifier\n", - producer_stage, - output->name, - (output->invariant) ? "has" : "lacks", - consumer_stage, - (input->invariant) ? "has" : "lacks"); - return; - } - - if (input->interpolation != output->interpolation) { - linker_error(prog, - "%s shader output `%s' specifies %s " - "interpolation qualifier, " - "but %s shader input specifies %s " - "interpolation qualifier\n", - producer_stage, - output->name, - output->interpolation_string(), - consumer_stage, - input->interpolation_string()); - return; - } + cross_validate_types_and_qualifiers(prog, input, output, + consumer->Type, producer->Type); } } } |