summaryrefslogtreecommitdiff
path: root/lib/mesa/src/compiler/glsl/link_varyings.cpp
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2019-05-23 05:33:34 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2019-05-23 05:33:34 +0000
commit9886815a25d84be79f51e65ebd8e458bb5d26ca8 (patch)
treea65edf018dd992543337433f7303fb29a6c8e8cf /lib/mesa/src/compiler/glsl/link_varyings.cpp
parente2a3acb64af2657b1181806818eacad061103c23 (diff)
Merge Mesa 19.0.5
Diffstat (limited to 'lib/mesa/src/compiler/glsl/link_varyings.cpp')
-rw-r--r--lib/mesa/src/compiler/glsl/link_varyings.cpp142
1 files changed, 95 insertions, 47 deletions
diff --git a/lib/mesa/src/compiler/glsl/link_varyings.cpp b/lib/mesa/src/compiler/glsl/link_varyings.cpp
index 93b3b82b9..28187e2f0 100644
--- a/lib/mesa/src/compiler/glsl/link_varyings.cpp
+++ b/lib/mesa/src/compiler/glsl/link_varyings.cpp
@@ -309,16 +309,16 @@ cross_validate_types_and_qualifiers(struct gl_context *ctx,
* "The invariance of varyings that are declared in both the vertex
* and fragment shaders must match."
*/
- if (input->data.invariant != output->data.invariant &&
+ if (input->data.explicit_invariant != output->data.explicit_invariant &&
prog->data->Version < (prog->IsES ? 300 : 430)) {
linker_error(prog,
"%s shader output `%s' %s invariant qualifier, "
"but %s shader input %s invariant qualifier\n",
_mesa_shader_stage_to_string(producer_stage),
output->name,
- (output->data.invariant) ? "has" : "lacks",
+ (output->data.explicit_invariant) ? "has" : "lacks",
_mesa_shader_stage_to_string(consumer_stage),
- (input->data.invariant) ? "has" : "lacks");
+ (input->data.explicit_invariant) ? "has" : "lacks");
return;
}
@@ -424,28 +424,14 @@ compute_variable_location_slot(ir_variable *var, gl_shader_stage stage)
struct explicit_location_info {
ir_variable *var;
- unsigned numerical_type;
+ bool base_type_is_integer;
+ unsigned base_type_bit_size;
unsigned interpolation;
bool centroid;
bool sample;
bool patch;
};
-static inline unsigned
-get_numerical_type(const glsl_type *type)
-{
- /* From the OpenGL 4.6 spec, section 4.4.1 Input Layout Qualifiers, Page 68,
- * (Location aliasing):
- *
- * "Further, when location aliasing, the aliases sharing the location
- * must have the same underlying numerical type (floating-point or
- * integer)
- */
- if (type->is_float() || type->is_double())
- return GLSL_TYPE_FLOAT;
- return GLSL_TYPE_INT;
-}
-
static bool
check_location_aliasing(struct explicit_location_info explicit_locations[][4],
ir_variable *var,
@@ -461,14 +447,23 @@ check_location_aliasing(struct explicit_location_info explicit_locations[][4],
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.
+ unsigned base_type_bit_size;
+ const glsl_type *type_without_array = type->without_array();
+ const bool base_type_is_integer =
+ glsl_base_type_is_integer(type_without_array->base_type);
+ const bool is_struct = type_without_array->is_record();
+ if (is_struct) {
+ /* structs don't have a defined underlying base type so just treat all
+ * component slots as used and set the bit size to 0. If there is
+ * location aliasing, we'll fail anyway later.
*/
last_comp = 4;
+ base_type_bit_size = 0;
} else {
- unsigned dmul = type->without_array()->is_64bit() ? 2 : 1;
- last_comp = component + type->without_array()->vector_elements * dmul;
+ unsigned dmul = type_without_array->is_64bit() ? 2 : 1;
+ last_comp = component + type_without_array->vector_elements * dmul;
+ base_type_bit_size =
+ glsl_base_type_get_bit_size(type_without_array->base_type);
}
while (location < location_limit) {
@@ -478,8 +473,22 @@ check_location_aliasing(struct explicit_location_info explicit_locations[][4],
&explicit_locations[location][comp];
if (info->var) {
- /* Component aliasing is not alloed */
- if (comp >= component && comp < last_comp) {
+ if (info->var->type->without_array()->is_record() || is_struct) {
+ /* Structs cannot share location since they are incompatible
+ * with any other underlying numerical type.
+ */
+ linker_error(prog,
+ "%s shader has multiple %sputs sharing the "
+ "same location that don't have the same "
+ "underlying numerical type. Struct variable '%s', "
+ "location %u\n",
+ _mesa_shader_stage_to_string(stage),
+ var->data.mode == ir_var_shader_in ? "in" : "out",
+ is_struct ? var->name : info->var->name,
+ location);
+ return false;
+ } else if (comp >= component && comp < last_comp) {
+ /* Component aliasing is not allowed */
linker_error(prog,
"%s shader has multiple %sputs explicitly "
"assigned to location %d and component %d\n",
@@ -488,27 +497,52 @@ check_location_aliasing(struct explicit_location_info explicit_locations[][4],
location, comp);
return false;
} else {
- /* For all other used components we need to have matching
- * types, interpolation and auxiliary storage
+ /* From the OpenGL 4.60.5 spec, section 4.4.1 Input Layout
+ * Qualifiers, Page 67, (Location aliasing):
+ *
+ * " Further, when location aliasing, the aliases sharing the
+ * location must have the same underlying numerical type
+ * and bit width (floating-point or integer, 32-bit versus
+ * 64-bit, etc.) and the same auxiliary storage and
+ * interpolation qualification."
+ */
+
+ /* If the underlying numerical type isn't integer, implicitly
+ * it will be float or else we would have failed by now.
*/
- if (info->numerical_type !=
- get_numerical_type(type->without_array())) {
+ if (info->base_type_is_integer != base_type_is_integer) {
linker_error(prog,
- "Varyings sharing the same location must "
- "have the same underlying numerical type. "
- "Location %u component %u\n",
- location, comp);
+ "%s shader has multiple %sputs sharing the "
+ "same location that don't have the same "
+ "underlying numerical type. Location %u "
+ "component %u.\n",
+ _mesa_shader_stage_to_string(stage),
+ var->data.mode == ir_var_shader_in ?
+ "in" : "out", location, comp);
+ return false;
+ }
+
+ if (info->base_type_bit_size != base_type_bit_size) {
+ linker_error(prog,
+ "%s shader has multiple %sputs sharing the "
+ "same location that don't have the same "
+ "underlying numerical bit size. Location %u "
+ "component %u.\n",
+ _mesa_shader_stage_to_string(stage),
+ var->data.mode == ir_var_shader_in ?
+ "in" : "out", location, comp);
return false;
}
if (info->interpolation != interpolation) {
linker_error(prog,
- "%s shader has multiple %sputs at explicit "
- "location %u with different interpolation "
- "settings\n",
+ "%s shader has multiple %sputs sharing the "
+ "same location that don't have the same "
+ "interpolation qualification. Location %u "
+ "component %u.\n",
_mesa_shader_stage_to_string(stage),
var->data.mode == ir_var_shader_in ?
- "in" : "out", location);
+ "in" : "out", location, comp);
return false;
}
@@ -516,17 +550,20 @@ check_location_aliasing(struct explicit_location_info explicit_locations[][4],
info->sample != sample ||
info->patch != patch) {
linker_error(prog,
- "%s shader has multiple %sputs at explicit "
- "location %u with different aux storage\n",
+ "%s shader has multiple %sputs sharing the "
+ "same location that don't have the same "
+ "auxiliary storage qualification. Location %u "
+ "component %u.\n",
_mesa_shader_stage_to_string(stage),
var->data.mode == ir_var_shader_in ?
- "in" : "out", location);
+ "in" : "out", location, comp);
return false;
}
}
} else if (comp >= component && comp < last_comp) {
info->var = var;
- info->numerical_type = get_numerical_type(type->without_array());
+ info->base_type_is_integer = base_type_is_integer;
+ info->base_type_bit_size = base_type_bit_size;
info->interpolation = interpolation;
info->centroid = centroid;
info->sample = sample;
@@ -773,8 +810,20 @@ cross_validate_outputs_to_inputs(struct gl_context *ctx,
output = explicit_locations[idx][input->data.location_frac].var;
- if (output == NULL ||
- input->data.location != output->data.location) {
+ if (output == NULL) {
+ /* A linker failure should only happen when there is no
+ * output declaration and there is Static Use of the
+ * declared input.
+ */
+ if (input->data.used) {
+ linker_error(prog,
+ "%s shader input `%s' with explicit location "
+ "has no matching output\n",
+ _mesa_shader_stage_to_string(consumer->Stage),
+ input->name);
+ break;
+ }
+ } else if (input->data.location != output->data.location) {
linker_error(prog,
"%s shader input `%s' with explicit location "
"has no matching output\n",
@@ -804,7 +853,7 @@ cross_validate_outputs_to_inputs(struct gl_context *ctx,
*/
assert(!input->data.assigned);
if (input->data.used && !input->get_interface_type() &&
- !input->data.explicit_location && !prog->SeparateShader)
+ !input->data.explicit_location)
linker_error(prog,
"%s shader input `%s' "
"has no matching output in the previous stage\n",
@@ -1166,8 +1215,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
return false;
}
- if ((this->offset / 4) / info->Buffers[buffer].Stride !=
- (xfb_offset - 1) / info->Buffers[buffer].Stride) {
+ if (xfb_offset > info->Buffers[buffer].Stride) {
linker_error(prog, "xfb_offset (%d) overflows xfb_stride (%d) for "
"buffer (%d)", xfb_offset * 4,
info->Buffers[buffer].Stride * 4, buffer);