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:
parent
ab41fe5df6
commit
9497485e14
@ -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
23
Test/420.geom
Normal 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();
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
46
Test/baseResults/420.geom.out
Normal file
46
Test/baseResults/420.geom.out
Normal 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)
|
||||
|
@ -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})
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -47,6 +47,7 @@ tokenLength.vert
|
||||
300scope.vert
|
||||
400.frag
|
||||
420.vert
|
||||
420.geom
|
||||
430scope.vert
|
||||
lineContinuation.vert
|
||||
numeral.frag
|
||||
|
@ -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) {
|
||||
// for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
|
||||
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())) ||
|
||||
@ -525,10 +545,64 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
|
||||
// it's too early to know what the inductive variables are, save it for post processing
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
return result;
|
||||
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:
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user