Remove invariant declaration in vertex shader for translation from ESSL 3.00 to GLSL <= 4.1

This is a follow-up patch of
https://chromium-review.googlesource.com/408569. This CL removes
invariant declaration in ESSL 3.00 vertex shader, such like:
"
out vec4 foo;
invariant foo;
"

This CL also adds the workarounds in libANGLE.

BUG=chromium:639760
TEST=webgl2_conformance

Change-Id: I568ab51a9a2f5da10d1aff0b63aae8805097e081
Reviewed-on: https://chromium-review.googlesource.com/409157
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Qiankun Miao 2016-11-09 12:59:30 +00:00 коммит произвёл Commit Bot
Родитель d9c6f50118
Коммит 89dd8f3701
15 изменённых файлов: 76 добавлений и 48 удалений

Просмотреть файл

@ -49,7 +49,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 166
#define ANGLE_SH_VERSION 167
enum ShShaderSpec
{
@ -226,8 +226,7 @@ const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1)
// 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;
const ShCompileOptions SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3 = UINT64_C(1) << 30;
// Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy

Просмотреть файл

@ -103,6 +103,22 @@ bool IsGLSL410OrOlder(ShShaderOutput output)
output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
}
bool RemoveInvariant(sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput outputType,
ShCompileOptions compileOptions)
{
if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
return true;
if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER && IsGLSL410OrOlder(outputType))
return true;
return false;
}
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
{
// WebGL defines a max token legnth of 256, while ES2 leaves max token
@ -394,8 +410,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
(outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
initializeGLPosition(root);
if (success && !(compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) &&
shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
if (success && RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
sh::RemoveInvariantDeclaration(root);
// This pass might emit short circuits so keep it before the short circuit unfolding

Просмотреть файл

@ -44,6 +44,14 @@ bool IsGLSL130OrNewer(ShShaderOutput output);
bool IsGLSL420OrNewer(ShShaderOutput output);
bool IsGLSL410OrOlder(ShShaderOutput output);
//
// Helper function to check if the invariant qualifier can be removed.
//
bool RemoveInvariant(sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput outputType,
ShCompileOptions compileOptions);
//
// The base class used to back handles returned to the driver.
//

Просмотреть файл

@ -14,6 +14,7 @@ TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable &symbolTable,
sh::GLenum shaderType,
int shaderVersion,
bool forceHighp,
ShCompileOptions compileOptions)
@ -22,6 +23,7 @@ TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
hashFunction,
nameMap,
symbolTable,
shaderType,
shaderVersion,
SH_ESSL_OUTPUT,
compileOptions),

Просмотреть файл

@ -14,20 +14,21 @@ namespace sh
class TOutputESSL : public TOutputGLSLBase
{
public:
TOutputESSL(TInfoSinkBase& objSink,
public:
TOutputESSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
NameMap &nameMap,
TSymbolTable &symbolTable,
sh::GLenum shaderType,
int shaderVersion,
bool forceHighp,
ShCompileOptions compileOptions);
protected:
bool writeVariablePrecision(TPrecision precision) override;
protected:
bool writeVariablePrecision(TPrecision precision) override;
private:
private:
bool mForceHighp;
};

Просмотреть файл

@ -9,11 +9,12 @@
namespace sh
{
TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
NameMap &nameMap,
TSymbolTable &symbolTable,
sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput output,
ShCompileOptions compileOptions)
@ -22,6 +23,7 @@ TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
hashFunction,
nameMap,
symbolTable,
shaderType,
shaderVersion,
output,
compileOptions)

Просмотреть файл

@ -15,11 +15,12 @@ namespace sh
class TOutputGLSL : public TOutputGLSLBase
{
public:
TOutputGLSL(TInfoSinkBase& objSink,
TOutputGLSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
NameMap &nameMap,
TSymbolTable &symbolTable,
sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput output,
ShCompileOptions compileOptions);

Просмотреть файл

@ -85,6 +85,7 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable &symbolTable,
sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput output,
ShCompileOptions compileOptions)
@ -95,6 +96,7 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
mHashFunction(hashFunction),
mNameMap(nameMap),
mSymbolTable(symbolTable),
mShaderType(shaderType),
mShaderVersion(shaderVersion),
mOutput(output),
mCompileOptions(compileOptions)
@ -103,11 +105,7 @@ 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)
if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions))
{
TInfoSinkBase &out = objSink();
out << "invariant ";
@ -165,7 +163,7 @@ void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
{
if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
!!(mCompileOptions & SH_REMOVE_CENTROID_FOR_ESSL3))
(mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0)
{
switch (qualifier)
{
@ -960,8 +958,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
ASSERT(sequence && sequence->size() == 1);
const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
ASSERT(symbol);
writeInvariantQualifier(symbol->getType());
out << hashVariableName(symbol->getName());
out << "invariant " << hashVariableName(symbol->getName());
}
visitChildren = false;
break;

Просмотреть файл

@ -23,7 +23,8 @@ class TOutputGLSLBase : public TIntermTraverser
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable& symbolTable,
TSymbolTable &symbolTable,
sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput output,
ShCompileOptions compileOptions);
@ -102,6 +103,8 @@ class TOutputGLSLBase : public TIntermTraverser
TSymbolTable &mSymbolTable;
sh::GLenum mShaderType;
const int mShaderVersion;
ShShaderOutput mOutput;

Просмотреть файл

@ -15,7 +15,7 @@ namespace
{
// An AST traverser that removes invariant declaration for input in fragment shader
// when GLSL >= 4.20.
// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2.
class RemoveInvariantDeclarationTraverser : public TIntermTraverser
{
public:
@ -26,17 +26,10 @@ class RemoveInvariantDeclarationTraverser : public TIntermTraverser
{
if (node->getOp() == EOpInvariantDeclaration)
{
for (TIntermNode *&child : *node->getSequence())
{
TIntermTyped *typed = child->getAsTyped();
if (typed && typed->getQualifier() == EvqVaryingIn)
{
TIntermSequence emptyReplacement;
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
getParentNode()->getAsBlock(), node, emptyReplacement));
return false;
}
}
TIntermSequence emptyReplacement;
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(),
node, emptyReplacement));
return false;
}
return true;
}

Просмотреть файл

@ -81,7 +81,8 @@ void TranslatorESSL::translate(TIntermNode *root, ShCompileOptions compileOption
// Write translated shader.
TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
getSymbolTable(), shaderVer, precisionEmulation, compileOptions);
getSymbolTable(), getShaderType(), shaderVer, precisionEmulation,
compileOptions);
root->traverse(&outputESSL);
}

Просмотреть файл

@ -188,13 +188,8 @@ void TranslatorGLSL::translate(TIntermNode *root, ShCompileOptions compileOption
}
// Write translated shader.
TOutputGLSL outputGLSL(sink,
getArrayIndexClampingStrategy(),
getHashFunction(),
getNameMap(),
getSymbolTable(),
getShaderVersion(),
getOutputType(),
TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(),
compileOptions);
root->traverse(&outputGLSL);
}

Просмотреть файл

@ -80,6 +80,11 @@ ShCompileOptions ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sour
options |= SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT;
}
if (mWorkarounds.removeInvariantAndCentroidForESSL3)
{
options |= SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3;
}
return options;
}

Просмотреть файл

@ -26,7 +26,8 @@ struct WorkaroundsGL
addAndTrueToLoopCondition(false),
emulateIsnanFloat(false),
useUnusedBlocksWithStandardOrSharedLayout(false),
dontRemoveInvariantForFragmentInput(false)
dontRemoveInvariantForFragmentInput(false),
removeInvariantAndCentroidForESSL3(false)
{
}
@ -116,6 +117,9 @@ struct WorkaroundsGL
// This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20
// on AMD.
bool dontRemoveInvariantForFragmentInput;
// This flag is used to fix spec difference between GLSL 4.1 or lower and ESSL3.
bool removeInvariantAndCentroidForESSL3;
};
}

Просмотреть файл

@ -944,6 +944,8 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround
workarounds->unpackLastRowSeparatelyForPaddingInclusion = IsNvidia(vendor);
workarounds->packLastRowSeparatelyForPaddingInclusion = IsNvidia(vendor);
#endif
workarounds->removeInvariantAndCentroidForESSL3 = functions->isAtMostGL(gl::Version(4, 1));
}
}