ES31: Implement gl_in in Geometry Shader
This patch intends to implement geometry shader built-in interface
block instance gl_in defined in GL_OES_geometry_shader.
1. Add the definition of gl_in and its interface block gl_PerVertex
into the symbol table.
2. Support gl_Position as a member of gl_in.
3. Set the array size of gl_in when a valid input primitive type is
known.
4. Add check that it should be a compile error to index gl_in or
call length() on gl_in without a valid input primitive declaration.
This patch also adds unit tests to cover all these new features.
BUG=angleproject:1941
TEST=angle_unittests
Change-Id: I8da20c943b29c9ce904834625b396aab6302e1e1
Reviewed-on: https://chromium-review.googlesource.com/605059
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index 336f3b7..00f1108 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -576,6 +576,7 @@
// GLSL ES 3.1 extension OES_geometry_shader qualifiers
EvqGeometryIn,
EvqGeometryOut,
+ EvqPerVertexIn,
EvqLayer, // gl_Layer
// end of list
@@ -832,6 +833,7 @@
case EvqWriteOnly: return "writeonly";
case EvqGeometryIn: return "in";
case EvqGeometryOut: return "out";
+ case EvqPerVertexIn: return "gl_in";
default: UNREACHABLE(); return "unknown qualifier";
}
// clang-format on
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 4ffae59..5815940 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -36,6 +36,7 @@
}
}
+// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
BlockType GetBlockType(TQualifier qualifier)
{
switch (qualifier)
@@ -44,6 +45,8 @@
return BlockType::BLOCK_UNIFORM;
case EvqBuffer:
return BlockType::BLOCK_BUFFER;
+ case EvqPerVertexIn:
+ return BlockType::BLOCK_IN;
default:
UNREACHABLE();
return BlockType::BLOCK_UNIFORM;
@@ -93,6 +96,7 @@
std::vector<Varying> *outputVaryings,
std::vector<InterfaceBlock> *uniformBlocks,
std::vector<InterfaceBlock> *shaderStorageBlocks,
+ std::vector<InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
@@ -110,7 +114,8 @@
Attribute recordAttribute(const TIntermSymbol &variable) const;
OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
Varying recordVarying(const TIntermSymbol &variable) const;
- InterfaceBlock recordInterfaceBlock(const TIntermSymbol &variable) const;
+ void recordInterfaceBlock(const TType &interfaceBlockType,
+ InterfaceBlock *interfaceBlock) const;
Uniform recordUniform(const TIntermSymbol &variable) const;
void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info);
@@ -120,6 +125,8 @@
std::vector<Varying> *varyings);
void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag);
void recordBuiltInAttributeUsed(const char *name, bool *addedFlag);
+ InterfaceBlock *recordGLInUsed(const TType &glInType);
+ InterfaceBlock *findNamedInterfaceBlock(const TString &name) const;
std::vector<Attribute> *mAttribs;
std::vector<OutputVariable> *mOutputVariables;
@@ -128,6 +135,7 @@
std::vector<Varying> *mOutputVaryings;
std::vector<InterfaceBlock> *mUniformBlocks;
std::vector<InterfaceBlock> *mShaderStorageBlocks;
+ std::vector<InterfaceBlock> *mInBlocks;
std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
@@ -148,6 +156,8 @@
bool mSecondaryFragColorEXTAdded;
bool mSecondaryFragDataEXTAdded;
+ bool mPerVertexInAdded;
+
ShHashFunction64 mHashFunction;
int mShaderVersion;
@@ -162,6 +172,7 @@
std::vector<sh::Varying> *outputVaryings,
std::vector<sh::InterfaceBlock> *uniformBlocks,
std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
+ std::vector<sh::InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
@@ -174,6 +185,7 @@
mOutputVaryings(outputVaryings),
mUniformBlocks(uniformBlocks),
mShaderStorageBlocks(shaderStorageBlocks),
+ mInBlocks(inBlocks),
mDepthRangeAdded(false),
mPointCoordAdded(false),
mFrontFacingAdded(false),
@@ -189,6 +201,7 @@
mFragDepthAdded(false),
mSecondaryFragColorEXTAdded(false),
mSecondaryFragDataEXTAdded(false),
+ mPerVertexInAdded(false),
mHashFunction(hashFunction),
mShaderVersion(shaderVersion),
mExtensionBehavior(extensionBehavior)
@@ -251,6 +264,25 @@
}
}
+InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
+{
+ if (!mPerVertexInAdded)
+ {
+ ASSERT(glInType.getQualifier() == EvqPerVertexIn);
+ InterfaceBlock info;
+ recordInterfaceBlock(glInType, &info);
+ info.staticUse = true;
+
+ mPerVertexInAdded = true;
+ mInBlocks->push_back(info);
+ return &mInBlocks->back();
+ }
+ else
+ {
+ return FindVariable("gl_PerVertex", mInBlocks);
+ }
+}
+
// We want to check whether a uniform/varying is statically used
// because we only count the used ones in packing computing.
// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
@@ -535,21 +567,30 @@
return varying;
}
-InterfaceBlock CollectVariablesTraverser::recordInterfaceBlock(const TIntermSymbol &variable) const
+// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
+void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlockType,
+ InterfaceBlock *interfaceBlock) const
{
- const TInterfaceBlock *blockType = variable.getType().getInterfaceBlock();
+ ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
+ ASSERT(interfaceBlock);
+
+ const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
ASSERT(blockType);
- InterfaceBlock interfaceBlock;
- interfaceBlock.name = blockType->name().c_str();
- interfaceBlock.mappedName = HashName(blockType->name().c_str(), mHashFunction).c_str();
- interfaceBlock.instanceName =
+ interfaceBlock->name = blockType->name().c_str();
+ interfaceBlock->mappedName = HashName(blockType->name().c_str(), mHashFunction).c_str();
+ interfaceBlock->instanceName =
(blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
- interfaceBlock.arraySize = variable.getArraySize();
- interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
- interfaceBlock.binding = blockType->blockBinding();
- interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
- interfaceBlock.blockType = GetBlockType(variable.getType().getQualifier());
+ interfaceBlock->arraySize = interfaceBlockType.getArraySize();
+
+ interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
+ if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
+ interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
+ {
+ interfaceBlock->isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
+ interfaceBlock->binding = blockType->blockBinding();
+ interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
+ }
// Gather field information
for (const TField *field : blockType->fields())
@@ -560,9 +601,8 @@
setCommonVariableProperties(fieldType, field->name(), &fieldVariable);
fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
- interfaceBlock.fields.push_back(fieldVariable);
+ interfaceBlock->fields.push_back(fieldVariable);
}
- return interfaceBlock;
}
Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
@@ -605,15 +645,22 @@
continue;
}
+ // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
if (typedNode.getBasicType() == EbtInterfaceBlock)
{
- if (qualifier == EvqUniform)
+ InterfaceBlock interfaceBlock;
+ recordInterfaceBlock(variable.getType(), &interfaceBlock);
+
+ switch (qualifier)
{
- mUniformBlocks->push_back(recordInterfaceBlock(variable));
- }
- else if (qualifier == EvqBuffer)
- {
- mShaderStorageBlocks->push_back(recordInterfaceBlock(variable));
+ case EvqUniform:
+ mUniformBlocks->push_back(interfaceBlock);
+ break;
+ case EvqBuffer:
+ mShaderStorageBlocks->push_back(interfaceBlock);
+ break;
+ default:
+ UNREACHABLE();
}
}
else
@@ -650,6 +697,18 @@
return false;
}
+// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
+// GL_OES_shader_io_blocks.
+InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &blockName) const
+{
+ InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
+ if (!namedBlock)
+ {
+ namedBlock = FindVariable(blockName, mShaderStorageBlocks);
+ }
+ return namedBlock;
+}
+
bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
{
if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
@@ -661,17 +720,43 @@
TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
ASSERT(constantUnion);
+ InterfaceBlock *namedBlock = nullptr;
+
+ bool traverseIndexExpression = false;
+ TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
+ if (interfaceIndexingNode)
+ {
+ TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
+ ASSERT(interfaceNode);
+
+ const TType &interfaceType = interfaceNode->getType();
+ if (interfaceType.getQualifier() == EvqPerVertexIn)
+ {
+ namedBlock = recordGLInUsed(interfaceType);
+ ASSERT(namedBlock);
+
+ // We need to continue traversing to collect useful variables in the index
+ // expression of gl_in.
+ traverseIndexExpression = true;
+ }
+ }
+
const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
- InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mUniformBlocks);
if (!namedBlock)
{
- namedBlock = FindVariable(interfaceBlock->name(), mShaderStorageBlocks);
+ namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
}
ASSERT(namedBlock);
namedBlock->staticUse = true;
unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
ASSERT(fieldIndex < namedBlock->fields.size());
namedBlock->fields[fieldIndex].staticUse = true;
+
+ if (traverseIndexExpression)
+ {
+ ASSERT(interfaceIndexingNode);
+ interfaceIndexingNode->getRight()->traverse(this);
+ }
return false;
}
@@ -688,13 +773,14 @@
std::vector<Varying> *outputVaryings,
std::vector<InterfaceBlock> *uniformBlocks,
std::vector<InterfaceBlock> *shaderStorageBlocks,
+ std::vector<InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
const TExtensionBehavior &extensionBehavior)
{
CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
- outputVaryings, uniformBlocks, shaderStorageBlocks,
+ outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
hashFunction, symbolTable, shaderVersion, extensionBehavior);
root->traverse(&collect);
}
diff --git a/src/compiler/translator/CollectVariables.h b/src/compiler/translator/CollectVariables.h
index 3a40824..fb257f9 100644
--- a/src/compiler/translator/CollectVariables.h
+++ b/src/compiler/translator/CollectVariables.h
@@ -26,6 +26,7 @@
std::vector<Varying> *outputVaryings,
std::vector<InterfaceBlock> *uniformBlocks,
std::vector<InterfaceBlock> *shaderStorageBlocks,
+ std::vector<InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
int shaderVersion,
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index ef8141f..8ef6285 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -475,8 +475,8 @@
{
ASSERT(!variablesCollected);
CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
- &outputVaryings, &uniformBlocks, &shaderStorageBlocks, hashFunction,
- &symbolTable, shaderVersion, extensionBehavior);
+ &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
+ hashFunction, &symbolTable, shaderVersion, extensionBehavior);
collectInterfaceBlocks();
variablesCollected = true;
if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
@@ -751,10 +751,11 @@
void TCompiler::collectInterfaceBlocks()
{
ASSERT(interfaceBlocks.empty());
- interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size());
+ interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
shaderStorageBlocks.end());
+ interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
}
void TCompiler::clearResults()
@@ -773,6 +774,7 @@
interfaceBlocks.clear();
uniformBlocks.clear();
shaderStorageBlocks.clear();
+ inBlocks.clear();
variablesCollected = false;
mGLPositionInitialized = false;
diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h
index 54f1e38..085b7a9 100644
--- a/src/compiler/translator/Compiler.h
+++ b/src/compiler/translator/Compiler.h
@@ -119,6 +119,7 @@
{
return shaderStorageBlocks;
}
+ const std::vector<sh::InterfaceBlock> &getInBlocks() const { return inBlocks; }
ShHashFunction64 getHashFunction() const { return hashFunction; }
NameMap &getNameMap() { return nameMap; }
@@ -196,6 +197,7 @@
std::vector<sh::InterfaceBlock> interfaceBlocks;
std::vector<sh::InterfaceBlock> uniformBlocks;
std::vector<sh::InterfaceBlock> shaderStorageBlocks;
+ std::vector<sh::InterfaceBlock> inBlocks;
private:
// Creates the function call DAG for further analysis, returning false if there is a recursion
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index c362ae2..61acd4f 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -908,9 +908,32 @@
}
case GL_GEOMETRY_SHADER_OES:
- // TODO(jiawei.shao@intel.com): add Geometry Shader built-in variables.
- break;
+ {
+ // 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.
+ // TODO(jiawei.shao@intel.com): implement GL_OES_geometry_point_size.
+ const TString *glPerVertexString = NewPoolTString("gl_PerVertex");
+ symbolTable.insertInterfaceBlockNameExt(ESSL3_1_BUILTINS, extension, glPerVertexString);
+
+ TFieldList *fieldList = NewPoolTFieldList();
+ TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
+ TField *glPositionField = new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4),
+ NewPoolTString("gl_Position"), zeroSourceLoc);
+ fieldList->push_back(glPositionField);
+
+ TInterfaceBlock *glInBlock = new TInterfaceBlock(
+ glPerVertexString, fieldList, NewPoolTString("gl_in"), TLayoutQualifier::create());
+
+ // The array size of gl_in is undefined until we get a valid input primitive
+ // declaration.
+ TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::create(), 0);
+ glInType.setArrayUnsized();
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType);
+
+ break;
+ }
default:
UNREACHABLE();
}
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index b7aacee..29da221 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -622,7 +622,8 @@
const TField *field = interfaceBlock->fields()[index->getIConst(0)];
TString fieldName = field->name();
- ASSERT(!mSymbolTable->findBuiltIn(interfaceBlock->name(), mShaderVersion));
+ ASSERT(!mSymbolTable->findBuiltIn(interfaceBlock->name(), mShaderVersion) ||
+ interfaceBlock->name() == "gl_PerVertex");
fieldName = hashName(TName(fieldName));
out << fieldName;
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index f1cb9ed..25ee442 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -95,6 +95,27 @@
return true;
}
+// Map input primitive types to input array sizes in a geometry shader.
+GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)
+{
+ switch (primitiveType)
+ {
+ case EptPoints:
+ return 1u;
+ case EptLines:
+ return 2u;
+ case EptTriangles:
+ return 3u;
+ case EptLinesAdjacency:
+ return 4u;
+ case EptTrianglesAdjacency:
+ return 6u;
+ default:
+ UNREACHABLE();
+ return 0u;
+ }
+}
+
} // namespace
// This tracks each binding point's current default offset for inheritance of subsequent
@@ -184,7 +205,8 @@
mGeometryShaderInvocations(0),
mGeometryShaderMaxVertices(-1),
mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
- mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices)
+ mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices),
+ mGeometryShaderInputArraySize(0)
{
mComputeShaderLocalSize.fill(-1);
}
@@ -496,6 +518,9 @@
case EvqComputeIn:
message = "can't modify work group size variable";
break;
+ case EvqPerVertexIn:
+ message = "can't modify any member in gl_in";
+ break;
default:
//
// Type that can't be written to?
@@ -1748,6 +1773,13 @@
type.setQualifier(EvqConst);
node = new TIntermConstantUnion(constArray, type);
}
+ // TODO(jiawei.shao@intel.com): set array sizes for user-defined geometry shader inputs.
+ else if (variable->getType().getQualifier() == EvqPerVertexIn)
+ {
+ TType type(variable->getType());
+ type.setArraySize(mGeometryShaderInputArraySize);
+ node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), type);
+ }
else
{
node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType());
@@ -2683,6 +2715,15 @@
}
}
+void TParseContext::setGeometryShaderInputArraySizes()
+{
+ // TODO(jiawei.shao@intel.com): check former input array sizes match the input primitive
+ // declaration.
+ ASSERT(mGeometryShaderInputArraySize == 0);
+ mGeometryShaderInputArraySize =
+ GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType);
+}
+
bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
{
ASSERT(typeQualifier.qualifier == EvqGeometryIn);
@@ -2708,6 +2749,7 @@
if (mGeometryShaderInputPrimitiveType == EptUndefined)
{
mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
+ setGeometryShaderInputArraySizes();
}
else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
{
@@ -3337,6 +3379,7 @@
//
// Interface/uniform blocks
+// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
//
TIntermDeclaration *TParseContext::addInterfaceBlock(
const TTypeQualifierBuilder &typeQualifierBuilder,
@@ -3641,6 +3684,16 @@
return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
}
+ if (baseExpression->getQualifier() == EvqPerVertexIn)
+ {
+ ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES);
+ if (mGeometryShaderInputPrimitiveType == EptUndefined)
+ {
+ error(location, "missing input primitive declaration before indexing gl_in.", "[");
+ return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
+ }
+ }
+
TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
@@ -3651,9 +3704,21 @@
{
if (baseExpression->isInterfaceBlock())
{
- error(location,
- "array indexes for interface blocks arrays must be constant integral expressions",
- "[");
+ // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
+ switch (baseExpression->getQualifier())
+ {
+ case EvqPerVertexIn:
+ break;
+ case EvqUniform:
+ case EvqBuffer:
+ error(location,
+ "array indexes for uniform block arrays and shader storage block arrays "
+ "must be constant integral expressions",
+ "[");
+ break;
+ default:
+ UNREACHABLE();
+ }
}
else if (baseExpression->getQualifier() == EvqFragmentOut)
{
@@ -5326,6 +5391,11 @@
{
error(loc, "length can only be called on arrays", "length");
}
+ else if (typedThis->getQualifier() == EvqPerVertexIn &&
+ mGeometryShaderInputPrimitiveType == EptUndefined)
+ {
+ error(loc, "missing input primitive declaration before calling length on gl_in", "length");
+ }
else
{
arraySize = typedThis->getArraySize();
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 0ea5535..e9b2c08 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -535,6 +535,7 @@
bool checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier);
bool parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier);
bool parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier);
+ void setGeometryShaderInputArraySizes();
// Set to true when the last/current declarator list was started with an empty declaration. The
// non-empty declaration error check will need to be performed if the empty declaration is
@@ -600,6 +601,8 @@
int mGeometryShaderMaxVertices;
int mMaxGeometryShaderInvocations;
int mMaxGeometryShaderMaxVertices;
+ int mGeometryShaderInputArraySize; // Track if all input array sizes are same and matches the
+ // latter input primitive declaration.
};
int PaParseStrings(size_t count,
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 38a87ed..5d15c9b 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -299,6 +299,18 @@
return nullptr;
}
+TInterfaceBlockName *TSymbolTable::insertInterfaceBlockNameExt(ESymbolLevel level,
+ const char *ext,
+ const TString *name)
+{
+ TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
+ if (insert(level, ext, blockNameSymbol))
+ {
+ return blockNameSymbol;
+ }
+ return nullptr;
+}
+
TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type)
{
return insertVariable(level, NewPoolTString(name), type);
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 673bf0e..6d9b714 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -347,6 +347,9 @@
const char *name,
const TType &type);
TVariable *insertStructType(ESymbolLevel level, TStructure *str);
+ TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level,
+ const char *ext,
+ const TString *name);
bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
{
diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h
index e120cd4..4450a0b 100644
--- a/src/compiler/translator/Types.h
+++ b/src/compiler/translator/Types.h
@@ -253,7 +253,7 @@
TType(TInterfaceBlock *interfaceBlockIn,
TQualifier qualifierIn,
TLayoutQualifier layoutQualifierIn,
- int arraySizeIn)
+ unsigned int arraySizeIn)
: type(EbtInterfaceBlock),
precision(EbpUndefined),
qualifier(qualifierIn),
@@ -349,6 +349,7 @@
invalidateMangledName();
}
}
+ void setArrayUnsized() { setArraySize(0u); }
void clearArrayness()
{
if (array)