summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2016-05-17 10:58:53 +1000
committerDave Airlie <[email protected]>2016-05-20 11:22:52 +1000
commit3ca1c2216d38970bb067c7d94dc701bfc33d983e (patch)
tree188a37546d2d55a178990c33e049a02db348711b
parent8a65b5135a167d4f12cef19408e0ca52fffe06bc (diff)
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 <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
-rw-r--r--src/compiler/glsl/ast_to_hir.cpp7
-rw-r--r--src/compiler/glsl_types.cpp4
-rw-r--r--src/compiler/glsl_types.h4
3 files changed, 11 insertions, 4 deletions
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index b4c6de2a6a1..ecfe684a0f4 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -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 *,
diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp
index c058283c48d..11f1e85ec1c 100644
--- a/src/compiler/glsl_types.cpp
+++ b/src/compiler/glsl_types.cpp
@@ -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
diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h
index a47b0ffe5a2..7f9e3184ca9 100644
--- a/src/compiler/glsl_types.h
+++ b/src/compiler/glsl_types.h
@@ -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: