diff options
author | Timothy Arceri <[email protected]> | 2016-05-17 11:15:27 +1000 |
---|---|---|
committer | Timothy Arceri <[email protected]> | 2016-05-24 12:46:48 +1000 |
commit | 72449c477ee3d3ecb825a49ea2fc2121a6c553e0 (patch) | |
tree | 69793a2f335b6336b45ab0ade4c5d5b1226ca411 /src/compiler | |
parent | 37266dfb7c747536d254b32eefa9222c60a37508 (diff) |
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 <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/glsl/linker.cpp | 72 |
1 files 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; } |