summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIago Toral Quiroga <itoral@igalia.com>2017-10-19 10:57:30 +0200
committerIago Toral Quiroga <itoral@igalia.com>2017-10-26 08:40:14 +0200
commit6aa68772d4ecea120deb59bc2655e075ed0b6a17 (patch)
tree2579c50f039005faf445bf52f4d19a73dbb10f7d
parentb9446172249f05f577072f09ea17a391f3ee5d90 (diff)
glsl/linker: refactor link-time validation of output locations
Move the checks for explicit locations to a separate function. We will use this in a follow-up patch to validate locations for interface variables where we need to validate each interface member rather than the interface variable itself. Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
-rw-r--r--src/compiler/glsl/link_varyings.cpp128
1 files changed, 73 insertions, 55 deletions
diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp
index cb9091d86b..d394488ab9 100644
--- a/src/compiler/glsl/link_varyings.cpp
+++ b/src/compiler/glsl/link_varyings.cpp
@@ -403,6 +403,75 @@ compute_variable_location_slot(ir_variable *var, gl_shader_stage stage)
return var->data.location - location_start;
}
+static bool
+check_location_aliasing(ir_variable *explicit_locations[][4],
+ ir_variable *var,
+ unsigned location,
+ unsigned component,
+ unsigned location_limit,
+ const glsl_type *type,
+ gl_shader_program *prog,
+ gl_shader_stage stage)
+{
+ unsigned last_comp;
+ if (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 = type->without_array()->is_64bit() ? 2 : 1;
+ last_comp = component + type->without_array()->vector_elements * dmul;
+ }
+
+ while (location < location_limit) {
+ unsigned i = component;
+ while (i < last_comp) {
+ if (explicit_locations[location][i] != NULL) {
+ linker_error(prog,
+ "%s shader has multiple outputs explicitly "
+ "assigned to location %d and component %d\n",
+ _mesa_shader_stage_to_string(stage),
+ location, component);
+ return false;
+ }
+
+ /* Make sure all component at this location have the same type.
+ */
+ for (unsigned j = 0; j < 4; j++) {
+ if (explicit_locations[location][j] &&
+ (explicit_locations[location][j]->type->without_array()
+ ->base_type != 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", location, component);
+ return false;
+ }
+ }
+
+ explicit_locations[location][i] = var;
+ i++;
+
+ /* 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 == 4 && last_comp > 4) {
+ last_comp = last_comp - 4;
+ /* Bump location index and reset the component index */
+ location++;
+ i = 0;
+ }
+ }
+
+ location++;
+ }
+
+ return true;
+}
+
/**
* Validate that outputs from one stage match inputs of another
*/
@@ -435,7 +504,6 @@ cross_validate_outputs_to_inputs(struct gl_context *ctx,
unsigned num_elements = type->count_attribute_slots(false);
unsigned idx = compute_variable_location_slot(var, producer->Stage);
unsigned slot_limit = idx + num_elements;
- unsigned last_comp;
unsigned slot_max =
ctx->Const.Program[producer->Stage].MaxOutputComponents / 4;
@@ -446,60 +514,10 @@ cross_validate_outputs_to_inputs(struct gl_context *ctx,
return;
}
- if (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 = type->without_array()->is_64bit() ? 2 : 1;
- last_comp = var->data.location_frac +
- type->without_array()->vector_elements * dmul;
- }
-
- while (idx < slot_limit) {
- unsigned i = var->data.location_frac;
- while (i < last_comp) {
- 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;
- }
-
- /* 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 != 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;
- i++;
-
- /* 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 == 4 && last_comp > 4) {
- last_comp = last_comp - 4;
- /* Bump location index and reset the component index */
- idx++;
- i = 0;
- }
- }
- idx++;
+ if (!check_location_aliasing(explicit_locations, var, idx,
+ var->data.location_frac, slot_limit,
+ type, prog, producer->Stage)) {
+ return;
}
}
}