ES31: Implement GL_OES_geometry_shader built-ins in GLSL compiler
This patch intends to implement all built-in constants, variables and
functions defined in OpenGL ES 3.1 extension GL_OES_geometry_shader
in ANGLE GLSL compiler.
1. Add all built-in constants defined in GL_OES_geometry_shader.
2. Add built-in functions EmitVertex() and EndPrimitive() required
in Geometry Shader.
3. Add built-in variables gl_PrimitiveIDIn and gl_InvocationID to
Geometry Shader.
4. Add built-in variables gl_PrimitiveID and gl_Layer to both
Geometry Shader and Fragment Shader when GL_OES_geometry_shader
is enabled.
BUG=angleproject:1941
TEST=angle_unittests
Change-Id: I92821553ed0efee2ccb77fead6e065e7799819d0
Reviewed-on: https://chromium-review.googlesource.com/627670
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index 00f1108..eda024e 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -576,8 +576,11 @@
// GLSL ES 3.1 extension OES_geometry_shader qualifiers
EvqGeometryIn,
EvqGeometryOut,
- EvqPerVertexIn,
- EvqLayer, // gl_Layer
+ EvqPerVertexIn, // gl_in
+ EvqPrimitiveIDIn, // gl_PrimitiveIDIn
+ EvqInvocationID, // gl_InvocationID
+ EvqPrimitiveID, // gl_PrimitiveID
+ EvqLayer, // gl_Layer
// end of list
EvqLast
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index abe4592..8753d77 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -100,6 +100,7 @@
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
+ GLenum shaderType,
const TExtensionBehavior &extensionBehavior);
void visitSymbol(TIntermSymbol *symbol) override;
@@ -139,15 +140,21 @@
std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
+ // Shader uniforms
bool mDepthRangeAdded;
+
+ // Vertex Shader builtins
+ bool mInstanceIDAdded;
+ bool mVertexIDAdded;
+ bool mPointSizeAdded;
+
+ // Vertex Shader and Geometry Shader builtins
+ bool mPositionAdded;
+
+ // Fragment Shader builtins
bool mPointCoordAdded;
bool mFrontFacingAdded;
bool mFragCoordAdded;
-
- bool mInstanceIDAdded;
- bool mVertexIDAdded;
- bool mPositionAdded;
- bool mPointSizeAdded;
bool mLastFragDataAdded;
bool mFragColorAdded;
bool mFragDataAdded;
@@ -156,11 +163,19 @@
bool mSecondaryFragColorEXTAdded;
bool mSecondaryFragDataEXTAdded;
+ // Geometry Shader builtins
bool mPerVertexInAdded;
+ bool mPrimitiveIDInAdded;
+ bool mInvocationIDAdded;
+
+ // Geometry Shader and Fragment Shader builtins
+ bool mPrimitiveIDAdded;
+ bool mLayerAdded;
ShHashFunction64 mHashFunction;
int mShaderVersion;
+ GLenum mShaderType;
const TExtensionBehavior &mExtensionBehavior;
};
@@ -176,6 +191,7 @@
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
+ GLenum shaderType,
const TExtensionBehavior &extensionBehavior)
: TIntermTraverser(true, false, false, symbolTable),
mAttribs(attribs),
@@ -187,13 +203,13 @@
mShaderStorageBlocks(shaderStorageBlocks),
mInBlocks(inBlocks),
mDepthRangeAdded(false),
+ mInstanceIDAdded(false),
+ mVertexIDAdded(false),
+ mPointSizeAdded(false),
+ mPositionAdded(false),
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
- mInstanceIDAdded(false),
- mVertexIDAdded(false),
- mPositionAdded(false),
- mPointSizeAdded(false),
mLastFragDataAdded(false),
mFragColorAdded(false),
mFragDataAdded(false),
@@ -202,8 +218,13 @@
mSecondaryFragColorEXTAdded(false),
mSecondaryFragDataEXTAdded(false),
mPerVertexInAdded(false),
+ mPrimitiveIDInAdded(false),
+ mInvocationIDAdded(false),
+ mPrimitiveIDAdded(false),
+ mLayerAdded(false),
mHashFunction(hashFunction),
mShaderVersion(shaderVersion),
+ mShaderType(shaderType),
mExtensionBehavior(extensionBehavior)
{
}
@@ -470,6 +491,38 @@
recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
&mSecondaryFragDataEXTAdded);
return;
+ case EvqInvocationID:
+ recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings);
+ break;
+ case EvqPrimitiveIDIn:
+ recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings);
+ break;
+ case EvqPrimitiveID:
+ if (mShaderType == GL_GEOMETRY_SHADER_OES)
+ {
+ recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings);
+ }
+ else
+ {
+ ASSERT(mShaderType == GL_FRAGMENT_SHADER);
+ recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings);
+ }
+ break;
+ case EvqLayer:
+ if (mShaderType == GL_GEOMETRY_SHADER_OES)
+ {
+ recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings);
+ }
+ else if (mShaderType == GL_FRAGMENT_SHADER)
+ {
+ recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings);
+ }
+ else
+ {
+ ASSERT(mShaderType == GL_VERTEX_SHADER &&
+ IsExtensionEnabled(mExtensionBehavior, "GL_OVR_multiview"));
+ }
+ break;
default:
break;
}
@@ -783,11 +836,13 @@
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
+ GLenum shaderType,
const TExtensionBehavior &extensionBehavior)
{
CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
- hashFunction, symbolTable, shaderVersion, extensionBehavior);
+ hashFunction, symbolTable, shaderVersion, shaderType,
+ extensionBehavior);
root->traverse(&collect);
}
diff --git a/src/compiler/translator/CollectVariables.h b/src/compiler/translator/CollectVariables.h
index fb257f9..4d0d119 100644
--- a/src/compiler/translator/CollectVariables.h
+++ b/src/compiler/translator/CollectVariables.h
@@ -30,6 +30,7 @@
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
+ GLenum shaderType,
const TExtensionBehavior &extensionBehavior);
}
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 8ef6285..4b39fe1 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -476,7 +476,8 @@
ASSERT(!variablesCollected);
CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
&outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
- hashFunction, &symbolTable, shaderVersion, extensionBehavior);
+ hashFunction, &symbolTable, shaderVersion, shaderType,
+ extensionBehavior);
collectInterfaceBlocks();
variablesCollected = true;
if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
@@ -740,9 +741,18 @@
<< ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
<< ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
<< ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
- << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
<< ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
- << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations;
+ << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
+ << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
+ << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
+ << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
+ << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
+ << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
+ << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
+ << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
+ << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
+ << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
+ << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
// clang-format on
builtInResourcesString = strstream.str();
@@ -1010,7 +1020,7 @@
void TCompiler::initializeOutputVariables(TIntermBlock *root)
{
InitVariableList list;
- if (shaderType == GL_VERTEX_SHADER)
+ if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES)
{
for (auto var : outputVaryings)
{
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index 52ae411..dc2cd12 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -676,6 +676,15 @@
voidType, "groupMemoryBarrier");
}
+ if (type == GL_GEOMETRY_SHADER_OES)
+ {
+ const char *extension = "GL_OES_geometry_shader";
+ symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, EOpEmitVertex,
+ voidType, "EmitVertex");
+ symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension,
+ EOpEndPrimitive, voidType, "EndPrimitive");
+ }
+
//
// Depth range in window coordinates
//
@@ -720,7 +729,7 @@
{
symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended",
"gl_MaxDualSourceDrawBuffersEXT",
- resources.MaxDualSourceDrawBuffers);
+ resources.MaxDualSourceDrawBuffers, EbpMedium);
}
symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors",
@@ -777,6 +786,29 @@
resources.MaxCombinedAtomicCounterBuffers, EbpMedium);
symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize",
resources.MaxAtomicCounterBufferSize, EbpMedium);
+
+ if (resources.OES_geometry_shader)
+ {
+ const char *ext = "GL_OES_geometry_shader";
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryInputComponents",
+ resources.MaxGeometryInputComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputComponents",
+ resources.MaxGeometryOutputComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryImageUniforms",
+ resources.MaxGeometryImageUniforms, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTextureImageUnits",
+ resources.MaxGeometryTextureImageUnits, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputVertices",
+ resources.MaxGeometryOutputVertices, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTotalOutputComponents",
+ resources.MaxGeometryTotalOutputComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryUniformComponents",
+ resources.MaxGeometryUniformComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounters",
+ resources.MaxGeometryAtomicCounters, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounterBuffers",
+ resources.MaxGeometryAtomicCounterBuffers, EbpMedium);
+ }
}
void IdentifyBuiltIns(sh::GLenum type,
@@ -872,6 +904,15 @@
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
}
+ if (resources.OES_geometry_shader)
+ {
+ const char *extension = "GL_OES_geometry_shader";
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID",
+ TType(EbtInt, EbpHigh, EvqPrimitiveID, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer",
+ TType(EbtInt, EbpHigh, EvqLayer, 1));
+ }
+
break;
}
case GL_VERTEX_SHADER:
@@ -909,7 +950,6 @@
case GL_GEOMETRY_SHADER_OES:
{
- // TODO(jiawei.shao@intel.com): add all Geometry Shader built-in variables.
const char *extension = "GL_OES_geometry_shader";
// Add built-in interface block gl_PerVertex and the built-in array gl_in.
@@ -932,6 +972,20 @@
glInType.makeArray(0u);
symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType);
+ TType glPositionType(EbtFloat, EbpHigh, EvqPosition, 4);
+ glPositionType.setInterfaceBlock(new TInterfaceBlock(
+ glPerVertexString, fieldList, nullptr, TLayoutQualifier::create()));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Position",
+ glPositionType);
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveIDIn",
+ TType(EbtInt, EbpHigh, EvqPrimitiveIDIn, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_InvocationID",
+ TType(EbtInt, EbpHigh, EvqInvocationID, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID",
+ TType(EbtInt, EbpHigh, EvqPrimitiveID, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer",
+ TType(EbtInt, EbpHigh, EvqLayer, 1));
+
break;
}
default:
diff --git a/src/compiler/translator/Operator.cpp b/src/compiler/translator/Operator.cpp
index da92115..61e39e6 100644
--- a/src/compiler/translator/Operator.cpp
+++ b/src/compiler/translator/Operator.cpp
@@ -341,6 +341,11 @@
return "memoryBarrierShared";
case EOpGroupMemoryBarrier:
return "groupMemoryBarrier";
+
+ case EOpEmitVertex:
+ return "EmitVertex";
+ case EOpEndPrimitive:
+ return "EndPrimitive";
default:
break;
}
diff --git a/src/compiler/translator/Operator.h b/src/compiler/translator/Operator.h
index 23f78a6..c42a564 100644
--- a/src/compiler/translator/Operator.h
+++ b/src/compiler/translator/Operator.h
@@ -237,7 +237,11 @@
EOpMemoryBarrierBuffer,
EOpMemoryBarrierImage,
EOpMemoryBarrierShared,
- EOpGroupMemoryBarrier
+ EOpGroupMemoryBarrier,
+
+ // Geometry only
+ EOpEmitVertex,
+ EOpEndPrimitive
};
// Returns the string corresponding to the operator in GLSL
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index e2c5b16..c0c0437 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -1006,6 +1006,8 @@
case EOpMemoryBarrierImage:
case EOpMemoryBarrierShared:
case EOpGroupMemoryBarrier:
+ case EOpEmitVertex:
+ case EOpEndPrimitive:
writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
break;
default:
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index a1c12f3..6a312b6 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -521,6 +521,24 @@
case EvqPerVertexIn:
message = "can't modify any member in gl_in";
break;
+ case EvqPrimitiveIDIn:
+ message = "can't modify gl_PrimitiveIDIn";
+ break;
+ case EvqInvocationID:
+ message = "can't modify gl_InvocationID";
+ break;
+ case EvqPrimitiveID:
+ if (mShaderType == GL_FRAGMENT_SHADER)
+ {
+ message = "can't modify gl_PrimitiveID in a fragment shader";
+ }
+ break;
+ case EvqLayer:
+ if (mShaderType == GL_FRAGMENT_SHADER)
+ {
+ message = "can't modify gl_Layer in a fragment shader";
+ }
+ break;
default:
//
// Type that can't be written to?
diff --git a/src/compiler/translator/ShaderLang.cpp b/src/compiler/translator/ShaderLang.cpp
index f9a5bb5..75e5490 100644
--- a/src/compiler/translator/ShaderLang.cpp
+++ b/src/compiler/translator/ShaderLang.cpp
@@ -236,10 +236,18 @@
resources->MaxUniformBufferBindings = 32;
- // TODO(jiawei.shao@intel.com): add complete geometry shader constants.
- resources->MaxGeometryUniformComponents = 1024;
- resources->MaxGeometryOutputVertices = 256;
- resources->MaxGeometryShaderInvocations = 32;
+ resources->MaxGeometryUniformComponents = 1024;
+ resources->MaxGeometryUniformBlocks = 12;
+ resources->MaxGeometryInputComponents = 64;
+ resources->MaxGeometryOutputComponents = 64;
+ resources->MaxGeometryOutputVertices = 256;
+ resources->MaxGeometryTotalOutputComponents = 1024;
+ resources->MaxGeometryTextureImageUnits = 16;
+ resources->MaxGeometryAtomicCounterBuffers = 0;
+ resources->MaxGeometryAtomicCounters = 0;
+ resources->MaxGeometryShaderStorageBlocks = 0;
+ resources->MaxGeometryShaderInvocations = 32;
+ resources->MaxGeometryImageUniforms = 0;
}
//
@@ -365,7 +373,7 @@
return GetShaderVariables<Uniform>(handle);
}
-const std::vector<sh::Varying> *GetInputVaryings(const ShHandle handle)
+const std::vector<Varying> *GetInputVaryings(const ShHandle handle)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
if (compiler == nullptr)
@@ -375,7 +383,7 @@
return &compiler->getInputVaryings();
}
-const std::vector<sh::Varying> *GetOutputVaryings(const ShHandle handle)
+const std::vector<Varying> *GetOutputVaryings(const ShHandle handle)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
if (compiler == nullptr)
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 5d15c9b..1c2de5c 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -557,6 +557,16 @@
insert(level, new TFunction(this, NewPoolTString(name), rvalue, op));
}
+void TSymbolTable::insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
+ const char *ext,
+ TOperator op,
+ const TType *rvalue,
+ const char *name)
+{
+ insertUnmangledBuiltInName(name, level);
+ insert(level, new TFunction(this, NewPoolTString(name), rvalue, op, ext));
+}
+
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
{
if (!SupportsPrecision(type))
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 6d9b714..58788a1 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -361,10 +361,14 @@
return insert(level, constant);
}
- bool insertConstIntExt(ESymbolLevel level, const char *ext, const char *name, int value)
+ bool insertConstIntExt(ESymbolLevel level,
+ const char *ext,
+ const char *name,
+ int value,
+ TPrecision precision)
{
TVariable *constant =
- new TVariable(this, NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+ new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray[0].setIConst(value);
constant->shareConstPointer(unionArray);
@@ -451,6 +455,12 @@
const TType *rvalue,
const char *name);
+ void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
+ const char *ext,
+ TOperator op,
+ const TType *rvalue,
+ const char *name);
+
TSymbol *find(const TString &name,
int shaderVersion,
bool *builtIn = nullptr,