glsl: handle same struct redeclaration (v2)

This works around a bug in older version of UE4, where a shader
defines the same structure twice. Although we aren't sure this is correct
GLSL (it most likely isn't) there are enough UE4 based things out there
we should deal with this.

This drops the error to a warning if the struct names and contents match.

v1.1: do better C++ on record_compare declaration (Rob)
v2: restrict this to desktop GL only (Ian)

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=95005
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie
2016-05-17 10:58:53 +10:00
parent 8a65b5135a
commit 3ca1c2216d
3 changed files with 11 additions and 4 deletions

View File

@@ -6918,7 +6918,12 @@ ast_struct_specifier::hir(exec_list *instructions,
glsl_type::get_record_instance(fields, decl_count, this->name);
if (!state->symbols->add_type(name, t)) {
_mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
const glsl_type *match = state->symbols->get_type(name);
/* allow struct matching for desktop GL - older UE4 does this */
if (state->is_version(130, 0) && match->record_compare(t, false))
_mesa_glsl_warning(& loc, state, "struct `%s' previously defined", name);
else
_mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
} else {
const glsl_type **s = reralloc(state, state->user_structures,
const glsl_type *,

View File

@@ -856,7 +856,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
bool
glsl_type::record_compare(const glsl_type *b) const
glsl_type::record_compare(const glsl_type *b, bool match_locations) const
{
if (this->length != b->length)
return false;
@@ -887,7 +887,7 @@ glsl_type::record_compare(const glsl_type *b) const
if (this->fields.structure[i].matrix_layout
!= b->fields.structure[i].matrix_layout)
return false;
if (this->fields.structure[i].location
if (match_locations && this->fields.structure[i].location
!= b->fields.structure[i].location)
return false;
if (this->fields.structure[i].offset

View File

@@ -740,8 +740,10 @@ struct glsl_type {
* Compare a record type against another record type.
*
* This is useful for matching record types declared across shader stages.
* 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.
*/
bool record_compare(const glsl_type *b) const;
bool record_compare(const glsl_type *b, bool match_locations = true) const;
private: