Commit b7bf7426 by Zhenyao Mo Committed by Commit Bot

Don't ouput "invarant" and "centroid" in GLSL 4.1 or older.

BUG=chromium:639760,chromium:641129 TEST=webgl2_conformance Change-Id: I5fe87246eaea78888529d7b45b79399e6065daa9 Reviewed-on: https://chromium-review.googlesource.com/408569Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Commit-Queue: Zhenyao Mo <zmo@chromium.org>
parent 70697252
...@@ -219,6 +219,16 @@ const ShCompileOptions SH_USE_UNUSED_STANDARD_SHARED_BLOCKS = UINT64_C(1) << 28; ...@@ -219,6 +219,16 @@ const ShCompileOptions SH_USE_UNUSED_STANDARD_SHARED_BLOCKS = UINT64_C(1) << 28;
// But don't remove on AMD Linux to avoid triggering the bug on AMD. // But don't remove on AMD Linux to avoid triggering the bug on AMD.
const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1) << 29; const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1) << 29;
// Due to spec difference between GLSL 4.1 or lower and ESSL3, some platforms (for example, Mac OSX
// core profile) require a variable's "invariant"/"centroid" qualifiers to match between vertex and
// fragment shader. A simple solution to allow such shaders to link is to omit the two qualifiers.
// Note that the two flags only take effect on ESSL3 input shaders translated to GLSL 4.1 or lower.
// TODO(zmo): This is not a good long-term solution. Simply dropping these qualifiers may break some
// developers' content. A more complex workaround of dynamically generating, compiling, and
// re-linking shaders that use these qualifiers should be implemented.
const ShCompileOptions SH_REMOVE_INVARIANT_FOR_ESSL3 = UINT64_C(1) << 30;
const ShCompileOptions SH_REMOVE_CENTROID_FOR_ESSL3 = UINT64_C(1) << 31;
// Defines alternate strategies for implementing array index clamping. // Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy enum ShArrayIndexClampingStrategy
{ {
......
...@@ -96,6 +96,13 @@ bool IsGLSL420OrNewer(ShShaderOutput output) ...@@ -96,6 +96,13 @@ bool IsGLSL420OrNewer(ShShaderOutput output)
output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
} }
bool IsGLSL410OrOlder(ShShaderOutput output)
{
return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
}
size_t GetGlobalMaxTokenSize(ShShaderSpec spec) size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
{ {
// WebGL defines a max token legnth of 256, while ES2 leaves max token // WebGL defines a max token legnth of 256, while ES2 leaves max token
......
...@@ -42,6 +42,7 @@ bool IsWebGLBasedSpec(ShShaderSpec spec); ...@@ -42,6 +42,7 @@ bool IsWebGLBasedSpec(ShShaderSpec spec);
// //
bool IsGLSL130OrNewer(ShShaderOutput output); bool IsGLSL130OrNewer(ShShaderOutput output);
bool IsGLSL420OrNewer(ShShaderOutput output); bool IsGLSL420OrNewer(ShShaderOutput output);
bool IsGLSL410OrOlder(ShShaderOutput output);
// //
// The base class used to back handles returned to the driver. // The base class used to back handles returned to the driver.
......
...@@ -101,6 +101,19 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, ...@@ -101,6 +101,19 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
{ {
} }
void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
{
bool removeInvariant = ((type.getQualifier() == EvqVaryingIn && sh::IsGLSL420OrNewer(mOutput) &&
!(mCompileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT)) ||
(sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
!!(mCompileOptions & SH_REMOVE_INVARIANT_FOR_ESSL3)));
if (!removeInvariant)
{
TInfoSinkBase &out = objSink();
out << "invariant ";
}
}
void TOutputGLSLBase::writeTriplet( void TOutputGLSLBase::writeTriplet(
Visit visit, const char *preStr, const char *inStr, const char *postStr) Visit visit, const char *preStr, const char *inStr, const char *postStr)
{ {
...@@ -149,15 +162,49 @@ void TOutputGLSLBase::writeLayoutQualifier(const TType &type) ...@@ -149,15 +162,49 @@ void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
out << ") "; out << ") ";
} }
const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
{
if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
!!(mCompileOptions & SH_REMOVE_CENTROID_FOR_ESSL3))
{
switch (qualifier)
{
// The return string is consistent with sh::getQualifierString() from
// BaseTypes.h minus the "centroid" keyword.
case EvqCentroid:
return "";
case EvqCentroidIn:
return "smooth in";
case EvqCentroidOut:
return "smooth out";
default:
break;
}
}
if (sh::IsGLSL130OrNewer(mOutput))
{
switch (qualifier)
{
case EvqAttribute:
return "in";
case EvqVaryingIn:
return "in";
case EvqVaryingOut:
return "out";
default:
break;
}
}
return sh::getQualifierString(qualifier);
}
void TOutputGLSLBase::writeVariableType(const TType &type) void TOutputGLSLBase::writeVariableType(const TType &type)
{ {
TQualifier qualifier = type.getQualifier(); TQualifier qualifier = type.getQualifier();
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
bool removeInvariant = (qualifier == EvqVaryingIn && sh::IsGLSL420OrNewer(mOutput) && if (type.isInvariant())
!(mCompileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT));
if (type.isInvariant() && !removeInvariant)
{ {
out << "invariant "; writeInvariantQualifier(type);
} }
if (type.getBasicType() == EbtInterfaceBlock) if (type.getBasicType() == EbtInterfaceBlock)
{ {
...@@ -166,27 +213,10 @@ void TOutputGLSLBase::writeVariableType(const TType &type) ...@@ -166,27 +213,10 @@ void TOutputGLSLBase::writeVariableType(const TType &type)
} }
if (qualifier != EvqTemporary && qualifier != EvqGlobal) if (qualifier != EvqTemporary && qualifier != EvqGlobal)
{ {
if (sh::IsGLSL130OrNewer(mOutput)) const char *qualifierString = mapQualifierToString(qualifier);
{ if (qualifierString && qualifierString[0] != '\0')
switch (qualifier)
{
case EvqAttribute:
out << "in ";
break;
case EvqVaryingIn:
out << "in ";
break;
case EvqVaryingOut:
out << "out ";
break;
default:
out << type.getQualifierString() << " ";
break;
}
}
else
{ {
out << type.getQualifierString() << " "; out << qualifierString << " ";
} }
} }
...@@ -930,7 +960,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -930,7 +960,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
ASSERT(sequence && sequence->size() == 1); ASSERT(sequence && sequence->size() == 1);
const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
ASSERT(symbol); ASSERT(symbol);
out << "invariant " << hashVariableName(symbol->getName()); writeInvariantQualifier(symbol->getType());
out << hashVariableName(symbol->getName());
} }
visitChildren = false; visitChildren = false;
break; break;
......
...@@ -37,6 +37,7 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -37,6 +37,7 @@ class TOutputGLSLBase : public TIntermTraverser
TInfoSinkBase &objSink() { return mObjSink; } TInfoSinkBase &objSink() { return mObjSink; }
void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
void writeLayoutQualifier(const TType &type); void writeLayoutQualifier(const TType &type);
void writeInvariantQualifier(const TType &type);
void writeVariableType(const TType &type); void writeVariableType(const TType &type);
virtual bool writeVariablePrecision(TPrecision precision) = 0; virtual bool writeVariablePrecision(TPrecision precision) = 0;
void writeFunctionParameters(const TIntermSequence &args); void writeFunctionParameters(const TIntermSequence &args);
...@@ -81,6 +82,8 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -81,6 +82,8 @@ class TOutputGLSLBase : public TIntermTraverser
void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction); void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction);
const char *mapQualifierToString(TQualifier qialifier);
TInfoSinkBase &mObjSink; TInfoSinkBase &mObjSink;
bool mDeclaringVariables; bool mDeclaringVariables;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment