Fix validation of statically referenced varyings. Varyings and in/out variables that are passed between shader pipeline stages are verified to have matching types at link-time, even when only statically referenced (this includes trivially optimized out branches) or even just declared. GLSL ES 3.00 - 4.3.10 Linking of Vertex Outputs and Fragment Inputs Change-Id: I122b1cdcc4630c86a8ebfb4d4e37f3a7a335afbe Reviewed-on: https://swiftshader-review.googlesource.com/16070 Tested-by: Nicolas Capens <nicolascapens@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp index 8edd099..6afc880 100644 --- a/src/OpenGL/compiler/OutputASM.cpp +++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -661,14 +661,23 @@ void OutputASM::visitSymbol(TIntermSymbol *symbol) { - // Vertex varyings don't have to be actively used to successfully link - // against pixel shaders that use them. So make sure they're declared. - if(symbol->getQualifier() == EvqVaryingOut || symbol->getQualifier() == EvqInvariantVaryingOut || symbol->getQualifier() == EvqVertexOut) + // The type of vertex outputs and fragment inputs with the same name must match (validated at link time), + // so declare them but don't assign a register index yet (one will be assigned when referenced in reachable code). + switch(symbol->getQualifier()) { + case EvqVaryingIn: + case EvqVaryingOut: + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: + case EvqVertexOut: + case EvqFragmentIn: if(symbol->getBasicType() != EbtInvariant) // Typeless declarations are not new varyings { declareVarying(symbol, -1); } + break; + default: + break; } TInterfaceBlock* block = symbol->getType().getInterfaceBlock();
diff --git a/src/OpenGL/compiler/SymbolTable.h b/src/OpenGL/compiler/SymbolTable.h index 3bc7ff4..3466f2f 100644 --- a/src/OpenGL/compiler/SymbolTable.h +++ b/src/OpenGL/compiler/SymbolTable.h
@@ -208,10 +208,10 @@ bool insert(TSymbol *symbol); - // Insert a function using its unmangled name as the key. - bool insertUnmangled(TFunction *function); + // Insert a function using its unmangled name as the key. + bool insertUnmangled(TFunction *function); - TSymbol *find(const TString &name) const; + TSymbol *find(const TString &name) const; static int nextUniqueId() {
diff --git a/src/OpenGL/libGLESv2/Program.cpp b/src/OpenGL/libGLESv2/Program.cpp index 42cf1b3..0d43096 100644 --- a/src/OpenGL/libGLESv2/Program.cpp +++ b/src/OpenGL/libGLESv2/Program.cpp
@@ -1349,9 +1349,13 @@ if(!matched) { - appendToInfoLog("Fragment varying %s does not match any vertex varying", input.name.c_str()); + // If a fragment varying is declared but not statically used, it's not an error to not have a matching vertex varying. + if(input.registerIndex >= 0) + { + appendToInfoLog("Fragment varying %s does not match any vertex varying", input.name.c_str()); - return false; + return false; + } } }