Commit d27f5c8d by Jiawei Shao Committed by Commit Bot

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: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 3c25ad07
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 179 #define ANGLE_SH_VERSION 180
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -415,10 +415,18 @@ struct ShBuiltInResources ...@@ -415,10 +415,18 @@ struct ShBuiltInResources
float MaxPointSize; float MaxPointSize;
// OES_geometry_shader constants // OES_geometry_shader constants
// TODO(jiawei.shao@intel.com): add complete geometry shader constants.
int MaxGeometryUniformComponents; int MaxGeometryUniformComponents;
int MaxGeometryUniformBlocks;
int MaxGeometryInputComponents;
int MaxGeometryOutputComponents;
int MaxGeometryOutputVertices; int MaxGeometryOutputVertices;
int MaxGeometryTotalOutputComponents;
int MaxGeometryTextureImageUnits;
int MaxGeometryAtomicCounterBuffers;
int MaxGeometryAtomicCounters;
int MaxGeometryShaderStorageBlocks;
int MaxGeometryShaderInvocations; int MaxGeometryShaderInvocations;
int MaxGeometryImageUniforms;
}; };
// //
......
...@@ -576,8 +576,11 @@ enum TQualifier ...@@ -576,8 +576,11 @@ enum TQualifier
// GLSL ES 3.1 extension OES_geometry_shader qualifiers // GLSL ES 3.1 extension OES_geometry_shader qualifiers
EvqGeometryIn, EvqGeometryIn,
EvqGeometryOut, EvqGeometryOut,
EvqPerVertexIn, EvqPerVertexIn, // gl_in
EvqLayer, // gl_Layer EvqPrimitiveIDIn, // gl_PrimitiveIDIn
EvqInvocationID, // gl_InvocationID
EvqPrimitiveID, // gl_PrimitiveID
EvqLayer, // gl_Layer
// end of list // end of list
EvqLast EvqLast
......
...@@ -100,6 +100,7 @@ class CollectVariablesTraverser : public TIntermTraverser ...@@ -100,6 +100,7 @@ class CollectVariablesTraverser : public TIntermTraverser
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion, int shaderVersion,
GLenum shaderType,
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior);
void visitSymbol(TIntermSymbol *symbol) override; void visitSymbol(TIntermSymbol *symbol) override;
...@@ -139,15 +140,21 @@ class CollectVariablesTraverser : public TIntermTraverser ...@@ -139,15 +140,21 @@ class CollectVariablesTraverser : public TIntermTraverser
std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields; std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
// Shader uniforms
bool mDepthRangeAdded; bool mDepthRangeAdded;
bool mPointCoordAdded;
bool mFrontFacingAdded;
bool mFragCoordAdded;
// Vertex Shader builtins
bool mInstanceIDAdded; bool mInstanceIDAdded;
bool mVertexIDAdded; bool mVertexIDAdded;
bool mPositionAdded;
bool mPointSizeAdded; bool mPointSizeAdded;
// Vertex Shader and Geometry Shader builtins
bool mPositionAdded;
// Fragment Shader builtins
bool mPointCoordAdded;
bool mFrontFacingAdded;
bool mFragCoordAdded;
bool mLastFragDataAdded; bool mLastFragDataAdded;
bool mFragColorAdded; bool mFragColorAdded;
bool mFragDataAdded; bool mFragDataAdded;
...@@ -156,11 +163,19 @@ class CollectVariablesTraverser : public TIntermTraverser ...@@ -156,11 +163,19 @@ class CollectVariablesTraverser : public TIntermTraverser
bool mSecondaryFragColorEXTAdded; bool mSecondaryFragColorEXTAdded;
bool mSecondaryFragDataEXTAdded; bool mSecondaryFragDataEXTAdded;
// Geometry Shader builtins
bool mPerVertexInAdded; bool mPerVertexInAdded;
bool mPrimitiveIDInAdded;
bool mInvocationIDAdded;
// Geometry Shader and Fragment Shader builtins
bool mPrimitiveIDAdded;
bool mLayerAdded;
ShHashFunction64 mHashFunction; ShHashFunction64 mHashFunction;
int mShaderVersion; int mShaderVersion;
GLenum mShaderType;
const TExtensionBehavior &mExtensionBehavior; const TExtensionBehavior &mExtensionBehavior;
}; };
...@@ -176,6 +191,7 @@ CollectVariablesTraverser::CollectVariablesTraverser( ...@@ -176,6 +191,7 @@ CollectVariablesTraverser::CollectVariablesTraverser(
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion, int shaderVersion,
GLenum shaderType,
const TExtensionBehavior &extensionBehavior) const TExtensionBehavior &extensionBehavior)
: TIntermTraverser(true, false, false, symbolTable), : TIntermTraverser(true, false, false, symbolTable),
mAttribs(attribs), mAttribs(attribs),
...@@ -187,13 +203,13 @@ CollectVariablesTraverser::CollectVariablesTraverser( ...@@ -187,13 +203,13 @@ CollectVariablesTraverser::CollectVariablesTraverser(
mShaderStorageBlocks(shaderStorageBlocks), mShaderStorageBlocks(shaderStorageBlocks),
mInBlocks(inBlocks), mInBlocks(inBlocks),
mDepthRangeAdded(false), mDepthRangeAdded(false),
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
mInstanceIDAdded(false), mInstanceIDAdded(false),
mVertexIDAdded(false), mVertexIDAdded(false),
mPositionAdded(false),
mPointSizeAdded(false), mPointSizeAdded(false),
mPositionAdded(false),
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
mLastFragDataAdded(false), mLastFragDataAdded(false),
mFragColorAdded(false), mFragColorAdded(false),
mFragDataAdded(false), mFragDataAdded(false),
...@@ -202,8 +218,13 @@ CollectVariablesTraverser::CollectVariablesTraverser( ...@@ -202,8 +218,13 @@ CollectVariablesTraverser::CollectVariablesTraverser(
mSecondaryFragColorEXTAdded(false), mSecondaryFragColorEXTAdded(false),
mSecondaryFragDataEXTAdded(false), mSecondaryFragDataEXTAdded(false),
mPerVertexInAdded(false), mPerVertexInAdded(false),
mPrimitiveIDInAdded(false),
mInvocationIDAdded(false),
mPrimitiveIDAdded(false),
mLayerAdded(false),
mHashFunction(hashFunction), mHashFunction(hashFunction),
mShaderVersion(shaderVersion), mShaderVersion(shaderVersion),
mShaderType(shaderType),
mExtensionBehavior(extensionBehavior) mExtensionBehavior(extensionBehavior)
{ {
} }
...@@ -470,6 +491,38 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) ...@@ -470,6 +491,38 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT", recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
&mSecondaryFragDataEXTAdded); &mSecondaryFragDataEXTAdded);
return; 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: default:
break; break;
} }
...@@ -783,11 +836,13 @@ void CollectVariables(TIntermBlock *root, ...@@ -783,11 +836,13 @@ void CollectVariables(TIntermBlock *root,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion, int shaderVersion,
GLenum shaderType,
const TExtensionBehavior &extensionBehavior) const TExtensionBehavior &extensionBehavior)
{ {
CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings, CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks, outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
hashFunction, symbolTable, shaderVersion, extensionBehavior); hashFunction, symbolTable, shaderVersion, shaderType,
extensionBehavior);
root->traverse(&collect); root->traverse(&collect);
} }
......
...@@ -30,6 +30,7 @@ void CollectVariables(TIntermBlock *root, ...@@ -30,6 +30,7 @@ void CollectVariables(TIntermBlock *root,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion, int shaderVersion,
GLenum shaderType,
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior);
} }
......
...@@ -476,7 +476,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -476,7 +476,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
ASSERT(!variablesCollected); ASSERT(!variablesCollected);
CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings, CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
&outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks, &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
hashFunction, &symbolTable, shaderVersion, extensionBehavior); hashFunction, &symbolTable, shaderVersion, shaderType,
extensionBehavior);
collectInterfaceBlocks(); collectInterfaceBlocks();
variablesCollected = true; variablesCollected = true;
if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
...@@ -740,9 +741,18 @@ void TCompiler::setResourceString() ...@@ -740,9 +741,18 @@ void TCompiler::setResourceString()
<< ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
<< ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
<< ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
<< ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
<< ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents << ":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 // clang-format on
builtInResourcesString = strstream.str(); builtInResourcesString = strstream.str();
...@@ -1010,7 +1020,7 @@ void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root) ...@@ -1010,7 +1020,7 @@ void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
void TCompiler::initializeOutputVariables(TIntermBlock *root) void TCompiler::initializeOutputVariables(TIntermBlock *root)
{ {
InitVariableList list; InitVariableList list;
if (shaderType == GL_VERTEX_SHADER) if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES)
{ {
for (auto var : outputVaryings) for (auto var : outputVaryings)
{ {
......
...@@ -676,6 +676,15 @@ void InsertBuiltInFunctions(sh::GLenum type, ...@@ -676,6 +676,15 @@ void InsertBuiltInFunctions(sh::GLenum type,
voidType, "groupMemoryBarrier"); 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 // Depth range in window coordinates
// //
...@@ -720,7 +729,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ...@@ -720,7 +729,7 @@ void InsertBuiltInFunctions(sh::GLenum type,
{ {
symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended", symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended",
"gl_MaxDualSourceDrawBuffersEXT", "gl_MaxDualSourceDrawBuffersEXT",
resources.MaxDualSourceDrawBuffers); resources.MaxDualSourceDrawBuffers, EbpMedium);
} }
symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors",
...@@ -777,6 +786,29 @@ void InsertBuiltInFunctions(sh::GLenum type, ...@@ -777,6 +786,29 @@ void InsertBuiltInFunctions(sh::GLenum type,
resources.MaxCombinedAtomicCounterBuffers, EbpMedium); resources.MaxCombinedAtomicCounterBuffers, EbpMedium);
symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize", symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize",
resources.MaxAtomicCounterBufferSize, EbpMedium); 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, void IdentifyBuiltIns(sh::GLenum type,
...@@ -872,6 +904,15 @@ void IdentifyBuiltIns(sh::GLenum type, ...@@ -872,6 +904,15 @@ void IdentifyBuiltIns(sh::GLenum type,
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)); 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; break;
} }
case GL_VERTEX_SHADER: case GL_VERTEX_SHADER:
...@@ -909,7 +950,6 @@ void IdentifyBuiltIns(sh::GLenum type, ...@@ -909,7 +950,6 @@ void IdentifyBuiltIns(sh::GLenum type,
case GL_GEOMETRY_SHADER_OES: case GL_GEOMETRY_SHADER_OES:
{ {
// TODO(jiawei.shao@intel.com): add all Geometry Shader built-in variables.
const char *extension = "GL_OES_geometry_shader"; const char *extension = "GL_OES_geometry_shader";
// Add built-in interface block gl_PerVertex and the built-in array gl_in. // Add built-in interface block gl_PerVertex and the built-in array gl_in.
...@@ -932,6 +972,20 @@ void IdentifyBuiltIns(sh::GLenum type, ...@@ -932,6 +972,20 @@ void IdentifyBuiltIns(sh::GLenum type,
glInType.makeArray(0u); glInType.makeArray(0u);
symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType); 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; break;
} }
default: default:
......
...@@ -341,6 +341,11 @@ const char *GetOperatorString(TOperator op) ...@@ -341,6 +341,11 @@ const char *GetOperatorString(TOperator op)
return "memoryBarrierShared"; return "memoryBarrierShared";
case EOpGroupMemoryBarrier: case EOpGroupMemoryBarrier:
return "groupMemoryBarrier"; return "groupMemoryBarrier";
case EOpEmitVertex:
return "EmitVertex";
case EOpEndPrimitive:
return "EndPrimitive";
default: default:
break; break;
} }
......
...@@ -237,7 +237,11 @@ enum TOperator ...@@ -237,7 +237,11 @@ enum TOperator
EOpMemoryBarrierBuffer, EOpMemoryBarrierBuffer,
EOpMemoryBarrierImage, EOpMemoryBarrierImage,
EOpMemoryBarrierShared, EOpMemoryBarrierShared,
EOpGroupMemoryBarrier EOpGroupMemoryBarrier,
// Geometry only
EOpEmitVertex,
EOpEndPrimitive
}; };
// Returns the string corresponding to the operator in GLSL // Returns the string corresponding to the operator in GLSL
......
...@@ -1006,6 +1006,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1006,6 +1006,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpMemoryBarrierImage: case EOpMemoryBarrierImage:
case EOpMemoryBarrierShared: case EOpMemoryBarrierShared:
case EOpGroupMemoryBarrier: case EOpGroupMemoryBarrier:
case EOpEmitVertex:
case EOpEndPrimitive:
writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction()); writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
break; break;
default: default:
......
...@@ -521,6 +521,24 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn ...@@ -521,6 +521,24 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn
case EvqPerVertexIn: case EvqPerVertexIn:
message = "can't modify any member in gl_in"; message = "can't modify any member in gl_in";
break; 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: default:
// //
// Type that can't be written to? // Type that can't be written to?
......
...@@ -236,10 +236,18 @@ void InitBuiltInResources(ShBuiltInResources *resources) ...@@ -236,10 +236,18 @@ void InitBuiltInResources(ShBuiltInResources *resources)
resources->MaxUniformBufferBindings = 32; resources->MaxUniformBufferBindings = 32;
// TODO(jiawei.shao@intel.com): add complete geometry shader constants. resources->MaxGeometryUniformComponents = 1024;
resources->MaxGeometryUniformComponents = 1024; resources->MaxGeometryUniformBlocks = 12;
resources->MaxGeometryOutputVertices = 256; resources->MaxGeometryInputComponents = 64;
resources->MaxGeometryShaderInvocations = 32; 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 @@ const std::vector<Uniform> *GetUniforms(const ShHandle handle) ...@@ -365,7 +373,7 @@ const std::vector<Uniform> *GetUniforms(const ShHandle handle)
return GetShaderVariables<Uniform>(handle); 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); TCompiler *compiler = GetCompilerFromHandle(handle);
if (compiler == nullptr) if (compiler == nullptr)
...@@ -375,7 +383,7 @@ const std::vector<sh::Varying> *GetInputVaryings(const ShHandle handle) ...@@ -375,7 +383,7 @@ const std::vector<sh::Varying> *GetInputVaryings(const ShHandle handle)
return &compiler->getInputVaryings(); return &compiler->getInputVaryings();
} }
const std::vector<sh::Varying> *GetOutputVaryings(const ShHandle handle) const std::vector<Varying> *GetOutputVaryings(const ShHandle handle)
{ {
TCompiler *compiler = GetCompilerFromHandle(handle); TCompiler *compiler = GetCompilerFromHandle(handle);
if (compiler == nullptr) if (compiler == nullptr)
......
...@@ -557,6 +557,16 @@ void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level, ...@@ -557,6 +557,16 @@ void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level,
insert(level, new TFunction(this, NewPoolTString(name), rvalue, op)); 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 TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
{ {
if (!SupportsPrecision(type)) if (!SupportsPrecision(type))
......
...@@ -361,10 +361,14 @@ class TSymbolTable : angle::NonCopyable ...@@ -361,10 +361,14 @@ class TSymbolTable : angle::NonCopyable
return insert(level, constant); 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 = 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]; TConstantUnion *unionArray = new TConstantUnion[1];
unionArray[0].setIConst(value); unionArray[0].setIConst(value);
constant->shareConstPointer(unionArray); constant->shareConstPointer(unionArray);
...@@ -451,6 +455,12 @@ class TSymbolTable : angle::NonCopyable ...@@ -451,6 +455,12 @@ class TSymbolTable : angle::NonCopyable
const TType *rvalue, const TType *rvalue,
const char *name); const char *name);
void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
const char *ext,
TOperator op,
const TType *rvalue,
const char *name);
TSymbol *find(const TString &name, TSymbol *find(const TString &name,
int shaderVersion, int shaderVersion,
bool *builtIn = nullptr, bool *builtIn = nullptr,
......
...@@ -131,10 +131,12 @@ class CollectFragmentVariablesTest : public CollectVariablesTest ...@@ -131,10 +131,12 @@ class CollectFragmentVariablesTest : public CollectVariablesTest
CollectFragmentVariablesTest() : CollectVariablesTest(GL_FRAGMENT_SHADER) {} CollectFragmentVariablesTest() : CollectVariablesTest(GL_FRAGMENT_SHADER) {}
}; };
class CollectGeometryVariablesTest : public CollectVariablesTest class CollectVariablesOESGeometryShaderTest : public CollectVariablesTest
{ {
public: public:
CollectGeometryVariablesTest() : CollectVariablesTest(GL_GEOMETRY_SHADER_OES) {} CollectVariablesOESGeometryShaderTest(sh::GLenum shaderType) : CollectVariablesTest(shaderType)
{
}
protected: protected:
void SetUp() override void SetUp() override
...@@ -152,7 +154,16 @@ class CollectGeometryVariablesTest : public CollectVariablesTest ...@@ -152,7 +154,16 @@ class CollectGeometryVariablesTest : public CollectVariablesTest
new TranslatorGLSL(mShaderType, SH_GLES3_1_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT)); new TranslatorGLSL(mShaderType, SH_GLES3_1_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT));
ASSERT_TRUE(mTranslator->Init(resources)); ASSERT_TRUE(mTranslator->Init(resources));
} }
};
class CollectGeometryVariablesTest : public CollectVariablesOESGeometryShaderTest
{
public:
CollectGeometryVariablesTest() : CollectVariablesOESGeometryShaderTest(GL_GEOMETRY_SHADER_OES)
{
}
protected:
void compileGeometryShaderWithInputPrimitive(const std::string &inputPrimitive) void compileGeometryShaderWithInputPrimitive(const std::string &inputPrimitive)
{ {
std::ostringstream sstream; std::ostringstream sstream;
...@@ -168,6 +179,15 @@ class CollectGeometryVariablesTest : public CollectVariablesTest ...@@ -168,6 +179,15 @@ class CollectGeometryVariablesTest : public CollectVariablesTest
} }
}; };
class CollectFragmentVariablesOESGeometryShaderTest : public CollectVariablesOESGeometryShaderTest
{
public:
CollectFragmentVariablesOESGeometryShaderTest()
: CollectVariablesOESGeometryShaderTest(GL_FRAGMENT_SHADER)
{
}
};
TEST_F(CollectFragmentVariablesTest, SimpleOutputVar) TEST_F(CollectFragmentVariablesTest, SimpleOutputVar)
{ {
const std::string &shaderString = const std::string &shaderString =
...@@ -927,3 +947,243 @@ TEST_F(CollectGeometryVariablesTest, GLInArraySize) ...@@ -927,3 +947,243 @@ TEST_F(CollectGeometryVariablesTest, GLInArraySize)
EXPECT_EQ(kArraySizeForInputPrimitives[i], inBlock->arraySize); EXPECT_EQ(kArraySizeForInputPrimitives[i], inBlock->arraySize);
} }
} }
// Test collecting gl_PrimitiveIDIn in a geometry shader.
TEST_F(CollectGeometryVariablesTest, CollectPrimitiveIDIn)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" int value = gl_PrimitiveIDIn;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
ASSERT_TRUE(mTranslator->getInBlocks().empty());
const auto &inputVaryings = mTranslator->getInputVaryings();
ASSERT_EQ(1u, inputVaryings.size());
const Varying *varying = &inputVaryings[0];
EXPECT_EQ("gl_PrimitiveIDIn", varying->name);
EXPECT_FALSE(varying->isArray());
EXPECT_FALSE(varying->isStruct());
EXPECT_TRUE(varying->staticUse);
EXPECT_TRUE(varying->isBuiltIn());
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
EXPECT_GLENUM_EQ(GL_INT, varying->type);
}
// Test collecting gl_InvocationID in a geometry shader.
TEST_F(CollectGeometryVariablesTest, CollectInvocationID)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points, invocations = 2) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" int value = gl_InvocationID;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
ASSERT_TRUE(mTranslator->getInBlocks().empty());
const auto &inputVaryings = mTranslator->getInputVaryings();
ASSERT_EQ(1u, inputVaryings.size());
const Varying *varying = &inputVaryings[0];
EXPECT_EQ("gl_InvocationID", varying->name);
EXPECT_FALSE(varying->isArray());
EXPECT_FALSE(varying->isStruct());
EXPECT_TRUE(varying->staticUse);
EXPECT_TRUE(varying->isBuiltIn());
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
EXPECT_GLENUM_EQ(GL_INT, varying->type);
}
// Test collecting gl_in in a geometry shader when gl_in is indexed by an expression.
TEST_F(CollectGeometryVariablesTest, CollectGLInIndexedByExpression)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (triangles, invocations = 2) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" vec4 value = gl_in[gl_InvocationID + 1].gl_Position;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
const auto &inBlocks = mTranslator->getInBlocks();
ASSERT_EQ(1u, inBlocks.size());
const InterfaceBlock *inBlock = &inBlocks[0];
EXPECT_EQ("gl_PerVertex", inBlock->name);
EXPECT_EQ("gl_in", inBlock->instanceName);
const auto &inputVaryings = mTranslator->getInputVaryings();
ASSERT_EQ(1u, inputVaryings.size());
const Varying *glInvocationID = &inputVaryings[0];
EXPECT_EQ("gl_InvocationID", glInvocationID->name);
}
// Test collecting gl_Position in a geometry shader.
TEST_F(CollectGeometryVariablesTest, CollectPosition)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(0.1, 0.2, 0.3, 1);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getInputVaryings().empty());
ASSERT_TRUE(mTranslator->getInBlocks().empty());
const auto &outputVaryings = mTranslator->getOutputVaryings();
ASSERT_EQ(1u, outputVaryings.size());
const Varying *varying = &outputVaryings[0];
EXPECT_EQ("gl_Position", varying->name);
EXPECT_FALSE(varying->isArray());
EXPECT_FALSE(varying->isStruct());
EXPECT_TRUE(varying->staticUse);
EXPECT_TRUE(varying->isBuiltIn());
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying->precision);
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying->type);
}
// Test collecting gl_PrimitiveID in a geometry shader.
TEST_F(CollectGeometryVariablesTest, CollectPrimitiveID)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" gl_PrimitiveID = 100;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getInputVaryings().empty());
ASSERT_TRUE(mTranslator->getInBlocks().empty());
const auto &OutputVaryings = mTranslator->getOutputVaryings();
ASSERT_EQ(1u, OutputVaryings.size());
const Varying *varying = &OutputVaryings[0];
EXPECT_EQ("gl_PrimitiveID", varying->name);
EXPECT_FALSE(varying->isArray());
EXPECT_FALSE(varying->isStruct());
EXPECT_TRUE(varying->staticUse);
EXPECT_TRUE(varying->isBuiltIn());
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
EXPECT_GLENUM_EQ(GL_INT, varying->type);
}
// Test collecting gl_Layer in a geometry shader.
TEST_F(CollectGeometryVariablesTest, CollectLayer)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" gl_Layer = 2;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getInputVaryings().empty());
ASSERT_TRUE(mTranslator->getInBlocks().empty());
const auto &OutputVaryings = mTranslator->getOutputVaryings();
ASSERT_EQ(1u, OutputVaryings.size());
const Varying *varying = &OutputVaryings[0];
EXPECT_EQ("gl_Layer", varying->name);
EXPECT_FALSE(varying->isArray());
EXPECT_FALSE(varying->isStruct());
EXPECT_TRUE(varying->staticUse);
EXPECT_TRUE(varying->isBuiltIn());
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
EXPECT_GLENUM_EQ(GL_INT, varying->type);
}
// Test collecting gl_PrimitiveID in a fragment shader.
TEST_F(CollectFragmentVariablesOESGeometryShaderTest, CollectPrimitiveID)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"void main()\n"
"{\n"
" int value = gl_PrimitiveID;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
const auto &inputVaryings = mTranslator->getInputVaryings();
ASSERT_EQ(1u, inputVaryings.size());
const Varying *varying = &inputVaryings[0];
EXPECT_EQ("gl_PrimitiveID", varying->name);
EXPECT_FALSE(varying->isArray());
EXPECT_FALSE(varying->isStruct());
EXPECT_TRUE(varying->staticUse);
EXPECT_TRUE(varying->isBuiltIn());
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
EXPECT_GLENUM_EQ(GL_INT, varying->type);
}
// Test collecting gl_Layer in a fragment shader.
TEST_F(CollectFragmentVariablesOESGeometryShaderTest, CollectLayer)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"void main()\n"
"{\n"
" int value = gl_Layer;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
const auto &inputVaryings = mTranslator->getInputVaryings();
ASSERT_EQ(1u, inputVaryings.size());
const Varying *varying = &inputVaryings[0];
EXPECT_EQ("gl_Layer", varying->name);
EXPECT_FALSE(varying->isArray());
EXPECT_FALSE(varying->isStruct());
EXPECT_TRUE(varying->staticUse);
EXPECT_TRUE(varying->isBuiltIn());
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
EXPECT_GLENUM_EQ(GL_INT, varying->type);
}
...@@ -986,3 +986,173 @@ TEST_F(GeometryShaderTest, AssignValueToGLIn) ...@@ -986,3 +986,173 @@ TEST_F(GeometryShaderTest, AssignValueToGLIn)
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
} }
} }
// Verify Geometry Shader supports all required built-in variables.
TEST_F(GeometryShaderTest, BuiltInVariables)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points, invocations = 2) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
" int invocation = gl_InvocationID;\n"
" gl_Layer = invocation;\n"
" int primitiveIn = gl_PrimitiveIDIn;\n"
" gl_PrimitiveID = primitiveIn;\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Verify that gl_PrimitiveIDIn cannot be l-value.
TEST_F(GeometryShaderTest, AssignValueToGLPrimitiveIn)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points, invocations = 2) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" gl_PrimitiveIDIn = 1;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Verify that gl_InvocationID cannot be l-value.
TEST_F(GeometryShaderTest, AssignValueToGLInvocations)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points, invocations = 2) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" gl_InvocationID = 1;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Verify that both EmitVertex() and EndPrimitive() are supported in Geometry Shader.
TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctions)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" gl_Position = gl_in[0].gl_Position;\n"
" EmitVertex();\n"
" EndPrimitive();\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Verify that using EmitVertex() or EndPrimitive() without GL_OES_geometry_shader declared causes a
// compile error.
TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctionsWithoutExtension)
{
const std::string &shaderString1 =
"#version 310 es\n"
"void main()\n"
"{\n"
" EmitVertex();\n"
"}\n";
const std::string &shaderString2 =
"#version 310 es\n"
"void main()\n"
"{\n"
" EndPrimitive();\n"
"}\n";
if (compile(shaderString1) || compile(shaderString2))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Verify that all required built-in constant values are supported in Geometry Shaders
TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstants)
{
const std::string &kShaderHeader =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"layout (points) in;\n"
"layout (points, max_vertices = 2) out;\n"
"void main()\n"
"{\n"
" int val = ";
const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
"gl_MaxGeometryInputComponents", "gl_MaxGeometryOutputComponents",
"gl_MaxGeometryImageUniforms", "gl_MaxGeometryTextureImageUnits",
"gl_MaxGeometryOutputVertices", "gl_MaxGeometryTotalOutputComponents",
"gl_MaxGeometryUniformComponents", "gl_MaxGeometryAtomicCounters",
"gl_MaxGeometryAtomicCounterBuffers",
}};
const std::string &kShaderTail =
";\n"
"}\n";
for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
{
std::ostringstream ostream;
ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
if (!compile(ostream.str()))
{
FAIL() << "Shader compilation failed, expecting success: \n" << mInfoLog;
}
}
}
// Verify that using any Geometry Shader built-in constant values without GL_OES_geometry_shader
// declared causes a compile error.
TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstantsWithoutExtension)
{
const std::string &kShaderHeader =
"#version 310 es\n"
"void main()\n"
"{\n"
" int val = ";
const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
"gl_MaxGeometryInputComponents", "gl_MaxGeometryOutputComponents",
"gl_MaxGeometryImageUniforms", "gl_MaxGeometryTextureImageUnits",
"gl_MaxGeometryOutputVertices", "gl_MaxGeometryTotalOutputComponents",
"gl_MaxGeometryUniformComponents", "gl_MaxGeometryAtomicCounters",
"gl_MaxGeometryAtomicCounterBuffers",
}};
const std::string &kShaderTail =
";\n"
"}\n";
for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
{
std::ostringstream ostream;
ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
if (compile(ostream.str()))
{
FAIL() << "Shader compilation succeeded, expecting failure: \n" << mInfoLog;
}
}
}
...@@ -107,6 +107,18 @@ class GeometryShaderValidationTest : public ShaderCompileTreeTest ...@@ -107,6 +107,18 @@ class GeometryShaderValidationTest : public ShaderCompileTreeTest
ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
}; };
class FragmentShaderOESGeometryShaderValidationTest : public FragmentShaderValidationTest
{
public:
FragmentShaderOESGeometryShaderValidationTest() {}
protected:
void initResources(ShBuiltInResources *resources) override
{
resources->OES_geometry_shader = 1;
}
};
// This is a test for a bug that used to exist in ANGLE: // This is a test for a bug that used to exist in ANGLE:
// Calling a function with all parameters missing should not succeed. // Calling a function with all parameters missing should not succeed.
TEST_F(FragmentShaderValidationTest, FunctionParameterMismatch) TEST_F(FragmentShaderValidationTest, FunctionParameterMismatch)
...@@ -4418,3 +4430,199 @@ TEST_F(VertexShaderValidationTest, ViewportIndexInESSL310) ...@@ -4418,3 +4430,199 @@ TEST_F(VertexShaderValidationTest, ViewportIndexInESSL310)
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
} }
} }
// Test that gl_PrimitiveID is valid in fragment shader with 'GL_OES_geometry_shader' declared.
TEST_F(FragmentShaderOESGeometryShaderValidationTest, PrimitiveIDWithExtension)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" vec4 data = vec4(0.1, 0.2, 0.3, 0.4);\n"
" float value = data[gl_PrimitiveID % 4];\n"
" fragColor = vec4(value, 0, 0, 1);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Test that gl_PrimitiveID is invalid in fragment shader without 'GL_OES_geometry_shader' declared.
TEST_F(FragmentShaderOESGeometryShaderValidationTest, PrimitiveIDWithoutExtension)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" vec4 data = vec4(0.1, 0.2, 0.3, 0.4);\n"
" float value = data[gl_PrimitiveID % 4];\n"
" fragColor = vec4(value, 0, 0, 1);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that gl_PrimitiveID cannot be l-value in fragment shader.
TEST_F(FragmentShaderOESGeometryShaderValidationTest, AssignValueToPrimitiveID)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" gl_PrimitiveID = 1;\n"
" fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that gl_Layer is valid in fragment shader with 'GL_OES_geometry_shader' declared.
TEST_F(FragmentShaderOESGeometryShaderValidationTest, LayerWithExtension)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" vec4 data = vec4(0.1, 0.2, 0.3, 0.4);\n"
" float value = data[gl_Layer % 4];\n"
" fragColor = vec4(value, 0, 0, 1);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Test that gl_Layer is invalid in fragment shader without 'GL_OES_geometry_shader' declared.
TEST_F(FragmentShaderOESGeometryShaderValidationTest, LayerWithoutExtension)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" vec4 data = vec4(0.1, 0.2, 0.3, 0.4);\n"
" float value = data[gl_Layer % 4];\n"
" fragColor = vec4(value, 0, 0, 1);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that gl_Layer cannot be l-value in fragment shader.
TEST_F(FragmentShaderOESGeometryShaderValidationTest, AssignValueToLayer)
{
const std::string &shaderString =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" gl_Layer = 1;\n"
" fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that all built-in constants defined in GL_OES_geometry_shader can be used in fragment shader
// with 'GL_OES_geometry_shader' declared.
TEST_F(FragmentShaderOESGeometryShaderValidationTest, GeometryShaderBuiltInConstants)
{
const std::string &kShaderHeader =
"#version 310 es\n"
"#extension GL_OES_geometry_shader : require\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" int val = ";
const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
"gl_MaxGeometryInputComponents", "gl_MaxGeometryOutputComponents",
"gl_MaxGeometryImageUniforms", "gl_MaxGeometryTextureImageUnits",
"gl_MaxGeometryOutputVertices", "gl_MaxGeometryTotalOutputComponents",
"gl_MaxGeometryUniformComponents", "gl_MaxGeometryAtomicCounters",
"gl_MaxGeometryAtomicCounterBuffers",
}};
const std::string &kShaderTail =
";\n"
" fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
{
std::ostringstream ostream;
ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
if (!compile(ostream.str()))
{
FAIL() << "Shader compilation failed, expecting success: \n" << mInfoLog;
}
}
}
// Test that any built-in constants defined in GL_OES_geometry_shader cannot be used in fragment
// shader without 'GL_OES_geometry_shader' declared.
TEST_F(FragmentShaderOESGeometryShaderValidationTest,
GeometryShaderBuiltInConstantsWithoutExtension)
{
const std::string &kShaderHeader =
"#version 310 es\n"
"precision mediump float;\n"
"layout(location = 0) out mediump vec4 fragColor;\n"
"void main(void)\n"
"{\n"
" int val = ";
const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
"gl_MaxGeometryInputComponents", "gl_MaxGeometryOutputComponents",
"gl_MaxGeometryImageUniforms", "gl_MaxGeometryTextureImageUnits",
"gl_MaxGeometryOutputVertices", "gl_MaxGeometryTotalOutputComponents",
"gl_MaxGeometryUniformComponents", "gl_MaxGeometryAtomicCounters",
"gl_MaxGeometryAtomicCounterBuffers",
}};
const std::string &kShaderTail =
";\n"
" fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
{
std::ostringstream ostream;
ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
if (compile(ostream.str()))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
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