From 72449c477ee3d3ecb825a49ea2fc2121a6c553e0 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Tue, 17 May 2016 11:15:27 +1000 Subject: [PATCH] glsl: add support for explicit components to frag outputs V2: fix error checking for arrays and components. V1 was only taking into account all the array elements and all the components of one of the varyings during the comparision and treating the other as a single slot/component. Reviewed-by: Anuj Phogat --- src/compiler/glsl/linker.cpp | 72 +++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 81a683e9423..5c0e4b67ff2 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -2606,7 +2606,12 @@ assign_attribute_or_color_locations(gl_shader_program *prog, } to_assign[32]; assert(max_index <= 32); + /* Temporary array for the set of attributes that have locations assigned. + */ + ir_variable *assigned[16]; + unsigned num_attr = 0; + unsigned assigned_attr = 0; foreach_in_list(ir_instruction, node, sh->ir) { ir_variable *const var = node->as_variable(); @@ -2768,18 +2773,62 @@ assign_attribute_or_color_locations(gl_shader_program *prog, * attribute overlaps any previously allocated bits. */ if ((~(use_mask << attr) & used_locations) != used_locations) { - if (target_index == MESA_SHADER_FRAGMENT || - (prog->IsES && prog->Version >= 300)) { - linker_error(prog, - "overlapping location is assigned " - "to %s `%s' %d %d %d\n", string, - var->name, used_locations, use_mask, attr); + if (target_index == MESA_SHADER_FRAGMENT && !prog->IsES) { + /* From section 4.4.2 (Output Layout Qualifiers) of the GLSL + * 4.40 spec: + * + * "Additionally, for fragment shader outputs, if two + * variables are placed within the same location, they + * must have the same underlying type (floating-point or + * integer). No component aliasing of output variables or + * members is allowed. + */ + for (unsigned i = 0; i < assigned_attr; i++) { + unsigned assigned_slots = + assigned[i]->type->count_attribute_slots(false); + unsigned assig_attr = + assigned[i]->data.location - generic_base; + unsigned assigned_use_mask = (1 << assigned_slots) - 1; + + if ((assigned_use_mask << assig_attr) & + (use_mask << attr)) { + + const glsl_type *assigned_type = + assigned[i]->type->without_array(); + const glsl_type *type = var->type->without_array(); + if (assigned_type->base_type != type->base_type) { + linker_error(prog, "types do not match for aliased" + " %ss %s and %s\n", string, + assigned[i]->name, var->name); + return false; + } + + unsigned assigned_component_mask = + ((1 << assigned_type->vector_elements) - 1) << + assigned[i]->data.location_frac; + unsigned component_mask = + ((1 << type->vector_elements) - 1) << + var->data.location_frac; + if (assigned_component_mask & component_mask) { + linker_error(prog, "overlapping component is " + "assigned to %ss %s and %s " + "(component=%d)\n", + string, assigned[i]->name, var->name, + var->data.location_frac); + return false; + } + } + } + } else if (target_index == MESA_SHADER_FRAGMENT || + (prog->IsES && prog->Version >= 300)) { + linker_error(prog, "overlapping location is assigned " + "to %s `%s' %d %d %d\n", string, var->name, + used_locations, use_mask, attr); return false; } else { - linker_warning(prog, - "overlapping location is assigned " - "to %s `%s' %d %d %d\n", string, - var->name, used_locations, use_mask, attr); + linker_warning(prog, "overlapping location is assigned " + "to %s `%s' %d %d %d\n", string, var->name, + used_locations, use_mask, attr); } } @@ -2809,6 +2858,9 @@ assign_attribute_or_color_locations(gl_shader_program *prog, double_storage_locations |= (use_mask << attr); } + assigned[assigned_attr] = var; + assigned_attr++; + continue; } -- 2.30.2