glsl: Fix input/output structure matching across shader stages
Section 7.4.1 (Shader Interface Matching) of the OpenGL 4.30 spec says: "Variables or block members declared as structures are considered to match in type if and only if structure members match in name, type, qualification, and declaration order." Fixes: * layout-location-struct.shader_test v2: rebased against master and small fixes Signed-off-by: Vadym Shovkoplias <vadym.shovkoplias@globallogic.com> Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com> Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108250
This commit is contained in:

committed by
Timothy Arceri

parent
738921afd9
commit
a7d40a13ec
@@ -7594,7 +7594,7 @@ ast_struct_specifier::hir(exec_list *instructions,
|
|||||||
if (!type->is_anonymous() && !state->symbols->add_type(name, type)) {
|
if (!type->is_anonymous() && !state->symbols->add_type(name, type)) {
|
||||||
const glsl_type *match = state->symbols->get_type(name);
|
const glsl_type *match = state->symbols->get_type(name);
|
||||||
/* allow struct matching for desktop GL - older UE4 does this */
|
/* allow struct matching for desktop GL - older UE4 does this */
|
||||||
if (match != NULL && state->is_version(130, 0) && match->record_compare(type, false))
|
if (match != NULL && state->is_version(130, 0) && match->record_compare(type, true, false))
|
||||||
_mesa_glsl_warning(& loc, state, "struct `%s' previously defined", name);
|
_mesa_glsl_warning(& loc, state, "struct `%s' previously defined", name);
|
||||||
else
|
else
|
||||||
_mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
|
_mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
|
||||||
|
@@ -214,6 +214,24 @@ cross_validate_types_and_qualifiers(struct gl_context *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type_to_match != output->type) {
|
if (type_to_match != output->type) {
|
||||||
|
if (output->type->is_struct()) {
|
||||||
|
/* Structures across shader stages can have different name
|
||||||
|
* and considered to match in type if and only if structure
|
||||||
|
* members match in name, type, qualification, and declaration
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
if (!output->type->record_compare(type_to_match, false, true)) {
|
||||||
|
linker_error(prog,
|
||||||
|
"%s shader output `%s' declared as struct `%s', "
|
||||||
|
"doesn't match in type with %s shader input "
|
||||||
|
"declared as struct `%s'\n",
|
||||||
|
_mesa_shader_stage_to_string(producer_stage),
|
||||||
|
output->name,
|
||||||
|
output->type->name,
|
||||||
|
_mesa_shader_stage_to_string(consumer_stage),
|
||||||
|
input->type->name);
|
||||||
|
}
|
||||||
|
} else if (!output->type->is_array() || !is_gl_identifier(output->name)) {
|
||||||
/* There is a bit of a special case for gl_TexCoord. This
|
/* There is a bit of a special case for gl_TexCoord. This
|
||||||
* built-in is unsized by default. Applications that variable
|
* built-in is unsized by default. Applications that variable
|
||||||
* access it must redeclare it with a size. There is some
|
* access it must redeclare it with a size. There is some
|
||||||
@@ -232,7 +250,6 @@ cross_validate_types_and_qualifiers(struct gl_context *ctx,
|
|||||||
* correspondence between the vertex language and the
|
* correspondence between the vertex language and the
|
||||||
* fragment language."
|
* fragment language."
|
||||||
*/
|
*/
|
||||||
if (!output->type->is_array() || !is_gl_identifier(output->name)) {
|
|
||||||
linker_error(prog,
|
linker_error(prog,
|
||||||
"%s shader output `%s' declared as type `%s', "
|
"%s shader output `%s' declared as type `%s', "
|
||||||
"but %s shader input declared as type `%s'\n",
|
"but %s shader input declared as type `%s'\n",
|
||||||
|
@@ -1008,7 +1008,8 @@ glsl_type::get_array_instance(const glsl_type *base,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
glsl_type::record_compare(const glsl_type *b, bool match_locations) const
|
glsl_type::record_compare(const glsl_type *b, bool match_name,
|
||||||
|
bool match_locations) const
|
||||||
{
|
{
|
||||||
if (this->length != b->length)
|
if (this->length != b->length)
|
||||||
return false;
|
return false;
|
||||||
@@ -1025,7 +1026,14 @@ glsl_type::record_compare(const glsl_type *b, bool match_locations) const
|
|||||||
* type definitions, and field names to be considered the same type."
|
* type definitions, and field names to be considered the same type."
|
||||||
*
|
*
|
||||||
* GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5).
|
* GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5).
|
||||||
|
*
|
||||||
|
* Section 7.4.1 (Shader Interface Matching) of the OpenGL 4.30 spec says:
|
||||||
|
*
|
||||||
|
* "Variables or block members declared as structures are considered
|
||||||
|
* to match in type if and only if structure members match in name,
|
||||||
|
* type, qualification, and declaration order."
|
||||||
*/
|
*/
|
||||||
|
if (match_name)
|
||||||
if (strcmp(this->name, b->name) != 0)
|
if (strcmp(this->name, b->name) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1098,7 +1106,8 @@ glsl_type::record_key_compare(const void *a, const void *b)
|
|||||||
const glsl_type *const key1 = (glsl_type *) a;
|
const glsl_type *const key1 = (glsl_type *) a;
|
||||||
const glsl_type *const key2 = (glsl_type *) b;
|
const glsl_type *const key2 = (glsl_type *) b;
|
||||||
|
|
||||||
return strcmp(key1->name, key2->name) == 0 && key1->record_compare(key2);
|
return strcmp(key1->name, key2->name) == 0 &&
|
||||||
|
key1->record_compare(key2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -934,11 +934,15 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Compare a record type against another record type.
|
* Compare a record type against another record type.
|
||||||
*
|
*
|
||||||
* This is useful for matching record types declared across shader stages.
|
* This is useful for matching record types declared on the same shader
|
||||||
|
* stage as well as across different shader stages.
|
||||||
|
* The option to not match name is needed for matching record types
|
||||||
|
* declared across different shader stages.
|
||||||
* The option to not match locations is to deal with places where the
|
* The option to not match locations is to deal with places where the
|
||||||
* same struct is defined in a block which has a location set on it.
|
* same struct is defined in a block which has a location set on it.
|
||||||
*/
|
*/
|
||||||
bool record_compare(const glsl_type *b, bool match_locations = true) const;
|
bool record_compare(const glsl_type *b, bool match_name,
|
||||||
|
bool match_locations = true) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the type interface packing.
|
* Get the type interface packing.
|
||||||
|
Reference in New Issue
Block a user