Add geometry shader input array sizing/checking WRT declared input primitive layout.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23698 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-10-24 22:41:04 +00:00
parent ab41fe5df6
commit 9497485e14
18 changed files with 369 additions and 63 deletions

View File

@ -12,3 +12,40 @@ void main()
layout(invocations = 3) out outbn { int a; }; // ERROR, not on a block
layout(max_vertices = 127, invocations = 4) out;
#extension GL_ARB_separate_shader_objects : enable
in gl_PerVertex { // testing input arrays with a block redeclaration, see 420.geom for without
vec4 gl_Position;
} gl_in[];
void foo()
{
gl_in.length(); // ERROR
gl_in[1].gl_Position;
}
in vec4 color[];
in vec4 color2[];
in vec4 colorS[3];
in vec4 colorBad[4];
void foo2()
{
color.length(); // ERROR
colorS.length();
}
layout(triangles) in; // give ERROR just for colorBad
in vec4 color[3];
in vec4 color2[3];
in vec4 colorbad2[2]; // ERROR
void foo3()
{
gl_in.length();
color.length();
color2.length();
colorS.length();
}

23
Test/420.geom Normal file
View File

@ -0,0 +1,23 @@
#version 150 core
// testing input arrays without a gl_in[] block redeclaration, see 400.geom for with
int i;
void foo()
{
gl_in.length(); // ERROR
gl_in[1].gl_Position;
gl_in[i].gl_Position; // ERROR
}
layout(triangles) in;
in vec4 color3[3];
void foo3()
{
gl_in.length();
gl_in[i].gl_Position;
color3.length();
}

View File

@ -300,7 +300,7 @@ ERROR: node is still EOpNull!
0:121 add second child into first child (4-component vector of float)
0:121 'v' (4-component vector of float)
0:121 direct index (smooth in 4-component vector of float)
0:121 'gl_TexCoord' (smooth in unsized array of 4-component vector of float)
0:121 'gl_TexCoord' (smooth in 6-element array of 4-component vector of float)
0:121 Constant:
0:121 3 (const int)
0:? Linker Objects

View File

@ -46,5 +46,6 @@ ERROR: node is still EOpNull!
0:? 'fflat' (flat in float)
0:? 'fsmooth' (smooth in float)
0:? 'fnop' (noperspective in float)
0:? 'gl_ClipDistance' (smooth in unsized array of float)
0:? 'sampC' (uniform samplerCube)

View File

@ -19,4 +19,5 @@ ERROR: node is still EOpNull!
0:? 'i' (smooth in 4-component vector of float)
0:? 'o' (out 4-component vector of float)
0:? 'gl_ClipDistance' (smooth in 5-element array of float)
0:? 'gl_ClipDistance' (smooth in 5-element array of float)

View File

@ -63,7 +63,7 @@ ERROR: node is still EOpNull!
0:33 direct index (float)
0:33 gl_ClipDistance: direct index for structure (unsized array of float)
0:33 direct index (in block{gl_Position,gl_PointSize,gl_ClipDistance})
0:33 'gl_in' (in unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:33 'gl_in' (in 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:33 Constant:
0:33 1 (const int)
0:33 Constant:
@ -77,7 +77,7 @@ ERROR: node is still EOpNull!
0:34 0 (const uint)
0:34 gl_Position: direct index for structure (4-component vector of float)
0:34 direct index (in block{gl_Position,gl_PointSize,gl_ClipDistance})
0:34 'gl_in' (in unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:34 'gl_in' (in 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:34 Constant:
0:34 0 (const int)
0:34 Constant:
@ -89,7 +89,7 @@ ERROR: node is still EOpNull!
0:35 1 (const uint)
0:35 gl_PointSize: direct index for structure (float)
0:35 direct index (in block{gl_Position,gl_PointSize,gl_ClipDistance})
0:35 'gl_in' (in unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:35 'gl_in' (in 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:35 Constant:
0:35 3 (const int)
0:35 Constant:
@ -119,6 +119,7 @@ ERROR: node is still EOpNull!
0:? 'fromV' (in block{color})
0:? 'toF' (layout(stream=0 ) out block{color})
0:? '__anon__0' (layout(stream=0 ) out block{color})
0:? 'gl_in' (in 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:? 'ov0' (layout(stream=0 ) out 4-component vector of float)
0:? 'ov4' (layout(stream=4 ) out 4-component vector of float)
0:? 'o1v0' (layout(stream=0 ) out 4-component vector of float)

View File

@ -112,6 +112,7 @@ ERROR: node is still EOpNull!
0:? 'arrayedSampler' (uniform 5-element array of sampler2D)
0:? 'samp2dr' (uniform usampler2DRect)
0:? 'isamp2DA' (uniform isampler2DArray)
0:? 'gl_ClipDistance' (smooth in unsized array of float)
0:? 'vl' (layout(location=4 ) smooth in 4-component vector of float)
0:? 'vl2' (layout(location=4 ) smooth in 4-component vector of float)
0:? 'uv3' (layout(location=3 ) uniform 3-component vector of float)

View File

@ -1,10 +1,14 @@
Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
ERROR: 0:13: 'invocations' : can only apply to a standalone qualifier
ERROR: 1 compilation errors. No code generated.
ERROR: 0:24: 'length' : array must be declared with a size before using this method
ERROR: 0:35: 'length' : array must be declared with a size before using this method
ERROR: 0:39: 'triangles' : inconsistent input primitive for array size colorBad
ERROR: 0:43: 'triangles' : inconsistent input primitive for array size colorbad2
ERROR: 5 compilation errors. No code generated.
invocations = 4
max_vertices = 127
input primitive = none
input primitive = triangles
output primitive = none
ERROR: node is still EOpNull!
0:3 Function Definition: main( (void)
@ -22,6 +26,42 @@ ERROR: node is still EOpNull!
0:10 move second child to first child (int)
0:10 'id' (int)
0:10 'gl_InvocationID' (in int)
0:22 Function Definition: foo( (void)
0:22 Function Parameters:
0:24 Sequence
0:24 Constant:
0:24 1 (const int)
0:25 gl_Position: direct index for structure (4-component vector of float)
0:25 direct index (in block{gl_Position})
0:25 'gl_in' (in 3-element array of block{gl_Position})
0:25 Constant:
0:25 1 (const int)
0:25 Constant:
0:25 0 (const int)
0:33 Function Definition: foo2( (void)
0:33 Function Parameters:
0:35 Sequence
0:35 Constant:
0:35 1 (const int)
0:36 Constant:
0:36 3 (const int)
0:45 Function Definition: foo3( (void)
0:45 Function Parameters:
0:47 Sequence
0:47 Constant:
0:47 3 (const int)
0:48 Constant:
0:48 3 (const int)
0:49 Constant:
0:49 3 (const int)
0:50 Constant:
0:50 3 (const int)
0:? Linker Objects
0:? '__anon__0' (layout(stream=0 ) out block{a})
0:? 'gl_in' (in 3-element array of block{gl_Position})
0:? 'color' (in 3-element array of 4-component vector of float)
0:? 'color2' (in 3-element array of 4-component vector of float)
0:? 'colorS' (in 3-element array of 4-component vector of float)
0:? 'colorBad' (in 4-element array of 4-component vector of float)
0:? 'colorbad2' (in 2-element array of 4-component vector of float)

View File

@ -2,7 +2,7 @@ Warning, version 410 is not yet complete; some version-specific features are pre
ERROR: 0:8: 'myIn' : cannot redeclare a built-in block with a user name
ERROR: 0:8: 'gl_' : reserved built-in name
ERROR: 0:12: 'gl_' : reserved built-in name
ERROR: 0:20: 'gl_PerVertex' : can only redeclare a built-in block once
ERROR: 0:20: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use
ERROR: 0:20: 'gl_' : reserved built-in name
ERROR: 5 compilation errors. No code generated.

View File

@ -0,0 +1,46 @@
Warning, version 150 is not yet complete; some version-specific features are present, but many are missing.
ERROR: 0:9: 'length' : array must be declared with a size before using this method
ERROR: 0:11: '[' : array must be redeclared with a size before being indexed with a variable
ERROR: 2 compilation errors. No code generated.
invocations = 0
max_vertices = 0
input primitive = triangles
output primitive = none
ERROR: node is still EOpNull!
0:7 Function Definition: foo( (void)
0:7 Function Parameters:
0:9 Sequence
0:9 Constant:
0:9 1 (const int)
0:10 gl_Position: direct index for structure (4-component vector of float)
0:10 direct index (in block{gl_Position,gl_PointSize,gl_ClipDistance})
0:10 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:10 Constant:
0:10 1 (const int)
0:10 Constant:
0:10 0 (const int)
0:11 gl_Position: direct index for structure (4-component vector of float)
0:11 indirect index (in block{gl_Position,gl_PointSize,gl_ClipDistance})
0:11 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:11 'i' (int)
0:11 Constant:
0:11 0 (const int)
0:18 Function Definition: foo3( (void)
0:18 Function Parameters:
0:20 Sequence
0:20 Constant:
0:20 3 (const int)
0:21 gl_Position: direct index for structure (4-component vector of float)
0:21 indirect index (in block{gl_Position,gl_PointSize,gl_ClipDistance})
0:21 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:21 'i' (int)
0:21 Constant:
0:21 0 (const int)
0:22 Constant:
0:22 3 (const int)
0:? Linker Objects
0:? 'i' (int)
0:? 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
0:? 'color3' (in 3-element array of 4-component vector of float)

View File

@ -286,8 +286,11 @@ ERROR: node is still EOpNull!
0:? '__anon__1' (in block{LightPos,LightColor})
0:? 'Materiala' (in block{Color,TexCoord})
0:? 'gl_FragCoord' (gl_FragCoord 4-component vector of float)
0:? 'gl_FragCoord' (gl_FragCoord 4-component vector of float)
0:? 'factor' (layout(location=3 ) out 4-component vector of float)
0:? 'colors' (layout(location=2 ) out 3-element array of 4-component vector of float)
0:? 'gl_FragDepth' (gl_FragDepth float)
0:? 'gl_FragDepth' (gl_FragDepth float)
0:? '__anon__2' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor})
0:? '__anon__2' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor})

View File

@ -294,6 +294,7 @@ ERROR: node is still EOpNull!
0:? 'c2' (layout(binding=3 ) uniform int)
0:? 'd2' (layout(binding=2 ) uniform int)
0:? '__anon__5' (out block{gl_Position,gl_PointSize,gl_ClipDistance,gl_ClipVertex,gl_FrontColor,gl_BackColor,gl_FrontSecondaryColor,gl_BackSecondaryColor,gl_TexCoord,gl_FogFragCoord})
0:? '__anon__5' (out block{gl_Position,gl_PointSize,gl_ClipDistance,gl_ClipVertex,gl_FrontColor,gl_BackColor,gl_FrontSecondaryColor,gl_BackSecondaryColor,gl_TexCoord,gl_FogFragCoord})
0:? 'ColorInv' (smooth out 3-component vector of float)
0:? 'Color4' (invariant centroid smooth out 3-component vector of float)
0:? 'position' (smooth out 4-component vector of float)

View File

@ -54,5 +54,6 @@ WARNING: 0:8: varying deprecated in version 130; may be removed in future releas
0:? 'color' (smooth in 4-component vector of float)
0:? 'alpha' (smooth in float)
0:? 'gl_TexCoord' (smooth in 6-element array of 4-component vector of float)
0:? 'gl_TexCoord' (smooth in 6-element array of 4-component vector of float)
0:? 'foo' (smooth in 3-element array of 4-component vector of float)

View File

@ -55,6 +55,7 @@ WARNING: 0:8: varying deprecated in version 130; may be removed in future releas
0:? 'color' (smooth in 4-component vector of float)
0:? 'alpha' (smooth in float)
0:? 'gl_TexCoord' (smooth in 6-element array of 4-component vector of float)
0:? 'gl_TexCoord' (smooth in 6-element array of 4-component vector of float)
0:? 'userIn' (smooth in 2-element array of 4-component vector of float)
0:? 'a' (uniform int)
0:? 'b' (uniform int)

View File

@ -47,6 +47,7 @@ tokenLength.vert
300scope.vert
400.frag
420.vert
420.geom
430scope.vert
lineContinuation.vert
numeral.frag

View File

@ -423,7 +423,7 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt
} else {
// The symbol table search was done in the lexical phase, but
// if this is a new symbol, it wouldn't have found it.
const TVariable* variable = symbol ? symbol->getAsVariable() : 0;
TVariable* variable = symbol ? symbol->getAsVariable() : 0;
if (symbol && ! variable)
error(loc, "variable name expected", string->c_str(), "");
@ -435,8 +435,16 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt
if (variable->getType().getQualifier().storage == EvqConst)
node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc);
else
node = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), loc);
else {
// break sharing with built-ins
TType* type;
if (variable->isReadOnly()) {
type = new TType;
type->deepCopy(variable->getType());
} else
type = &variable->getWritableType();
node = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), *type, loc);
}
}
return node;
@ -470,6 +478,7 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
result = addConstMatrixNode(index->getAsConstantUnion()->getConstArray()[0].getIConst(), base, loc);
}
} else {
// at least one of base and index is variable...
if (index->getQualifier().storage == EvqConst) {
int indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
if (! base->isArray() && ((base->isVector() && base->getType().getVectorSize() <= indexValue) ||
@ -488,7 +497,7 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
if (base->getBasicType() == EbtBlock)
requireProfile(base->getLoc(), ~EEsProfile, "variable indexing block array");
if (base->getBasicType() == EbtSampler && version >= 130) {
else if (base->getBasicType() == EbtSampler && version >= 130) {
const char* explanation = "variable indexing sampler array";
requireProfile(base->getLoc(), ECoreProfile | ECompatibilityProfile, explanation);
profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, 0, explanation);
@ -510,8 +519,19 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
newType.dereference();
result->setType(newType);
if (anyIndexLimits) {
if (anyIndexLimits)
handleIndexLimits(loc, base, index);
if (language == EShLangGeometry && base->isArray())
handleInputArrayAccess(loc, base);
}
return result;
}
// for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
void TParseContext::handleIndexLimits(TSourceLoc loc, TIntermTyped* base, TIntermTyped* index)
{
if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) ||
(! limits.generalUniformIndexing && base->getQualifier().isUniform() && language != EShLangVertex) ||
(! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) ||
@ -526,9 +546,63 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
needsIndexLimitationChecking.push_back(index);
}
}
// Handle a dereference of a geometry shader input arrays.
// See inputArrayNodeResizeList comment in ParseHelper.h.
//
void TParseContext::handleInputArrayAccess(TSourceLoc loc, TIntermTyped* base)
{
if (base->getType().getQualifier().storage == EvqVaryingIn) {
TIntermSymbol* symbol = base->getAsSymbolNode();
assert(symbol);
inputArrayNodeResizeList.push_back(symbol);
if (symbol && builtInName(symbol->getName())) {
// make sure we have a user-modifiable copy of this built-in input array
TSymbol* input = symbolTable.find(symbol->getName());
if (input->isReadOnly()) {
input = symbolTable.copyUp(input);
inputArraySymbolResizeList.push_back(input);
// Save it in the AST for linker use.
intermediate.addSymbolLinkageNode(linkage, *input);
}
}
}
}
return result;
// If there has been an input primitive declaration, make sure all input array types
// match it in size. Types come either from nodes in the AST or symbols in the
// symbol table.
//
// Types without an array size will be given one.
// Types already having a size that is wrong will get an error.
//
void TParseContext::checkInputArrayConsistency(TSourceLoc loc, bool tailOnly)
{
TLayoutGeometry primitive = intermediate.getInputPrimitive();
if (primitive == ElgNone)
return;
if (tailOnly) {
checkInputArrayConsistency(loc, primitive, inputArraySymbolResizeList.back()->getWritableType(), inputArraySymbolResizeList.back()->getName());
return;
}
for (size_t i = 0; i < inputArrayNodeResizeList.size(); ++i)
checkInputArrayConsistency(loc, primitive, inputArrayNodeResizeList[i]->getWritableType(), inputArrayNodeResizeList[i]->getName());
for (size_t i = 0; i < inputArraySymbolResizeList.size(); ++i)
checkInputArrayConsistency(loc, primitive, inputArraySymbolResizeList[i]->getWritableType(), inputArraySymbolResizeList[i]->getName());
}
void TParseContext::checkInputArrayConsistency(TSourceLoc loc, TLayoutGeometry primitive, TType& type, const TString& name)
{
int requiredSize = TQualifier::mapGeometryToSize(primitive);
if (type.getArraySize() == 0)
type.changeArraySize(requiredSize);
else if (type.getArraySize() != requiredSize)
error(loc, "inconsistent input primitive for array size", TQualifier::getGeometryString(primitive), name.c_str());
}
//
@ -1268,7 +1342,7 @@ void TParseContext::globalCheck(TSourceLoc loc, const char* token)
bool TParseContext::reservedErrorCheck(TSourceLoc loc, const TString& identifier)
{
if (! symbolTable.atBuiltInLevel()) {
if (identifier.compare(0, 3, "gl_") == 0) {
if (builtInName(identifier)) {
error(loc, "reserved built-in name", "gl_", "");
return true;
@ -1283,6 +1357,11 @@ bool TParseContext::reservedErrorCheck(TSourceLoc loc, const TString& identifier
return false;
}
bool TParseContext::builtInName(const TString& identifier)
{
return identifier.compare(0, 3, "gl_") == 0;
}
//
// Make sure there is enough data provided to the constructor to build
// something of the type of the constructor. Also returns the type of
@ -1787,6 +1866,13 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
symbol = new TVariable(&identifier, type);
symbolTable.insert(*symbol);
newDeclaration = true;
// Handle user geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
if (language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn && ! symbolTable.atBuiltInLevel()) {
inputArraySymbolResizeList.push_back(symbol);
checkInputArrayConsistency(loc, true);
}
return;
}
if (symbol->getAsAnonMember()) {
@ -1811,16 +1897,21 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
return;
}
if (newType.getArraySize() > 0) {
// be more leniant for input arrays to geometry shaders, where the redeclaration is the same size
if (! (language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn && newType.getArraySize() == type.getArraySize()))
error(loc, "redeclaration of array with size", identifier.c_str(), "");
return;
}
if (! newType.sameElementType(type)) {
error(loc, "redeclaration of array with a different newType", identifier.c_str(), "");
error(loc, "redeclaration of array with a different type", identifier.c_str(), "");
return;
}
newType.shareArraySizes(type);
if (language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn)
checkInputArrayConsistency(loc);
}
void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int index)
@ -1850,9 +1941,17 @@ void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int in
// For read-only built-ins, add a new variable for holding the maximum array size of an implicitly-sized shared array.
// TODO: functionality: unsized arrays: is this new array type shared with the node?
if (symbol->isReadOnly())
if (symbol->isReadOnly()) {
symbol = symbolTable.copyUp(symbol);
// Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
if (language == EShLangGeometry && symbol->getType().getQualifier().storage == EvqVaryingIn)
inputArraySymbolResizeList.push_back(symbol);
// Save it in the AST for linker use.
intermediate.addSymbolLinkageNode(linkage, *symbol);
}
symbol->getWritableType().setMaxArraySize(index + 1);
}
@ -1883,7 +1982,7 @@ void TParseContext::nonInitConstCheck(TSourceLoc loc, TString& identifier, TType
//
TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString& identifier, bool& newDeclaration)
{
if (profile == EEsProfile || identifier.compare(0, 3, "gl_") != 0 || symbolTable.atBuiltInLevel())
if (profile == EEsProfile || ! builtInName(identifier) || symbolTable.atBuiltInLevel())
return 0;
// Potentially redeclaring a built-in variable...
@ -1915,6 +2014,13 @@ TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString&
// Copy the symbol up to make a writable version
newDeclaration = true;
symbol = symbolTable.copyUp(symbol);
// Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
if (language == EShLangGeometry && symbol->getType().getQualifier().storage == EvqVaryingIn && symbol->getType().isArray())
inputArraySymbolResizeList.push_back(symbol);
// Save it in the AST for linker use.
intermediate.addSymbolLinkageNode(linkage, *symbol);
}
// Now, modify the type of the copy, as per the type of the current redeclaration.
@ -1929,10 +2035,10 @@ TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString&
bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
{
// just a quick out, not everything that must be checked:
if (symbolTable.atBuiltInLevel() || profile == EEsProfile || blockName.compare(0, 3, "gl_") != 0)
if (symbolTable.atBuiltInLevel() || profile == EEsProfile || ! builtInName(blockName))
return false;
if (instanceName && instanceName->compare(0, 3, "gl_") != 0) {
if (instanceName && ! builtInName(*instanceName)) {
error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
return false;
}
@ -1944,11 +2050,8 @@ bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, c
if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment")
return false;
// Blocks with instance names are easy to find, lookup the instance name,
// Anonymous blocks need to be found via a member. copyUp()?? will work
// just fine for either find.
// Anonymous blocks need to be found via a member.
bool builtIn;
TSymbol* block;
if (instanceName)
@ -1964,7 +2067,7 @@ bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, c
// Built-in blocks cannot be redeclared more than once, which if happened,
// we'd be finding the already redeclared one here, rather than the built in.
if (! builtIn) {
error(loc, "can only redeclare a built-in block once", blockName.c_str(), "");
error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), "");
return false;
}
@ -1976,6 +2079,10 @@ bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, c
return false;
}
// Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
if (language == EShLangGeometry && block->getType().isArray() && block->getType().getQualifier().storage == EvqVaryingIn)
inputArraySymbolResizeList.push_back(block);
// TODO: semantics: block redeclaration: instance array size matching?
// Edit and error check the container against the redeclaration
@ -3124,7 +3231,9 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
case ElgLinesAdjacency:
case ElgTriangles:
case ElgTrianglesAdjacency:
if (! intermediate.setInputPrimitive(publicType.geometry))
if (intermediate.setInputPrimitive(publicType.geometry))
checkInputArrayConsistency(loc);
else
error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.geometry), "");
break;
default:

View File

@ -72,12 +72,17 @@ public:
const char *szExtraInfoFormat, ...);
void C_DECL warn(TSourceLoc, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...);
bool reservedErrorCheck(TSourceLoc, const TString& identifier);
bool reservedErrorCheck(TSourceLoc, const TString&);
bool builtInName(const TString&);
void updateExtensionBehavior(const char* extName, const char* behavior);
void handlePragma(const char **tokens, int numTokens);
TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string);
TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
void handleIndexLimits(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
void handleInputArrayAccess(TSourceLoc, TIntermTyped* base);
void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false);
void checkInputArrayConsistency(TSourceLoc, TLayoutGeometry, TType&, const TString&);
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function);
TIntermAggregate* handleFunctionPrototype(TSourceLoc, TFunction&);
@ -230,6 +235,40 @@ protected:
bool anyIndexLimits;
TVector<TIntermTyped*> needsIndexLimitationChecking;
// TODO: desktop functionality: track use of gl_FragDepth before redeclaration
//
// Geometry shader input arrays:
// - array sizing is based on input primitive and/or explicit size
// - array sizing is retroactive
// - built-in block redeclarations interact with this
//
// Design:
// - use a per-context "resize-list", a list of entities whose array sizes
// can be fixed; this is logically one list, but physically two:
// * a list for nodes in the AST
// * a list for symbols in the symbol table
// this could be done a bit more simply, but this allows better error messages.
//
// - the resize-list starts empty at beginning of user-shader compilation, it does
// not have built-ins in it
//
// - on built-in input array use: copy-up symbol and add both the symbol and
// its use to resize-list
//
// - on user-input array declaration: add it to the resize-list
//
// - on block redeclaration: copy-up symbol and add it to the resize-list
// * note, that appropriately gives an error if redeclaring a block that
// was already used and hence already copied-up
//
// - on seeing an input primitive-layout declaration, fix everything in the resize-list,
// giving errors for mismatch
//
// - on seeing an array size declaration, give errors on mismatch between it and previous
// input primitive declarations
//
TVector<TIntermSymbol*> inputArrayNodeResizeList;
TVector<TSymbol*> inputArraySymbolResizeList;
};
} // end namespace glslang

View File

@ -99,7 +99,7 @@ public:
virtual int getUniqueId() const { return uniqueId; }
virtual void dump(TInfoSink &infoSink) const = 0;
virtual bool isReadOnly() { return ! writable; }
virtual bool isReadOnly() const { return ! writable; }
virtual void makeReadOnly() { writable = false; }
protected:
@ -417,9 +417,10 @@ public:
// 3: user-shader globals
//
protected:
static const int globalLevel = 3;
bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
bool isGlobalLevel(int level) { return level <= 3; } // include user globals
bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
public:
bool isEmpty() { return table.size() == 0; }
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
@ -482,7 +483,7 @@ public:
TSymbol* copyUp(TSymbol* shared)
{
TSymbol* copy = copyUpDeferredInsert(shared);
table[currentLevel()]->insert(*copy);
table[globalLevel]->insert(*copy);
if (shared->getAsVariable())
return copy;
else {