From 0d88b15f073d09afed1747d9cdde98f15c7aa28d Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 17 Dec 2015 11:34:09 +1100 Subject: [PATCH] glsl: cross validate varyings with a component qualifier This change checks for component overlap, including handling overlap of locations and components by doubles. Previously there was no validation for assigning explicit locations to a location used by the second half of a double. V3: simplify handling of doubles and fix double component aliasing detection V2: fix component matching for matricies Reviewed-by: Anuj Phogat Reviewed-by: Edward O'Callaghan Reviewed-by: Kenneth Graunke --- src/compiler/glsl/link_varyings.cpp | 63 ++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp index c222ede9291..34e82c71d56 100644 --- a/src/compiler/glsl/link_varyings.cpp +++ b/src/compiler/glsl/link_varyings.cpp @@ -350,7 +350,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer) { glsl_symbol_table parameters; - ir_variable *explicit_locations[MAX_VARYING] = { NULL, }; + ir_variable *explicit_locations[MAX_VARYING][4] = { {NULL, NULL} }; /* Find all shader outputs in the "producer" stage. */ @@ -371,18 +371,59 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, unsigned num_elements = type->count_attribute_slots(false); unsigned idx = var->data.location - VARYING_SLOT_VAR0; unsigned slot_limit = idx + num_elements; + unsigned last_comp; + + if (var->type->without_array()->is_record()) { + /* The component qualifier can't be used on structs so just treat + * all component slots as used. + */ + last_comp = 4; + } else { + unsigned dmul = var->type->is_double() ? 2 : 1; + last_comp = var->data.location_frac + + var->type->without_array()->vector_elements * dmul; + } while (idx < slot_limit) { - if (explicit_locations[idx] != NULL) { - linker_error(prog, - "%s shader has multiple outputs explicitly " - "assigned to location %d\n", - _mesa_shader_stage_to_string(producer->Stage), - idx); - return; - } + for (unsigned i = var->data.location_frac; i < last_comp; i++) { + if (explicit_locations[idx][i] != NULL) { + linker_error(prog, + "%s shader has multiple outputs explicitly " + "assigned to location %d and component %d\n", + _mesa_shader_stage_to_string(producer->Stage), + idx, var->data.location_frac); + return; + } - explicit_locations[idx] = var; + /* Make sure all component at this location have the same type. + */ + for (unsigned j = 0; j < 4; j++) { + if (explicit_locations[idx][j] && + (explicit_locations[idx][j]->type->without_array() + ->base_type != var->type->without_array()->base_type)) { + linker_error(prog, + "Varyings sharing the same location must " + "have the same underlying numerical type. " + "Location %u component %u\n", idx, + var->data.location_frac); + return; + } + } + + explicit_locations[idx][i] = var; + + /* We need to do some special handling for doubles as dvec3 and + * dvec4 consume two consecutive locations. We don't need to + * worry about components beginning at anything other than 0 as + * the spec does not allow this for dvec3 and dvec4. + */ + if (i == 3 && last_comp > 4) { + last_comp = last_comp - 4; + /* Bump location index and reset the component index */ + idx++; + i = 0; + } + } idx++; } } @@ -439,7 +480,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, unsigned slot_limit = idx + num_elements; while (idx < slot_limit) { - output = explicit_locations[idx]; + output = explicit_locations[idx][input->data.location_frac]; if (output == NULL || input->data.location != output->data.location) { -- 2.30.2