mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-08 11:30:06 +00:00
Tessellation: Implicit array sizing and consistency checking of control-shader output arrays based on layout(vertices=...).
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24518 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
116c30b6ed
commit
f3e2a89452
@ -35,3 +35,11 @@ void main()
|
||||
gl_TessLevelOuter[3] = 3.2;
|
||||
gl_TessLevelInner[1] = 1.3;
|
||||
}
|
||||
|
||||
layout(vertices = 4) in; // ERROR
|
||||
layout(vertices = 5) out; // ERROR
|
||||
|
||||
void foo()
|
||||
{
|
||||
gl_out[4].gl_PointSize; // ERROR
|
||||
}
|
11
Test/410.tesc
Normal file
11
Test/410.tesc
Normal file
@ -0,0 +1,11 @@
|
||||
#version 400 core
|
||||
|
||||
// no layout(vertices = ...) out;
|
||||
int outa[gl_out.length()]; // ERROR
|
||||
|
||||
patch out vec4 patchOut;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
}
|
27
Test/420.tesc
Normal file
27
Test/420.tesc
Normal file
@ -0,0 +1,27 @@
|
||||
#version 400 core
|
||||
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(vertices = 4) out;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
} gl_out[3]; // ERROR, wrong size
|
||||
|
||||
out int a[gl_out.length()];
|
||||
out int outb[5]; // ERROR, wrong size
|
||||
out int outc[];
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 p = gl_in[1].gl_Position;
|
||||
float ps = gl_in[1].gl_PointSize;
|
||||
float cd = gl_in[1].gl_ClipDistance[2];
|
||||
|
||||
int pvi = gl_PatchVerticesIn;
|
||||
int pid = gl_PrimitiveID;
|
||||
int iid = gl_InvocationID;
|
||||
|
||||
gl_out[1].gl_Position = p;
|
||||
gl_out[1].gl_PointSize = ps; // ERROR
|
||||
}
|
21
Test/420_size_gl_in.geom
Normal file
21
Test/420_size_gl_in.geom
Normal file
@ -0,0 +1,21 @@
|
||||
#version 420 core
|
||||
|
||||
// testing input arrays without a gl_in[] block redeclaration, see 400.geom for with
|
||||
|
||||
int i;
|
||||
|
||||
layout(triangles) in;
|
||||
in vec4 colorun[];
|
||||
in vec4 color3[3];
|
||||
|
||||
void foo()
|
||||
{
|
||||
gl_in.length();
|
||||
gl_in[1].gl_Position;
|
||||
gl_in.length();
|
||||
gl_in[i].gl_Position;
|
||||
}
|
||||
|
||||
in gl_PerVertex { // ERROR, already used
|
||||
vec4 gl_Position;
|
||||
} gl_in[];
|
@ -4,8 +4,8 @@ ERROR: 0:13: 'invocations' : can only apply to a standalone qualifier
|
||||
ERROR: 0:20: 'patch' : not supported in this stage: geometry
|
||||
ERROR: 0:20: 'gl_PointSize' : cannot add layout to redeclared block member
|
||||
ERROR: 0:20: 'gl_PointSize' : cannot add patch to redeclared block member
|
||||
ERROR: 0:25: 'length' : array must be declared with a size before using this method
|
||||
ERROR: 0:36: 'length' : array must be declared with a size before using this method
|
||||
ERROR: 0:25: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 0:36: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 0:40: 'triangles' : inconsistent input primitive for array size colorBad
|
||||
ERROR: 0:44: 'triangles' : inconsistent input primitive for array size colorbad2
|
||||
ERROR: 0:56: 'location' : repeated use of location 4
|
||||
@ -81,7 +81,7 @@ ERROR: node is still EOpNull!
|
||||
|
||||
Linked geometry stage:
|
||||
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify an output layout primitive
|
||||
ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
|
||||
|
||||
invocations = 4
|
||||
max_vertices = 127
|
||||
|
@ -1,11 +1,13 @@
|
||||
400.tesc
|
||||
Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
|
||||
ERROR: 0:4: 'length' : array must be declared with a size before using this method
|
||||
ERROR: 0:6: 'quads' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
|
||||
ERROR: 0:7: 'ccw' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
|
||||
ERROR: 0:8: 'fractional_even_spacing' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
|
||||
ERROR: 0:10: 'patch' : can only use on output in tessellation-control shader
|
||||
ERROR: 5 compilation errors. No code generated.
|
||||
ERROR: 0:39: 'vertices' : can only apply to 'out'
|
||||
ERROR: 0:40: 'vertices' : cannot change previously set layout value
|
||||
ERROR: 0:44: '[' : array index out of range '4'
|
||||
ERROR: 7 compilation errors. No code generated.
|
||||
|
||||
|
||||
vertices = 4
|
||||
@ -67,7 +69,7 @@ ERROR: node is still EOpNull!
|
||||
0:31 move second child to first child (4-component vector of float)
|
||||
0:31 gl_Position: direct index for structure (4-component vector of float)
|
||||
0:31 direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:31 'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:31 'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:31 Constant:
|
||||
0:31 1 (const int)
|
||||
0:31 Constant:
|
||||
@ -76,7 +78,7 @@ ERROR: node is still EOpNull!
|
||||
0:32 move second child to first child (float)
|
||||
0:32 gl_PointSize: direct index for structure (float)
|
||||
0:32 direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:32 'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:32 'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:32 Constant:
|
||||
0:32 1 (const int)
|
||||
0:32 Constant:
|
||||
@ -86,7 +88,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 (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:33 'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:33 'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:33 Constant:
|
||||
0:33 1 (const int)
|
||||
0:33 Constant:
|
||||
@ -108,11 +110,21 @@ ERROR: node is still EOpNull!
|
||||
0:36 1 (const int)
|
||||
0:36 Constant:
|
||||
0:36 1.300000
|
||||
0:42 Function Definition: foo( (void)
|
||||
0:42 Function Parameters:
|
||||
0:44 Sequence
|
||||
0:44 gl_PointSize: direct index for structure (float)
|
||||
0:44 direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:44 'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:44 Constant:
|
||||
0:44 4 (const int)
|
||||
0:44 Constant:
|
||||
0:44 1 (const int)
|
||||
0:? Linker Objects
|
||||
0:? 'outa' (1-element array of int)
|
||||
0:? 'outa' (4-element array of int)
|
||||
0:? 'patchIn' (patch in 4-component vector of float)
|
||||
0:? 'patchOut' (patch out 4-component vector of float)
|
||||
0:? 'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:? 'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
|
||||
|
||||
Linked tessellation control stage:
|
||||
|
@ -52,9 +52,9 @@ ERROR: node is still EOpNull!
|
||||
|
||||
Linked geometry stage:
|
||||
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify an input layout primitive
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify an output layout primitive
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify a layout(max_vertices = value)
|
||||
ERROR: Linking geometry stage: At least one shader must specify an input layout primitive
|
||||
ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
|
||||
ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
|
||||
|
||||
invocations = 0
|
||||
max_vertices = 0
|
||||
|
21
Test/baseResults/410.tesc.out
Normal file
21
Test/baseResults/410.tesc.out
Normal file
@ -0,0 +1,21 @@
|
||||
410.tesc
|
||||
Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
|
||||
ERROR: 0:4: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 1 compilation errors. No code generated.
|
||||
|
||||
|
||||
vertices = 0
|
||||
ERROR: node is still EOpNull!
|
||||
0:8 Function Definition: main( (void)
|
||||
0:8 Function Parameters:
|
||||
0:? Linker Objects
|
||||
0:? 'outa' (1-element array of int)
|
||||
0:? 'patchOut' (patch out 4-component vector of float)
|
||||
|
||||
|
||||
Linked tessellation control stage:
|
||||
|
||||
ERROR: Linking tessellation control stage: At least one shader must specify an output layout(vertices=...)
|
||||
|
||||
vertices = 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
420.geom
|
||||
Warning, version 420 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: 0:9: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 0:11: '[' : array must be sized by a redeclaration or layout qualifier before being indexed with a variable
|
||||
ERROR: 0:42: 'assign' : l-value required (can't modify a const)
|
||||
ERROR: 0:43: 'assign' : l-value required "v4" (can't modify a uniform)
|
||||
ERROR: 0:48: 'gl_PointSize' : cannot change arrayness of redeclared block member
|
||||
@ -123,8 +123,8 @@ ERROR: node is still EOpNull!
|
||||
Linked geometry stage:
|
||||
|
||||
ERROR: Linking geometry stage: Missing entry point: Each stage requires one "void main()" entry point
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify an output layout primitive
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify a layout(max_vertices = value)
|
||||
ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
|
||||
ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
|
||||
|
||||
invocations = 0
|
||||
max_vertices = 0
|
||||
|
85
Test/baseResults/420.tesc.out
Normal file
85
Test/baseResults/420.tesc.out
Normal file
@ -0,0 +1,85 @@
|
||||
420.tesc
|
||||
Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
|
||||
ERROR: 0:7: 'vertices' : inconsistent output number of vertices for array size gl_out
|
||||
ERROR: 0:11: 'vertices' : inconsistent output number of vertices for array size a
|
||||
ERROR: 0:12: 'vertices' : inconsistent output number of vertices for array size outb
|
||||
ERROR: 0:26: 'gl_PointSize' : no such field in structure
|
||||
ERROR: 0:26: 'assign' : cannot convert from 'float' to 'block{gl_Position}'
|
||||
ERROR: 5 compilation errors. No code generated.
|
||||
|
||||
|
||||
vertices = 4
|
||||
ERROR: node is still EOpNull!
|
||||
0:15 Function Definition: main( (void)
|
||||
0:15 Function Parameters:
|
||||
0:17 Sequence
|
||||
0:17 Sequence
|
||||
0:17 move second child to first child (4-component vector of float)
|
||||
0:17 'p' (4-component vector of float)
|
||||
0:17 gl_Position: direct index for structure (4-component vector of float)
|
||||
0:17 direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:17 'gl_in' (in 32-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:17 Constant:
|
||||
0:17 1 (const int)
|
||||
0:17 Constant:
|
||||
0:17 0 (const int)
|
||||
0:18 Sequence
|
||||
0:18 move second child to first child (float)
|
||||
0:18 'ps' (float)
|
||||
0:18 gl_PointSize: direct index for structure (float)
|
||||
0:18 direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:18 'gl_in' (in 32-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:18 Constant:
|
||||
0:18 1 (const int)
|
||||
0:18 Constant:
|
||||
0:18 1 (const int)
|
||||
0:19 Sequence
|
||||
0:19 move second child to first child (float)
|
||||
0:19 'cd' (float)
|
||||
0:19 direct index (float)
|
||||
0:19 gl_ClipDistance: direct index for structure (unsized array of float)
|
||||
0:19 direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:19 'gl_in' (in 32-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:19 Constant:
|
||||
0:19 1 (const int)
|
||||
0:19 Constant:
|
||||
0:19 2 (const int)
|
||||
0:19 Constant:
|
||||
0:19 2 (const int)
|
||||
0:21 Sequence
|
||||
0:21 move second child to first child (int)
|
||||
0:21 'pvi' (int)
|
||||
0:21 'gl_PatchVerticesIn' (in int)
|
||||
0:22 Sequence
|
||||
0:22 move second child to first child (int)
|
||||
0:22 'pid' (int)
|
||||
0:22 'gl_PrimitiveID' (in int)
|
||||
0:23 Sequence
|
||||
0:23 move second child to first child (int)
|
||||
0:23 'iid' (int)
|
||||
0:23 'gl_InvocationID' (in int)
|
||||
0:25 move second child to first child (4-component vector of float)
|
||||
0:25 gl_Position: direct index for structure (4-component vector of float)
|
||||
0:25 direct index (block{gl_Position})
|
||||
0:25 'gl_out' (out 3-element array of block{gl_Position})
|
||||
0:25 Constant:
|
||||
0:25 1 (const int)
|
||||
0:25 Constant:
|
||||
0:25 0 (const int)
|
||||
0:25 'p' (4-component vector of float)
|
||||
0:26 direct index (block{gl_Position})
|
||||
0:26 'gl_out' (out 3-element array of block{gl_Position})
|
||||
0:26 Constant:
|
||||
0:26 1 (const int)
|
||||
0:? Linker Objects
|
||||
0:? 'gl_out' (out 3-element array of block{gl_Position})
|
||||
0:? 'a' (out 3-element array of int)
|
||||
0:? 'outb' (out 5-element array of int)
|
||||
0:? 'outc' (out 4-element array of int)
|
||||
|
||||
|
||||
Linked tessellation control stage:
|
||||
|
||||
|
||||
vertices = 4
|
||||
|
@ -163,7 +163,7 @@ ERROR: node is still EOpNull!
|
||||
|
||||
Linked tessellation evaluation stage:
|
||||
|
||||
ERROR: Linking tessellation evaluation stage: At least one tessellation shader must specify an input layout primitive
|
||||
ERROR: Linking tessellation evaluation stage: At least one shader must specify an input layout primitive
|
||||
|
||||
input primitive = none
|
||||
vertex spacing = equal_spacing
|
||||
|
49
Test/baseResults/420_size_gl_in.geom.out
Normal file
49
Test/baseResults/420_size_gl_in.geom.out
Normal file
@ -0,0 +1,49 @@
|
||||
420_size_gl_in.geom
|
||||
Warning, version 420 is not yet complete; some version-specific features are present, but many are missing.
|
||||
ERROR: 0:19: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use
|
||||
ERROR: 1 compilation errors. No code generated.
|
||||
|
||||
|
||||
invocations = 0
|
||||
max_vertices = 0
|
||||
input primitive = triangles
|
||||
output primitive = none
|
||||
ERROR: node is still EOpNull!
|
||||
0:11 Function Definition: foo( (void)
|
||||
0:11 Function Parameters:
|
||||
0:13 Sequence
|
||||
0:13 Constant:
|
||||
0:13 3 (const int)
|
||||
0:14 gl_Position: direct index for structure (4-component vector of float)
|
||||
0:14 direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:14 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:14 Constant:
|
||||
0:14 1 (const int)
|
||||
0:14 Constant:
|
||||
0:14 0 (const int)
|
||||
0:15 Constant:
|
||||
0:15 3 (const int)
|
||||
0:16 gl_Position: direct index for structure (4-component vector of float)
|
||||
0:16 indirect index (block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:16 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
0:16 'i' (int)
|
||||
0:16 Constant:
|
||||
0:16 0 (const int)
|
||||
0:? Linker Objects
|
||||
0:? 'i' (int)
|
||||
0:? 'colorun' (in 3-element array of 4-component vector of float)
|
||||
0:? 'color3' (in 3-element array of 4-component vector of float)
|
||||
0:? 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
|
||||
|
||||
|
||||
Linked geometry stage:
|
||||
|
||||
ERROR: Linking geometry stage: Missing entry point: Each stage requires one "void main()" entry point
|
||||
ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
|
||||
ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
|
||||
|
||||
invocations = 0
|
||||
max_vertices = 0
|
||||
input primitive = triangles
|
||||
output primitive = none
|
||||
|
@ -44,8 +44,8 @@ Linked geometry stage:
|
||||
|
||||
ERROR: Linking geometry stage: Contradictory output layout primitives
|
||||
ERROR: Linking geometry stage: Missing entry point: Each stage requires one "void main()" entry point
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify an input layout primitive
|
||||
ERROR: Linking geometry stage: At least one geometry shader must specify a layout(max_vertices = value)
|
||||
ERROR: Linking geometry stage: At least one shader must specify an input layout primitive
|
||||
ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
|
||||
|
||||
Linked fragment stage:
|
||||
|
||||
|
@ -49,7 +49,9 @@ tokenLength.vert
|
||||
300scope.vert
|
||||
400.frag
|
||||
420.vert
|
||||
420.tesc
|
||||
420.geom
|
||||
420_size_gl_in.geom
|
||||
430scope.vert
|
||||
lineContinuation100.vert
|
||||
lineContinuation.vert
|
||||
@ -58,6 +60,7 @@ numeral.frag
|
||||
400.tesc
|
||||
400.tese
|
||||
410.geom
|
||||
410.tesc
|
||||
420.tese
|
||||
430.vert
|
||||
430.comp
|
||||
|
@ -9,5 +9,5 @@
|
||||
// source have to figure out how to create revision.h just to get a build
|
||||
// going. However, if it is not updated, it can be a version behind.
|
||||
|
||||
#define GLSLANG_REVISION "24480"
|
||||
#define GLSLANG_DATE "2013/12/11 15:38:19"
|
||||
#define GLSLANG_REVISION "24486"
|
||||
#define GLSLANG_DATE "2013/12/11 18:25:37"
|
||||
|
@ -437,13 +437,21 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
|
||||
return intermediate.foldDereference(base, indexValue, loc);
|
||||
else {
|
||||
// at least one of base and index is variable...
|
||||
|
||||
if (isIoResizeArray(base->getType()))
|
||||
handleIoResizeArrayAccess(loc, base);
|
||||
|
||||
if (index->getQualifier().storage == EvqConst) {
|
||||
if (base->isArray() && base->getType().getArraySize() == 0)
|
||||
updateMaxArraySize(loc, base, indexValue);
|
||||
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
||||
} else {
|
||||
if (base->isArray() && base->getType().getArraySize() == 0)
|
||||
error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
|
||||
if (base->isArray() && base->getType().getArraySize() == 0) {
|
||||
if (isIoResizeArray(base->getType()))
|
||||
error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable");
|
||||
else
|
||||
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");
|
||||
else if (language == EShLangFragment && base->getQualifier().isPipeOutput())
|
||||
@ -474,9 +482,6 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
|
||||
|
||||
if (anyIndexLimits)
|
||||
handleIndexLimits(loc, base, index);
|
||||
|
||||
if (language == EShLangGeometry && base->isArray())
|
||||
handleInputArrayAccess(loc, base);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -523,62 +528,99 @@ void TParseContext::handleIndexLimits(TSourceLoc loc, TIntermTyped* base, TInter
|
||||
}
|
||||
}
|
||||
|
||||
// Handle a dereference of a geometry shader input arrays.
|
||||
// See inputArrayNodeResizeList comment in ParseHelper.h.
|
||||
//
|
||||
void TParseContext::handleInputArrayAccess(TSourceLoc loc, TIntermTyped* base)
|
||||
// Return true if this is a geometry shader input array or tessellation control output array.
|
||||
bool TParseContext::isIoResizeArray(const TType& type)
|
||||
{
|
||||
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);
|
||||
return type.isArray() &&
|
||||
((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) ||
|
||||
(language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch));
|
||||
}
|
||||
|
||||
// Save it in the AST for linker use.
|
||||
intermediate.addSymbolLinkageNode(linkage, *input);
|
||||
// Handle a dereference of a geometry shader input array or tessellation control output array.
|
||||
// See ioArrayNodeResizeList comment in ParseHelper.h.
|
||||
//
|
||||
void TParseContext::handleIoResizeArrayAccess(TSourceLoc loc, TIntermTyped* base)
|
||||
{
|
||||
TIntermSymbol* symbol = base->getAsSymbolNode();
|
||||
assert(symbol);
|
||||
ioArrayNodeResizeList.push_back(symbol);
|
||||
if (symbol && builtInName(symbol->getName())) {
|
||||
// make sure we have a user-modifiable copy of this built-in input array
|
||||
TSymbol* arry = symbolTable.find(symbol->getName());
|
||||
if (arry->isReadOnly()) {
|
||||
arry = symbolTable.copyUp(arry);
|
||||
|
||||
// fix array size, if already implicitly size
|
||||
if (arry->getType().getArraySize() == 0) {
|
||||
int newSize = getIoArrayImplicitSize();
|
||||
if (newSize) {
|
||||
arry->getWritableType().changeArraySize(newSize);
|
||||
symbol->getWritableType().changeArraySize(newSize);
|
||||
}
|
||||
}
|
||||
|
||||
ioArraySymbolResizeList.push_back(arry);
|
||||
|
||||
// Save it in the AST for linker use.
|
||||
intermediate.addSymbolLinkageNode(linkage, *arry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there has been an input primitive declaration, make sure all input array types
|
||||
// If there has been an input primitive declaration (geometry shader) or an output
|
||||
// number of vertices declaration(tessellation shader), 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)
|
||||
void TParseContext::checkIoArraysConsistency(TSourceLoc loc, bool tailOnly)
|
||||
{
|
||||
TLayoutGeometry primitive = intermediate.getInputPrimitive();
|
||||
if (primitive == ElgNone)
|
||||
int requiredSize = getIoArrayImplicitSize();
|
||||
if (requiredSize == 0)
|
||||
return;
|
||||
|
||||
const char* feature;
|
||||
if (language == EShLangGeometry)
|
||||
feature = TQualifier::getGeometryString(intermediate.getInputPrimitive());
|
||||
else if (language == EShLangTessControl)
|
||||
feature = "vertices";
|
||||
|
||||
if (tailOnly) {
|
||||
checkInputArrayConsistency(loc, primitive, inputArraySymbolResizeList.back()->getWritableType(), inputArraySymbolResizeList.back()->getName());
|
||||
checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.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 < ioArrayNodeResizeList.size(); ++i)
|
||||
checkIoArrayConsistency(loc, requiredSize, feature, ioArrayNodeResizeList[i]->getWritableType(), ioArrayNodeResizeList[i]->getName());
|
||||
|
||||
for (size_t i = 0; i < inputArraySymbolResizeList.size(); ++i)
|
||||
checkInputArrayConsistency(loc, primitive, inputArraySymbolResizeList[i]->getWritableType(), inputArraySymbolResizeList[i]->getName());
|
||||
for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i)
|
||||
checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName());
|
||||
}
|
||||
|
||||
void TParseContext::checkInputArrayConsistency(TSourceLoc loc, TLayoutGeometry primitive, TType& type, const TString& name)
|
||||
int TParseContext::getIoArrayImplicitSize() const
|
||||
{
|
||||
int requiredSize = TQualifier::mapGeometryToSize(primitive);
|
||||
if (language == EShLangGeometry)
|
||||
return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive());
|
||||
else if (language == EShLangTessControl)
|
||||
return intermediate.getVertices();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TParseContext::checkIoArrayConsistency(TSourceLoc loc, int requiredSize, const char* feature, TType& type, const TString& name)
|
||||
{
|
||||
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());
|
||||
else if (type.getArraySize() != requiredSize) {
|
||||
if (language == EShLangGeometry)
|
||||
error(loc, "inconsistent input primitive for array size", feature, name.c_str());
|
||||
else if (language == EShLangTessControl)
|
||||
error(loc, "inconsistent output number of vertices for array size", feature, name.c_str());
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -837,13 +879,31 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
|
||||
if (op == EOpArrayLength) {
|
||||
if (fnCall->getParamCount() > 0)
|
||||
error(loc, "method does not accept any arguments", fnCall->getName().c_str(), "");
|
||||
int length;
|
||||
if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray() || intermNode->getAsTyped()->getType().getArraySize() == 0) {
|
||||
error(loc, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
|
||||
length = 1;
|
||||
int length = 0;
|
||||
if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray())
|
||||
error(loc, "", fnCall->getName().c_str(), "can only be applied to an array");
|
||||
else if (intermNode->getAsTyped()->getType().getArraySize() == 0) {
|
||||
bool implicitlySized = false;
|
||||
if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType())) {
|
||||
// We could be between a layout declaration that gives a built-in io array implicit size and
|
||||
// a user redeclaration of that array, meaning we have to substitute its implicit size here
|
||||
// without actually redeclaring the array. (It is an error to use a member before the
|
||||
// redeclaration, but not an error to use the array name itself.)
|
||||
const TString& name = intermNode->getAsSymbolNode()->getName();
|
||||
if (name == "gl_in" || name == "gl_out")
|
||||
length = getIoArrayImplicitSize();
|
||||
}
|
||||
if (length == 0) {
|
||||
if (isIoResizeArray(intermNode->getAsTyped()->getType()))
|
||||
error(loc, "", fnCall->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
|
||||
else
|
||||
error(loc, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
|
||||
}
|
||||
} else
|
||||
length = intermNode->getAsTyped()->getType().getArraySize();
|
||||
|
||||
if (length == 0)
|
||||
length = 1;
|
||||
TConstUnionArray unionArray(1);
|
||||
unionArray[0].setIConst(length);
|
||||
result = intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc);
|
||||
@ -1986,10 +2046,9 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
|
||||
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);
|
||||
if (! symbolTable.atBuiltInLevel() && isIoResizeArray(type)) {
|
||||
ioArraySymbolResizeList.push_back(symbol);
|
||||
checkIoArraysConsistency(loc, true);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -2016,8 +2075,8 @@ 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()))
|
||||
// be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size
|
||||
if (! (isIoResizeArray(type) && newType.getArraySize() == type.getArraySize()))
|
||||
error(loc, "redeclaration of array with size", identifier.c_str(), "");
|
||||
return;
|
||||
}
|
||||
@ -2031,8 +2090,8 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
|
||||
|
||||
newType.shareArraySizes(type);
|
||||
|
||||
if (language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn)
|
||||
checkInputArrayConsistency(loc);
|
||||
if (isIoResizeArray(type))
|
||||
checkIoArraysConsistency(loc);
|
||||
}
|
||||
|
||||
void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int index)
|
||||
@ -2064,9 +2123,8 @@ void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int in
|
||||
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);
|
||||
if (isIoResizeArray(symbol->getType()))
|
||||
ioArraySymbolResizeList.push_back(symbol);
|
||||
|
||||
// Save it in the AST for linker use.
|
||||
intermediate.addSymbolLinkageNode(linkage, *symbol);
|
||||
@ -2128,16 +2186,15 @@ TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString&
|
||||
return 0;
|
||||
|
||||
// If it wasn't at a built-in level, then it's already been redeclared;
|
||||
// that is, this is a redeclaration of a redeclaration, reuse that initial
|
||||
// that is, this is a redeclaration of a redeclaration; reuse that initial
|
||||
// redeclaration. Otherwise, make the new one.
|
||||
if (builtIn) {
|
||||
// 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);
|
||||
if (isIoResizeArray(symbol->getType()))
|
||||
ioArraySymbolResizeList.push_back(symbol);
|
||||
|
||||
// Save it in the AST for linker use.
|
||||
intermediate.addSymbolLinkageNode(linkage, *symbol);
|
||||
@ -2248,10 +2305,6 @@ void TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& newTypeList
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Edit and error check the container against the redeclaration
|
||||
// - remove unused members
|
||||
// - ensure remaining qualifiers/types match
|
||||
@ -2320,12 +2373,20 @@ void TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& newTypeList
|
||||
error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), "");
|
||||
else if (type.isArray() && type.getArraySize() > 0 && type.getArraySize() != arraySizes->getSize())
|
||||
error(loc, "cannot change array size of redeclared block", blockName.c_str(), "");
|
||||
else if (type.isArray() && type.getArraySize() == 0 && arraySizes->getSize() > 0)
|
||||
type.changeArraySize(arraySizes->getSize());
|
||||
|
||||
symbolTable.insert(*block);
|
||||
|
||||
// Check for general layout qualifier errors
|
||||
layoutTypeCheck(loc, *block);
|
||||
|
||||
// Tracking for implicit sizing of array
|
||||
if (isIoResizeArray(block->getType())) {
|
||||
ioArraySymbolResizeList.push_back(block);
|
||||
checkIoArraysConsistency(loc, true);
|
||||
}
|
||||
|
||||
// Save it in the AST for linker use.
|
||||
intermediate.addSymbolLinkageNode(linkage, *block);
|
||||
}
|
||||
@ -2728,8 +2789,6 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
|
||||
|
||||
case EShLangTessControl:
|
||||
if (id == "vertices") {
|
||||
// TODO: tessellation: implement gl_out[] array sizing based on this
|
||||
// TODO: tessellation: semantic check this is on the out qualifier only
|
||||
publicType.shaderQualifiers.vertices = value;
|
||||
return;
|
||||
}
|
||||
@ -2932,8 +2991,14 @@ void TParseContext::checkNoShaderLayouts(TSourceLoc loc, const TShaderQualifiers
|
||||
error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), "");
|
||||
if (shaderQualifiers.invocations > 0)
|
||||
error(loc, message, "invocations", "");
|
||||
if (shaderQualifiers.vertices > 0)
|
||||
error(loc, message, "max_vertices", "");
|
||||
if (shaderQualifiers.vertices > 0) {
|
||||
if (language == EShLangGeometry)
|
||||
error(loc, message, "max_vertices", "");
|
||||
else if (language == EShLangTessControl)
|
||||
error(loc, message, "vertices", "");
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -3726,8 +3791,15 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
|
||||
if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) {
|
||||
if (language == EShLangGeometry)
|
||||
error(loc, "cannot change previously set layout value", "max_vertices", "");
|
||||
else
|
||||
else if (language == EShLangTessControl)
|
||||
error(loc, "cannot change previously set layout value", "vertices", "");
|
||||
else
|
||||
assert(0);
|
||||
} else if (language == EShLangTessControl) {
|
||||
if (publicType.qualifier.storage != EvqVaryingOut)
|
||||
error(loc, "can only apply to 'out'", "vertices", "");
|
||||
else
|
||||
checkIoArraysConsistency(loc);
|
||||
}
|
||||
}
|
||||
if (publicType.shaderQualifiers.invocations) {
|
||||
@ -3744,9 +3816,10 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
|
||||
case ElgTrianglesAdjacency:
|
||||
case ElgQuads:
|
||||
case ElgIsolines:
|
||||
if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry))
|
||||
checkInputArrayConsistency(loc);
|
||||
else
|
||||
if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) {
|
||||
if (language == EShLangGeometry)
|
||||
checkIoArraysConsistency(loc);
|
||||
} else
|
||||
error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
|
||||
break;
|
||||
default:
|
||||
@ -3761,7 +3834,7 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
|
||||
error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
|
||||
break;
|
||||
default:
|
||||
error(loc, "does not only apply to output", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
|
||||
error(loc, "does not apply to output", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
|
||||
}
|
||||
} else
|
||||
error(loc, "cannot be used here", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
|
||||
|
@ -84,9 +84,13 @@ public:
|
||||
TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
|
||||
void checkIndex(TSourceLoc, const TType&, int& 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&);
|
||||
|
||||
bool isIoResizeArray(const TType&);
|
||||
void handleIoResizeArrayAccess(TSourceLoc, TIntermTyped* base);
|
||||
void checkIoArraysConsistency(TSourceLoc, bool tailOnly = false);
|
||||
int getIoArrayImplicitSize() const;
|
||||
void checkIoArrayConsistency(TSourceLoc, int requiredSize, const char* feature, TType&, const TString&);
|
||||
|
||||
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
|
||||
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype);
|
||||
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
|
||||
@ -257,6 +261,11 @@ protected:
|
||||
//
|
||||
// Geometry shader input arrays:
|
||||
// - array sizing is based on input primitive and/or explicit size
|
||||
//
|
||||
// Tessellation control output arrays:
|
||||
// - array sizing is based on output layout(vertices=...) and/or explicit size
|
||||
//
|
||||
// Both:
|
||||
// - array sizing is retroactive
|
||||
// - built-in block redeclarations interact with this
|
||||
//
|
||||
@ -270,23 +279,23 @@ protected:
|
||||
// - 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
|
||||
// - on built-in 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 user 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 a layout declaration that sizes the array, 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
|
||||
// array-sizing declarations
|
||||
//
|
||||
TVector<TIntermSymbol*> inputArrayNodeResizeList;
|
||||
TVector<TSymbol*> inputArraySymbolResizeList;
|
||||
TVector<TIntermSymbol*> ioArrayNodeResizeList;
|
||||
TVector<TSymbol*> ioArraySymbolResizeList;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
@ -88,8 +88,14 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
|
||||
|
||||
if (vertices == 0)
|
||||
vertices = unit.vertices;
|
||||
else if (vertices != unit.vertices)
|
||||
error(infoSink, "Contradictory layout max_vertices values");
|
||||
else if (vertices != unit.vertices) {
|
||||
if (language == EShLangGeometry)
|
||||
error(infoSink, "Contradictory layout max_vertices values");
|
||||
else if (language == EShLangTessControl)
|
||||
error(infoSink, "Contradictory layout vertices values");
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (vertexSpacing == EvsNone)
|
||||
vertexSpacing = unit.vertexSpacing;
|
||||
@ -297,11 +303,14 @@ void TIntermediate::finalCheck(TInfoSink& infoSink)
|
||||
|
||||
switch (language) {
|
||||
case EShLangVertex:
|
||||
break;
|
||||
case EShLangTessControl:
|
||||
if (vertices == 0)
|
||||
error(infoSink, "At least one shader must specify an output layout(vertices=...)");
|
||||
break;
|
||||
case EShLangTessEvaluation:
|
||||
if (inputPrimitive == ElgNone)
|
||||
error(infoSink, "At least one tessellation shader must specify an input layout primitive");
|
||||
error(infoSink, "At least one shader must specify an input layout primitive");
|
||||
if (vertexSpacing == EvsNone)
|
||||
vertexSpacing = EvsEqual;
|
||||
if (vertexOrder == EvoNone)
|
||||
@ -309,13 +318,14 @@ void TIntermediate::finalCheck(TInfoSink& infoSink)
|
||||
break;
|
||||
case EShLangGeometry:
|
||||
if (inputPrimitive == ElgNone)
|
||||
error(infoSink, "At least one geometry shader must specify an input layout primitive");
|
||||
error(infoSink, "At least one shader must specify an input layout primitive");
|
||||
if (outputPrimitive == ElgNone)
|
||||
error(infoSink, "At least one geometry shader must specify an output layout primitive");
|
||||
error(infoSink, "At least one shader must specify an output layout primitive");
|
||||
if (vertices == 0)
|
||||
error(infoSink, "At least one geometry shader must specify a layout(max_vertices = value)");
|
||||
error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
|
||||
break;
|
||||
case EShLangFragment:
|
||||
break;
|
||||
case EShLangCompute:
|
||||
break;
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ public:
|
||||
vertices = m;
|
||||
return true;
|
||||
}
|
||||
int getVertices() const { return vertices; }
|
||||
bool setInputPrimitive(TLayoutGeometry p)
|
||||
{
|
||||
if (inputPrimitive != ElgNone)
|
||||
|
Loading…
Reference in New Issue
Block a user