Commit 05b6b7fc by Zhenyao Mo

Add an SH_GLSL_CORE_OUTPUT profile.

So we could generate shaders for Apple using core GL profile. By switching to core profile, we still pass most WebGL conformance tests 1.0.2 on Linux, but not all, so apparently more work is needed. However, I think it's OK to check this CL in because this output profile will be only used behind a chromium switch. BUG=angleproject:933 TEST=webgl conformance tests Change-Id: Iad70e1aebf82349d3fc5f4116c1d6bc4448193fd Reviewed-on: https://chromium-review.googlesource.com/255282Tested-by: 's avatarZhenyao Mo <zmo@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 7749005a
......@@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 133
#define ANGLE_SH_VERSION 134
typedef enum {
SH_GLES2_SPEC = 0x8B40,
......@@ -81,13 +81,16 @@ typedef enum {
} ShShaderSpec;
typedef enum {
SH_ESSL_OUTPUT = 0x8B45,
SH_GLSL_OUTPUT = 0x8B46,
SH_ESSL_OUTPUT = 0x8B45,
// SH_GLSL_OUTPUT is deprecated. This is to not break the build.
SH_GLSL_OUTPUT = 0x8B46,
SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
SH_GLSL_CORE_OUTPUT = 0x8B47,
// HLSL output only supported in some configurations.
SH_HLSL_OUTPUT = 0x8B47,
SH_HLSL9_OUTPUT = 0x8B47,
SH_HLSL11_OUTPUT = 0x8B48
SH_HLSL_OUTPUT = 0x8B48,
SH_HLSL9_OUTPUT = 0x8B48,
SH_HLSL11_OUTPUT = 0x8B49
} ShShaderOutput;
// Compile options.
......
......@@ -19,12 +19,13 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
{
switch (output) {
case SH_ESSL_OUTPUT:
case SH_ESSL_OUTPUT:
return new TranslatorESSL(type, spec);
case SH_GLSL_OUTPUT:
return new TranslatorGLSL(type, spec);
case SH_HLSL9_OUTPUT:
case SH_HLSL11_OUTPUT:
case SH_GLSL_CORE_OUTPUT:
case SH_GLSL_COMPATIBILITY_OUTPUT:
return new TranslatorGLSL(type, spec, output);
case SH_HLSL9_OUTPUT:
case SH_HLSL11_OUTPUT:
#ifdef ANGLE_ENABLE_HLSL
return new TranslatorHLSL(type, spec, output);
#else
......@@ -32,7 +33,7 @@ TCompiler* ConstructCompiler(
// configuration. Return NULL per the ShConstructCompiler API.
return NULL;
#endif // ANGLE_ENABLE_HLSL
default:
default:
// Unknown format. Return NULL per the ShConstructCompiler API.
return NULL;
}
......
......@@ -510,7 +510,9 @@ bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
{
// Other languages not yet supported
ASSERT(outputLanguage == SH_GLSL_OUTPUT || outputLanguage == SH_ESSL_OUTPUT);
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
outputLanguage == SH_GLSL_CORE_OUTPUT ||
outputLanguage == SH_ESSL_OUTPUT);
writeCommonPrecisionEmulationHelpers(sink, outputLanguage);
EmulationSet::const_iterator it;
......
......@@ -6,14 +6,20 @@
#include "compiler/translator/OutputESSL.h"
TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
NameMap &nameMap,
TSymbolTable &symbolTable,
int shaderVersion,
bool forceHighp)
: TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion),
: TOutputGLSLBase(objSink,
clampingStrategy,
hashFunction,
nameMap,
symbolTable,
shaderVersion,
SH_ESSL_OUTPUT),
mForceHighp(forceHighp)
{
}
......
......@@ -11,8 +11,15 @@ TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
int shaderVersion)
: TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion)
int shaderVersion,
ShShaderOutput output)
: TOutputGLSLBase(objSink,
clampingStrategy,
hashFunction,
nameMap,
symbolTable,
shaderVersion,
output)
{
}
......@@ -21,21 +28,30 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision)
return false;
}
void TOutputGLSL::visitSymbol(TIntermSymbol* node)
void TOutputGLSL::visitSymbol(TIntermSymbol *node)
{
TInfoSinkBase& out = objSink();
if (node->getSymbol() == "gl_FragDepthEXT")
const TString &symbol = node->getSymbol();
if (symbol == "gl_FragDepthEXT")
{
out << "gl_FragDepth";
}
else if (symbol == "gl_FragColor" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
{
out << "webgl_FragColor";
}
else if (symbol == "gl_FragData" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
{
out << "webgl_FragData";
}
else
{
TOutputGLSLBase::visitSymbol(node);
}
}
TString TOutputGLSL::translateTextureFunction(TString& name)
TString TOutputGLSL::translateTextureFunction(TString &name)
{
static const char *simpleRename[] = {
"texture2DLodEXT", "texture2DLod",
......@@ -46,10 +62,30 @@ TString TOutputGLSL::translateTextureFunction(TString& name)
"textureCubeGradEXT", "textureCubeGradARB",
NULL, NULL
};
static const char *legacyToCoreRename[] = {
"texture2D", "texture",
"texture2DProj", "textureProj",
"texture2DLod", "textureLod",
"texture2DProjLod", "textureProjLod",
"textureCube", "texture",
"textureCubeLod", "textureLod",
// Extensions
"texture2DLodEXT", "textureLod",
"texture2DProjLodEXT", "textureProjLod",
"textureCubeLodEXT", "textureLod",
"texture2DGradEXT", "textureGrad",
"texture2DProjGradEXT", "textureProjGrad",
"textureCubeGradEXT", "textureGrad",
NULL, NULL
};
const char **mapping = (getShaderOutput() == SH_GLSL_CORE_OUTPUT) ?
legacyToCoreRename : simpleRename;
for (int i = 0; simpleRename[i] != NULL; i += 2) {
if (name == simpleRename[i]) {
return simpleRename[i+1];
for (int i = 0; mapping[i] != NULL; i += 2)
{
if (name == mapping[i])
{
return mapping[i+1];
}
}
......
......@@ -11,15 +11,16 @@
class TOutputGLSL : public TOutputGLSLBase
{
public:
public:
TOutputGLSL(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
int shaderVersion);
int shaderVersion,
ShShaderOutput output);
protected:
protected:
virtual bool writeVariablePrecision(TPrecision);
virtual void visitSymbol(TIntermSymbol* node);
virtual TString translateTextureFunction(TString& name);
......
......@@ -46,6 +46,7 @@ bool isSingleStatement(TIntermNode *node)
}
return true;
}
} // namespace
TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
......@@ -53,7 +54,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable &symbolTable,
int shaderVersion)
int shaderVersion,
ShShaderOutput output)
: TIntermTraverser(true, true, true),
mObjSink(objSink),
mDeclaringVariables(false),
......@@ -61,7 +63,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
mHashFunction(hashFunction),
mNameMap(nameMap),
mSymbolTable(symbolTable),
mShaderVersion(shaderVersion)
mShaderVersion(shaderVersion),
mOutput(output)
{
}
......@@ -91,7 +94,34 @@ void TOutputGLSLBase::writeVariableType(const TType &type)
TQualifier qualifier = type.getQualifier();
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
{
out << type.getQualifierString() << " ";
if (mOutput == SH_GLSL_CORE_OUTPUT)
{
switch (qualifier)
{
case EvqAttribute:
out << "in" << " ";
break;
case EvqVaryingIn:
out << "in" << " ";
break;
case EvqVaryingOut:
out << "out" << " ";
break;
case EvqInvariantVaryingIn:
out << "invariant in" << " ";
break;
case EvqInvariantVaryingOut:
out << "invariant out" << " ";
break;
default:
out << type.getQualifierString() << " ";
break;
}
}
else
{
out << type.getQualifierString() << " ";
}
}
// Declare the struct if we have not done so already.
if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
......
......@@ -21,7 +21,13 @@ class TOutputGLSLBase : public TIntermTraverser
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable& symbolTable,
int shaderVersion);
int shaderVersion,
ShShaderOutput output);
ShShaderOutput getShaderOutput() const
{
return mOutput;
}
protected:
TInfoSinkBase &objSink() { return mObjSink; }
......@@ -80,6 +86,8 @@ class TOutputGLSLBase : public TIntermTraverser
TSymbolTable &mSymbolTable;
const int mShaderVersion;
ShShaderOutput mOutput;
};
#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
......@@ -11,7 +11,8 @@
#include "angle_gl.h"
TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
: TCompiler(type, spec, SH_ESSL_OUTPUT) {
: TCompiler(type, spec, SH_ESSL_OUTPUT)
{
}
void TranslatorESSL::translate(TIntermNode *root, int) {
......@@ -40,7 +41,13 @@ void TranslatorESSL::translate(TIntermNode *root, int) {
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
// Write translated shader.
TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion(), precisionEmulation);
TOutputESSL outputESSL(sink,
getArrayIndexClampingStrategy(),
getHashFunction(),
getNameMap(),
getSymbolTable(),
getShaderVersion(),
precisionEmulation);
root->traverse(&outputESSL);
}
......
......@@ -9,14 +9,15 @@
#include "compiler/translator/Compiler.h"
class TranslatorESSL : public TCompiler {
public:
class TranslatorESSL : public TCompiler
{
public:
TranslatorESSL(sh::GLenum type, ShShaderSpec spec);
protected:
protected:
virtual void translate(TIntermNode *root, int compileOptions);
private:
private:
void writeExtensionBehavior();
};
......
......@@ -6,13 +6,59 @@
#include "compiler/translator/TranslatorGLSL.h"
#include "angle_gl.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/OutputGLSL.h"
#include "compiler/translator/VersionGLSL.h"
namespace
{
// To search for what output variables are used in a fragment shader.
// We handle gl_FragColor and gl_FragData at the moment.
class TFragmentOutSearcher : public TIntermTraverser
{
public:
TFragmentOutSearcher()
: mUsesGlFragColor(false),
mUsesGlFragData(false)
{
}
bool usesGlFragColor() const
{
return mUsesGlFragColor;
}
bool usesGlFragData() const
{
return mUsesGlFragData;
}
TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec)
: TCompiler(type, spec, SH_GLSL_OUTPUT) {
protected:
virtual void visitSymbol(TIntermSymbol *node) override
{
if (node->getSymbol() == "gl_FragColor")
{
mUsesGlFragColor = true;
}
else if (node->getSymbol() == "gl_FragData")
{
mUsesGlFragData = true;
}
}
private:
bool mUsesGlFragColor;
bool mUsesGlFragData;
};
} // namespace anonymous
TranslatorGLSL::TranslatorGLSL(sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output)
: TCompiler(type, spec, output) {
}
void TranslatorGLSL::translate(TIntermNode *root, int) {
......@@ -33,7 +79,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int) {
EmulatePrecision emulatePrecision;
root->traverse(&emulatePrecision);
emulatePrecision.updateTree();
emulatePrecision.writeEmulationHelpers(sink, SH_GLSL_OUTPUT);
emulatePrecision.writeEmulationHelpers(sink, getOutputType());
}
// Write emulated built-in functions if needed.
......@@ -43,14 +89,38 @@ void TranslatorGLSL::translate(TIntermNode *root, int) {
// Write array bounds clamping emulation if needed.
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
// Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
// if it's core profile shaders and they are used.
if (getShaderType() == GL_FRAGMENT_SHADER &&
getOutputType() == SH_GLSL_CORE_OUTPUT)
{
TFragmentOutSearcher searcher;
root->traverse(&searcher);
ASSERT(!(searcher.usesGlFragData() && searcher.usesGlFragColor()));
if (searcher.usesGlFragColor())
{
sink << "out vec4 webgl_FragColor;\n";
}
if (searcher.usesGlFragData())
{
sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
}
}
// Write translated shader.
TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion());
TOutputGLSL outputGLSL(sink,
getArrayIndexClampingStrategy(),
getHashFunction(),
getNameMap(),
getSymbolTable(),
getShaderVersion(),
getOutputType());
root->traverse(&outputGLSL);
}
void TranslatorGLSL::writeVersion(TIntermNode *root)
{
TVersionGLSL versionGLSL(getShaderType(), getPragma());
TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType());
root->traverse(&versionGLSL);
int version = versionGLSL.getVersion();
// We need to write version directive only if it is greater than 110.
......
......@@ -12,7 +12,7 @@
class TranslatorGLSL : public TCompiler
{
public:
TranslatorGLSL(sh::GLenum type, ShShaderSpec spec);
TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
protected:
virtual void translate(TIntermNode *root, int compileOptions);
......
......@@ -8,6 +8,7 @@
static const int GLSL_VERSION_110 = 110;
static const int GLSL_VERSION_120 = 120;
static const int GLSL_VERSION_150 = 150;
// We need to scan for the following:
// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
......@@ -26,12 +27,22 @@ static const int GLSL_VERSION_120 = 120;
// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
// are built-in types, entire structures or arrays... are all l-values."
//
TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma)
TVersionGLSL::TVersionGLSL(sh::GLenum type,
const TPragma &pragma,
ShShaderOutput output)
{
if (pragma.stdgl.invariantAll)
mVersion = GLSL_VERSION_120;
if (output == SH_GLSL_CORE_OUTPUT)
{
mVersion = GLSL_VERSION_150;
}
else
mVersion = GLSL_VERSION_110;
{
ASSERT(output == SH_GLSL_COMPATIBILITY_OUTPUT);
if (pragma.stdgl.invariantAll)
mVersion = GLSL_VERSION_120;
else
mVersion = GLSL_VERSION_110;
}
}
void TVersionGLSL::visitSymbol(TIntermSymbol *node)
......
......@@ -29,14 +29,16 @@
class TVersionGLSL : public TIntermTraverser
{
public:
TVersionGLSL(sh::GLenum type, const TPragma &pragma);
// Returns 120 if the following is used the shader:
// - "invariant",
// - "gl_PointCoord",
// - matrix/matrix constructors
// - array "out" parameters
// Else 110 is returned.
TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output);
// If output is core profile, returns 150.
// If output is legacy profile,
// Returns 120 if the following is used the shader:
// - "invariant",
// - "gl_PointCoord",
// - matrix/matrix constructors
// - array "out" parameters
// Else 110 is returned.
int getVersion() { return mVersion; }
virtual void visitSymbol(TIntermSymbol *);
......
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