glsl/linker: outputs in the same location must share interpolation
From ARB_enhanced_layouts: "[...]when location aliasing, the aliases sharing the location must have the same underlying numerical type (floating-point or integer) and the same auxiliary storage and interpolation qualification.[...]" Add code to the linker to validate that aliased locations do have the same interpolation. Fixes: KHR-GL45.enhanced_layouts.varying_location_aliasing_with_mixed_interpolation Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
This commit is contained in:
@@ -406,6 +406,7 @@ compute_variable_location_slot(ir_variable *var, gl_shader_stage stage)
|
|||||||
struct explicit_location_info {
|
struct explicit_location_info {
|
||||||
ir_variable *var;
|
ir_variable *var;
|
||||||
unsigned base_type;
|
unsigned base_type;
|
||||||
|
unsigned interpolation;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -415,6 +416,7 @@ check_location_aliasing(struct explicit_location_info explicit_locations[][4],
|
|||||||
unsigned component,
|
unsigned component,
|
||||||
unsigned location_limit,
|
unsigned location_limit,
|
||||||
const glsl_type *type,
|
const glsl_type *type,
|
||||||
|
unsigned interpolation,
|
||||||
gl_shader_program *prog,
|
gl_shader_program *prog,
|
||||||
gl_shader_stage stage)
|
gl_shader_stage stage)
|
||||||
{
|
{
|
||||||
@@ -431,6 +433,38 @@ check_location_aliasing(struct explicit_location_info explicit_locations[][4],
|
|||||||
|
|
||||||
while (location < location_limit) {
|
while (location < location_limit) {
|
||||||
unsigned i = component;
|
unsigned i = component;
|
||||||
|
|
||||||
|
/* If there are other outputs assigned to the same location
|
||||||
|
* they must have the same interpolation
|
||||||
|
*/
|
||||||
|
unsigned comp = 0;
|
||||||
|
while (comp < 4) {
|
||||||
|
/* Skip the components used by this output, we only care about
|
||||||
|
* other outputs in the same location
|
||||||
|
*/
|
||||||
|
if (comp == i) {
|
||||||
|
comp = last_comp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct explicit_location_info *info =
|
||||||
|
&explicit_locations[location][comp];
|
||||||
|
|
||||||
|
if (info->var) {
|
||||||
|
if (info->interpolation != interpolation) {
|
||||||
|
linker_error(prog,
|
||||||
|
"%s shader has multiple outputs at explicit "
|
||||||
|
"location %u with different interpolation "
|
||||||
|
"settings\n",
|
||||||
|
_mesa_shader_stage_to_string(stage), location);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Component aliasing is not allowed */
|
||||||
while (i < last_comp) {
|
while (i < last_comp) {
|
||||||
if (explicit_locations[location][i].var != NULL) {
|
if (explicit_locations[location][i].var != NULL) {
|
||||||
linker_error(prog,
|
linker_error(prog,
|
||||||
@@ -458,6 +492,7 @@ check_location_aliasing(struct explicit_location_info explicit_locations[][4],
|
|||||||
explicit_locations[location][i].var = var;
|
explicit_locations[location][i].var = var;
|
||||||
explicit_locations[location][i].base_type =
|
explicit_locations[location][i].base_type =
|
||||||
type->without_array()->base_type;
|
type->without_array()->base_type;
|
||||||
|
explicit_locations[location][i].interpolation = interpolation;
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
/* We need to do some special handling for doubles as dvec3 and
|
/* We need to do some special handling for doubles as dvec3 and
|
||||||
@@ -526,18 +561,20 @@ cross_validate_outputs_to_inputs(struct gl_context *ctx,
|
|||||||
unsigned field_location = type->fields.structure[i].location -
|
unsigned field_location = type->fields.structure[i].location -
|
||||||
(type->fields.structure[i].patch ? VARYING_SLOT_PATCH0 :
|
(type->fields.structure[i].patch ? VARYING_SLOT_PATCH0 :
|
||||||
VARYING_SLOT_VAR0);
|
VARYING_SLOT_VAR0);
|
||||||
|
unsigned interpolation = type->fields.structure[i].interpolation;
|
||||||
if (!check_location_aliasing(explicit_locations, var,
|
if (!check_location_aliasing(explicit_locations, var,
|
||||||
field_location,
|
field_location,
|
||||||
0, field_location + 1,
|
0, field_location + 1,
|
||||||
field_type, prog,
|
field_type, interpolation,
|
||||||
producer->Stage)) {
|
prog, producer->Stage)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!check_location_aliasing(explicit_locations, var,
|
} else if (!check_location_aliasing(explicit_locations, var,
|
||||||
idx, var->data.location_frac,
|
idx, var->data.location_frac,
|
||||||
slot_limit, type, prog,
|
slot_limit, type,
|
||||||
producer->Stage)) {
|
var->data.interpolation,
|
||||||
|
prog, producer->Stage)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user