aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Kessenich <cepheus@frii.com>2014-01-08 23:25:18 +0000
committerJohn Kessenich <cepheus@frii.com>2014-01-08 23:25:18 +0000
commit68546c6ca4bf2dcebb57dbaeec71082d3f2edd2a (patch)
treeebaffeda65c21621e464b1a8d4c51cbd5a41117a
parentb76d6d64968b55bdefa0fa5360b88c44b09d3514 (diff)
downloadglslang-68546c6ca4bf2dcebb57dbaeec71082d3f2edd2a.tar.gz
GL_ARB_enhanced_layouts, part 2: Full implementation of location/component, plus the parsing for xfb* and align/offset (but not yet full semantics for align/offset).
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24692 e7fa87d3-cd2b-0410-9028-fcbf551c1848
-rw-r--r--Test/330.frag65
-rw-r--r--Test/440.frag22
-rw-r--r--Test/440.vert64
-rw-r--r--Test/baseResults/150.geom.out4
-rw-r--r--Test/baseResults/150.tesc.out8
-rw-r--r--Test/baseResults/300layout.frag.out4
-rw-r--r--Test/baseResults/300layout.vert.out10
-rw-r--r--Test/baseResults/330.frag.out29
-rw-r--r--Test/baseResults/400.geom.out2
-rw-r--r--Test/baseResults/430.vert.out4
-rw-r--r--Test/baseResults/440.frag.out25
-rw-r--r--Test/baseResults/440.vert.out66
-rw-r--r--Test/baseResults/specExamples.frag.out2
-rw-r--r--Test/baseResults/specExamples.vert.out12
-rw-r--r--Test/testlist2
-rw-r--r--Todo.txt24
-rw-r--r--glslang/Include/Types.h72
-rw-r--r--glslang/Include/revision.h4
-rw-r--r--glslang/MachineIndependent/ParseHelper.cpp253
-rw-r--r--glslang/MachineIndependent/ParseHelper.h4
-rw-r--r--glslang/MachineIndependent/linkValidate.cpp38
-rw-r--r--glslang/MachineIndependent/localintermediate.h14
22 files changed, 615 insertions, 113 deletions
diff --git a/Test/330.frag b/Test/330.frag
index b90ae54e..3fad83b8 100644
--- a/Test/330.frag
+++ b/Test/330.frag
@@ -45,9 +45,72 @@ layout(location = -2) in vec4 v1; // ERROR
layout(location = start + 2) in vec4 v2; // ERROR
layout(location = 4.7e10) in vec4 v20; // ERROR
+struct S {
+ float f1;
+ layout(location = 3) float f2; // ERROR
+};
+
+layout(location = 1) in inblock { // ERROR
+ float f1;
+ layout(location = 3) float f2; // ERROR
+};
+
+layout(location = 1) uniform ublock { // ERROR
+ float f1;
+ layout(location = 3) float f2; // ERROR
+} uinst;
+
#extension GL_ARB_enhanced_layouts : enable
layout(location = start) in vec4 v3;
layout(location = -2) in vec4 v4; // ERROR
layout(location = -start) in vec4 v5; // ERROR
-layout(location = start*start - 2) in vec4 v6;
+layout(location = start*start - 2 - 4) in vec4 v6;
+
+struct S2 {
+ float f1;
+ layout(location = 3) float f2; // ERROR
+};
+
+layout(location = 28) in inblock2 {
+ bool b1;
+ float f1;
+ layout(location = 25) float f2;
+ vec4 f3;
+ layout(location = 21) S2 s2;
+ vec4 f4;
+ vec4 f5;
+} ininst2;
+
+layout(location = 13) uniform ublock2 { // ERROR
+ float f1;
+ layout(location = 3) float f2; // ERROR
+} uinst2;
+
+in inblock3 { // ERROR, mix of location internal with no location external
+ float f1;
+ layout(location = 40) float f2;
+} in3;
+
+in ublock4 {
+ layout(location = 50) float f1;
+ layout(location = 51) float f2;
+} in4;
+
+layout(location = 33) in struct SS {
+ vec3 a; // gets location 33
+ mat2 b; // gets locations 34 and 35
+ vec4 c[2]; // gets locations 36 and 37
+ layout (location = 38) vec2 A; // ERROR, can't use on struct member
+} s;
+
+layout(location = 44) in block {
+ vec4 d; // gets location 44
+ vec4 e; // gets location 45
+ layout(location = 47) vec4 f; // gets location 47
+ vec4 g; // gets location 48
+ layout (location = 41) vec4 h; // gets location 41
+ vec4 i; // gets location 42
+ vec4 j; // gets location 43
+ vec4 k; // ERROR, location 44 already used
+};
diff --git a/Test/440.frag b/Test/440.frag
new file mode 100644
index 00000000..23c43b47
--- /dev/null
+++ b/Test/440.frag
@@ -0,0 +1,22 @@
+#version 440
+
+// Note 'location'-only tests for enhanced layouts are in 330.frag
+// Generic 'component' tests are in 440.vert
+
+// a consumes components 2 and 3 of location 4
+layout(location = 4, component = 2) in vec2 a;
+
+// b consumes component 1 of location 4
+layout(location = 4, component = 1) in float b;
+layout(location = 4, component = 2) in vec2 h; // ERROR, component overlap not okay for fragment in
+
+layout(location = 3, component = 2) in vec3 c; // ERROR: c overflows components 2 and 3
+
+// e consumes beginning (components 0, 1 and 2) of each of 6 slots
+layout(location = 20, component = 0) in vec3 e[6];
+
+// f consumes last component of the same 6 slots
+layout(location = 20, component = 3) in float f[6];
+
+layout(location = 30, component = 3) out int be;
+layout(location = 30, component = 0) out vec3 bf; // ERROR, not the same basic type
diff --git a/Test/440.vert b/Test/440.vert
new file mode 100644
index 00000000..3aeebaa8
--- /dev/null
+++ b/Test/440.vert
@@ -0,0 +1,64 @@
+#version 440
+
+// Note 'location' tests for enhanced layouts are in 330.frag
+
+layout(location = 2, component = 2) in vec2 a;
+layout(location = 2, component = 1) in float b;
+
+layout(location = 3, component = 2) in vec3 c; // ERROR: c overflows components 2 and 3
+
+layout(location = 0, component = 3) in float d[4];
+
+layout(location = 4, component = 0) in vec3 e[5];
+layout(location = 4, component = 3) in float f[5];
+
+layout(location = 9, component = 4) in float g[6]; // ERROR, component too big
+
+layout(location = 4, component = 2) in vec2 h; // component overlap okay for vertex in
+
+layout(location = 3, component = 2) out vec2 i;
+layout(location = 3, component = 0) out vec2 j;
+
+layout(location = 4, component = 2) out vec2 k;
+layout(location = 4, component = 2) out vec2 m; // ERROR, component overlap
+
+layout(location = 2, component = 2) out vec2 n;
+layout(location = 2, component = 0) out vec3 p; // ERROR, component overlap
+
+layout(location = 10, component = 3) out float q[6];
+layout(location = 10, component = 0) out vec3 r[6];
+
+layout(location = 15, component = 3) out float s; // ERROR, overlap
+layout(location = 10, component = 1) out float t; // ERROR, overlap
+
+layout(location = 20, component = 2) out float u;
+layout(location = 20, component = 0) out float v;
+layout(location = 20, component = 3) out float w;
+layout(location = 20, component = 1) out vec2 x; // ERROR, overlap
+
+layout(location = 30, component = 3) out vec2 y; // ERROR, goes to component 4
+layout(location = 31, component = 1) out vec4 z; // ERROR, goes to component 4
+
+layout(location = 32, component = 1) out mat4 ba; // ERROR
+layout(location = 33, component = 1) out struct S {int a;} Ss; // ERROR
+layout(location = 34, component = 1) out bn { int a;} bb; // ERROR
+
+layout(component = 1) out float bc; // ERROR, no location
+
+out blockname {
+ layout(location = 40, component = 2) out float u;
+ layout(location = 40, component = 0) out float v;
+ layout(location = 40, component = 3) out float w;
+ layout(location = 40, component = 1) out vec2 x; // ERROR, overlap
+
+ layout(location = 41, component = 3) out vec2 y; // ERROR, goes to component 4
+ layout(location = 42, component = 1) out vec4 z; // ERROR, goes to component 4
+
+ layout(location = 42, component = 1) out mat4 ba; // ERROR
+ layout(location = 43, component = 1) out S Ss; // ERROR
+} bd;
+
+layout(location = 1, component = 1) out; // ERROR, no global setting
+
+layout(location = 50, component = 3) out int be;
+layout(location = 50, component = 0) out vec3 bf;
diff --git a/Test/baseResults/150.geom.out b/Test/baseResults/150.geom.out
index 59180a70..30fd4bab 100644
--- a/Test/baseResults/150.geom.out
+++ b/Test/baseResults/150.geom.out
@@ -9,6 +9,7 @@ ERROR: 0:44: 'stream' : can only be used on an output
ERROR: 0:45: 'stream' : can only be used on an output
ERROR: 0:46: 'stream' : can only be used on an output
ERROR: 0:47: 'stream' : can only be used on an output
+ERROR: 0:47: 'stream' : can only be used on an output
ERROR: 0:60: 'stream' : member cannot contradict block
ERROR: 0:65: 'max_vertices' : can only apply to a standalone qualifier
ERROR: 0:70: 'points' : cannot change previously set output primitive
@@ -29,7 +30,8 @@ ERROR: 0:86: 'triangles_adjacency' : cannot change previously set input primitiv
ERROR: 0:87: 'invocations' : not supported for this version or the enabled extensions
ERROR: 0:88: 'max_vertices' : too large, must be less than gl_MaxGeometryOutputVertices
ERROR: 0:91: 'stream' : member cannot contradict block
-ERROR: 29 compilation errors. No code generated.
+ERROR: 0:91: 'stream' : can only be used on an output
+ERROR: 31 compilation errors. No code generated.
invocations = 4
diff --git a/Test/baseResults/150.tesc.out b/Test/baseResults/150.tesc.out
index f6258e9e..30646f91 100644
--- a/Test/baseResults/150.tesc.out
+++ b/Test/baseResults/150.tesc.out
@@ -221,8 +221,8 @@ ERROR: 0:40: 'vertices' : cannot change previously set layout value
ERROR: 0:44: '[' : array index out of range '4'
ERROR: 0:47: 'in' : type must be an array: ina
ERROR: 0:49: '[]' : tessellation input array size must be gl_MaxPatchVertices or unsized
-ERROR: 0:56: 'location' : repeated use of location 4
-ERROR: 0:60: 'location' : repeated use of location 4
+ERROR: 0:56: 'location' : overlapping use of location 4
+ERROR: 0:60: 'location' : overlapping use of location 4
ERROR: 11 compilation errors. No code generated.
@@ -381,8 +381,8 @@ ERROR: 0:73: 'in' : type must be an array: ina
ERROR: 0:75: '[]' : tessellation input array size must be gl_MaxPatchVertices or unsized
ERROR: 0:78: 'in' : type must be an array: bla
ERROR: 0:86: '[]' : tessellation input array size must be gl_MaxPatchVertices or unsized
-ERROR: 0:96: 'location' : repeated use of location 24
-ERROR: 0:99: 'location' : repeated use of location 24
+ERROR: 0:96: 'location' : overlapping use of location 24
+ERROR: 0:99: 'location' : overlapping use of location 24
ERROR: 29 compilation errors. No code generated.
diff --git a/Test/baseResults/300layout.frag.out b/Test/baseResults/300layout.frag.out
index ac665696..0c952e44 100644
--- a/Test/baseResults/300layout.frag.out
+++ b/Test/baseResults/300layout.frag.out
@@ -1,7 +1,7 @@
300layout.frag
ERROR: 0:4: 'location qualifier on input' : not supported in this stage: fragment
-ERROR: 0:18: 'location' : repeated use of location 41
-ERROR: 0:19: 'location' : repeated use of location 40
+ERROR: 0:18: 'location' : overlapping use of location 41
+ERROR: 0:19: 'location' : overlapping use of location 40
ERROR: 3 compilation errors. No code generated.
diff --git a/Test/baseResults/300layout.vert.out b/Test/baseResults/300layout.vert.out
index a34e63f1..4ce58fa0 100644
--- a/Test/baseResults/300layout.vert.out
+++ b/Test/baseResults/300layout.vert.out
@@ -2,9 +2,9 @@
ERROR: 0:7: 'vertex input arrays' : not supported with this profile: es
ERROR: 0:8: 'in' : cannot be a structure or array
ERROR: 0:8: 'vertex input arrays' : not supported with this profile: es
-ERROR: 0:8: 'location' : repeated use of location 10
-ERROR: 0:12: 'badm4' : cannot specify matrix layout on a variable declaration
-ERROR: 0:12: 'badm4' : cannot specify packing on a variable declaration
+ERROR: 0:8: 'location' : overlapping use of location 10
+ERROR: 0:12: 'layout' : cannot specify matrix layout on a variable declaration
+ERROR: 0:12: 'layout' : cannot specify packing on a variable declaration
ERROR: 0:19: 'badf' : member of uniform block cannot have an auxiliary or interpolation qualifier
ERROR: 0:20: 'badg' : member storage qualifier cannot contradict block storage qualifier
ERROR: 0:21: 'bad1' : member of block cannot have a packing layout qualifier
@@ -15,8 +15,8 @@ ERROR: 0:38: 'output block' : not supported with this profile: es
ERROR: 0:42: 'location qualifier on output' : not supported in this stage: vertex
ERROR: 0:50: 'shared' : not supported with this profile: es
ERROR: 0:50: 'shared' : not supported in this stage: vertex
-ERROR: 0:54: 'aoeuntaoeu' : layout qualifiers for matrix layout and packing only apply to uniform or buffer blocks
-ERROR: 0:57: 'location' : repeated use of location 40
+ERROR: 0:54: 'layout' : qualifiers for matrix layout and block packing only apply to uniform or buffer blocks
+ERROR: 0:57: 'location' : overlapping use of location 40
ERROR: 18 compilation errors. No code generated.
diff --git a/Test/baseResults/330.frag.out b/Test/baseResults/330.frag.out
index 0ada0598..f8e9f2b4 100644
--- a/Test/baseResults/330.frag.out
+++ b/Test/baseResults/330.frag.out
@@ -10,9 +10,22 @@ ERROR: 0:44: 'layout-id value' : cannot be negative
ERROR: 0:45: 'non-literal layout-id value' : not supported for this version or the enabled extensions
ERROR: 0:46: 'layout-id value' : scalar integer expression required
ERROR: 0:46: 'location' : location is too large
-ERROR: 0:51: 'layout-id value' : cannot be negative
-ERROR: 0:52: 'layout-id value' : cannot be negative
-ERROR: 12 compilation errors. No code generated.
+ERROR: 0:50: 'f2' : cannot use layout qualifiers on structure members
+ERROR: 0:55: 'location on block member' : not supported for this version or the enabled extensions
+ERROR: 0:60: 'location on block member' : can only use in an in/out block
+ERROR: 0:60: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
+ERROR: 0:58: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
+ERROR: 0:66: 'layout-id value' : cannot be negative
+ERROR: 0:67: 'layout-id value' : cannot be negative
+ERROR: 0:72: 'f2' : cannot use layout qualifiers on structure members
+ERROR: 0:87: 'location on block member' : can only use in an in/out block
+ERROR: 0:87: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
+ERROR: 0:87: 'location' : overlapping use of location 3
+ERROR: 0:85: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
+ERROR: 0:90: 'location' : either the block needs a location, or all members need a location, or no members have a location
+ERROR: 0:104: 'A' : cannot use layout qualifiers on structure members
+ERROR: 0:115: 'location' : overlapping use of location 44
+ERROR: 25 compilation errors. No code generated.
ERROR: node is still EOpNull!
@@ -57,10 +70,18 @@ ERROR: node is still EOpNull!
0:? 'v1' (smooth in 4-component vector of float)
0:? 'v2' (layout(location=8 ) smooth in 4-component vector of float)
0:? 'v20' (smooth in 4-component vector of float)
+0:? '__anon__1' (in block{layout(location=1 component=0 ) in float f1, layout(location=3 ) in float f2})
+0:? 'uinst' (layout(location=1 column_major shared ) uniform block{layout(column_major shared ) uniform float f1, layout(location=3 column_major shared ) uniform float f2})
0:? 'v3' (layout(location=6 ) smooth in 4-component vector of float)
0:? 'v4' (smooth in 4-component vector of float)
0:? 'v5' (smooth in 4-component vector of float)
-0:? 'v6' (layout(location=34 ) smooth in 4-component vector of float)
+0:? 'v6' (layout(location=30 ) smooth in 4-component vector of float)
+0:? 'ininst2' (in block{layout(location=28 component=0 ) in bool b1, layout(location=29 component=0 ) in float f1, layout(location=25 ) in float f2, layout(location=26 component=0 ) in 4-component vector of float f3, layout(location=21 ) in structure{float f1, float f2} s2, layout(location=23 component=0 ) in 4-component vector of float f4, layout(location=24 component=0 ) in 4-component vector of float f5})
+0:? 'uinst2' (layout(location=13 column_major shared ) uniform block{layout(column_major shared ) uniform float f1, layout(location=3 column_major shared ) uniform float f2})
+0:? 'in3' (in block{in float f1, layout(location=40 ) in float f2})
+0:? 'in4' (in block{layout(location=50 ) in float f1, layout(location=51 ) in float f2})
+0:? 's' (layout(location=33 ) smooth in structure{3-component vector of float a, 2X2 matrix of float b, 2-element array of 4-component vector of float c, 2-component vector of float A})
+0:? '__anon__2' (in block{layout(location=44 component=0 ) in 4-component vector of float d, layout(location=45 component=0 ) in 4-component vector of float e, layout(location=47 ) in 4-component vector of float f, layout(location=48 component=0 ) in 4-component vector of float g, layout(location=41 ) in 4-component vector of float h, layout(location=42 component=0 ) in 4-component vector of float i, layout(location=43 component=0 ) in 4-component vector of float j, layout(location=44 component=0 ) in 4-component vector of float k})
Linked fragment stage:
diff --git a/Test/baseResults/400.geom.out b/Test/baseResults/400.geom.out
index d2e69a8b..163ebfd3 100644
--- a/Test/baseResults/400.geom.out
+++ b/Test/baseResults/400.geom.out
@@ -8,7 +8,7 @@ ERROR: 0:25: 'length' : array must first be sized by a redeclaration or layout
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 of colorBad
ERROR: 0:44: 'triangles' : inconsistent input primitive for array size of colorbad2
-ERROR: 0:56: 'location' : repeated use of location 4
+ERROR: 0:56: 'location' : overlapping use of location 4
ERROR: 0:58: 'patch' : not supported in this stage: geometry
ERROR: 0:59: 'patch' : not supported in this stage: geometry
ERROR: 0:61: 'in' : type must be an array: scalar
diff --git a/Test/baseResults/430.vert.out b/Test/baseResults/430.vert.out
index f407711c..9176bfa2 100644
--- a/Test/baseResults/430.vert.out
+++ b/Test/baseResults/430.vert.out
@@ -1,6 +1,6 @@
430.vert
Warning, version 430 is not yet complete; some version-specific features are present, but many are missing.
-ERROR: 0:3: 'v4' : location qualifiers only appy to uniform, buffer, in, or out storage qualifiers
+ERROR: 0:3: 'location' : can only appy to uniform, buffer, in, or out storage qualifiers
ERROR: 0:7: 'location qualifier on in/out block' : not supported for this version or the enabled extensions
ERROR: 0:8: 'location qualifier on in/out block' : not supported for this version or the enabled extensions
ERROR: 0:21: 'g' : cannot use storage or interpolation qualifiers on structure members
@@ -11,7 +11,7 @@ ERROR: 0:25: 'm3' : cannot use layout qualifiers on structure members
ERROR: 0:28: '' : cannot use invariant qualifier on a function parameter
ERROR: 0:30: '' : cannot use layout qualifiers on a function parameter
ERROR: 0:31: '' : cannot use auxiliary or interpolation qualifiers on a function parameter
-ERROR: 0:42: 'location' : repeated use of location 53
+ERROR: 0:42: 'location' : overlapping use of location 53
ERROR: 0:47: 'gl_ClipDistance array size' : must be less than gl_MaxClipDistances (8)
ERROR: 13 compilation errors. No code generated.
diff --git a/Test/baseResults/440.frag.out b/Test/baseResults/440.frag.out
new file mode 100644
index 00000000..771715ff
--- /dev/null
+++ b/Test/baseResults/440.frag.out
@@ -0,0 +1,25 @@
+440.frag
+Warning, version 440 is not yet complete; some version-specific features are present, but many are missing.
+ERROR: 0:11: 'location' : overlapping use of location 4
+ERROR: 0:13: 'component' : type overflows the available 4 components
+ERROR: 0:22: 'location' : fragment outputs sharing the same location must be the same basic type 30
+ERROR: 3 compilation errors. No code generated.
+
+
+ERROR: node is still EOpNull!
+0:? Linker Objects
+0:? 'a' (layout(location=4 component=2 ) smooth in 2-component vector of float)
+0:? 'b' (layout(location=4 component=1 ) smooth in float)
+0:? 'h' (layout(location=4 component=2 ) smooth in 2-component vector of float)
+0:? 'c' (layout(location=3 component=2 ) smooth in 3-component vector of float)
+0:? 'e' (layout(location=20 component=0 ) smooth in 6-element array of 3-component vector of float)
+0:? 'f' (layout(location=20 component=3 ) smooth in 6-element array of float)
+0:? 'be' (layout(location=30 component=3 ) out int)
+0:? 'bf' (layout(location=30 component=0 ) out 3-component vector of float)
+
+
+Linked fragment stage:
+
+ERROR: Linking fragment stage: Missing entry point: Each stage requires one "void main()" entry point
+
+
diff --git a/Test/baseResults/440.vert.out b/Test/baseResults/440.vert.out
new file mode 100644
index 00000000..ed94e051
--- /dev/null
+++ b/Test/baseResults/440.vert.out
@@ -0,0 +1,66 @@
+440.vert
+Warning, version 440 is not yet complete; some version-specific features are present, but many are missing.
+ERROR: 0:8: 'component' : type overflows the available 4 components
+ERROR: 0:15: 'component' : component is too large
+ERROR: 0:23: 'location' : overlapping use of location 4
+ERROR: 0:26: 'location' : overlapping use of location 2
+ERROR: 0:31: 'location' : overlapping use of location 15
+ERROR: 0:32: 'location' : overlapping use of location 10
+ERROR: 0:37: 'location' : overlapping use of location 20
+ERROR: 0:39: 'component' : type overflows the available 4 components
+ERROR: 0:40: 'component' : type overflows the available 4 components
+ERROR: 0:42: 'component' : cannot apply to a matrix, structure, or block
+ERROR: 0:43: 'component' : cannot apply to a matrix, structure, or block
+ERROR: 0:44: 'component' : cannot apply to a matrix, structure, or block
+ERROR: 0:46: 'component' : must specify 'location' to use 'component'
+ERROR: 0:52: 'location' : overlapping use of location 40
+ERROR: 0:54: 'component' : type overflows the available 4 components
+ERROR: 0:55: 'component' : type overflows the available 4 components
+ERROR: 0:57: 'component' : cannot apply to a matrix, structure, or block
+ERROR: 0:58: 'component' : cannot apply to a matrix, structure, or block
+ERROR: 0:61: 'location' : cannot declare a default, use a full declaration
+ERROR: 19 compilation errors. No code generated.
+
+
+ERROR: node is still EOpNull!
+0:? Linker Objects
+0:? 'a' (layout(location=2 component=2 ) in 2-component vector of float)
+0:? 'b' (layout(location=2 component=1 ) in float)
+0:? 'c' (layout(location=3 component=2 ) in 3-component vector of float)
+0:? 'd' (layout(location=0 component=3 ) in 4-element array of float)
+0:? 'e' (layout(location=4 component=0 ) in 5-element array of 3-component vector of float)
+0:? 'f' (layout(location=4 component=3 ) in 5-element array of float)
+0:? 'g' (layout(location=9 ) in 6-element array of float)
+0:? 'h' (layout(location=4 component=2 ) in 2-component vector of float)
+0:? 'i' (layout(location=3 component=2 ) smooth out 2-component vector of float)
+0:? 'j' (layout(location=3 component=0 ) smooth out 2-component vector of float)
+0:? 'k' (layout(location=4 component=2 ) smooth out 2-component vector of float)
+0:? 'm' (layout(location=4 component=2 ) smooth out 2-component vector of float)
+0:? 'n' (layout(location=2 component=2 ) smooth out 2-component vector of float)
+0:? 'p' (layout(location=2 component=0 ) smooth out 3-component vector of float)
+0:? 'q' (layout(location=10 component=3 ) smooth out 6-element array of float)
+0:? 'r' (layout(location=10 component=0 ) smooth out 6-element array of 3-component vector of float)
+0:? 's' (layout(location=15 component=3 ) smooth out float)
+0:? 't' (layout(location=10 component=1 ) smooth out float)
+0:? 'u' (layout(location=20 component=2 ) smooth out float)
+0:? 'v' (layout(location=20 component=0 ) smooth out float)
+0:? 'w' (layout(location=20 component=3 ) smooth out float)
+0:? 'x' (layout(location=20 component=1 ) smooth out 2-component vector of float)
+0:? 'y' (layout(location=30 component=3 ) smooth out 2-component vector of float)
+0:? 'z' (layout(location=31 component=1 ) smooth out 4-component vector of float)
+0:? 'ba' (layout(location=32 component=1 ) smooth out 4X4 matrix of float)
+0:? 'Ss' (layout(location=33 component=1 ) smooth out structure{int a})
+0:? 'bb' (layout(location=34 component=1 ) out block{out int a})
+0:? 'bc' (layout(location=63 component=1 ) smooth out float)
+0:? 'bd' (out block{layout(location=40 component=2 ) out float u, layout(location=40 component=0 ) out float v, layout(location=40 component=3 ) out float w, layout(location=40 component=1 ) out 2-component vector of float x, layout(location=41 component=3 ) out 2-component vector of float y, layout(location=42 component=1 ) out 4-component vector of float z, layout(location=42 component=1 ) out 4X4 matrix of float ba, layout(location=43 component=1 ) out structure{int a} Ss})
+0:? 'be' (layout(location=50 component=3 ) smooth out int)
+0:? 'bf' (layout(location=50 component=0 ) smooth out 3-component vector of float)
+0:? 'gl_VertexID' (gl_VertexId int)
+0:? 'gl_InstanceID' (gl_InstanceId int)
+
+
+Linked vertex stage:
+
+ERROR: Linking vertex stage: Missing entry point: Each stage requires one "void main()" entry point
+
+
diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out
index cc136af9..9c0c1c52 100644
--- a/Test/baseResults/specExamples.frag.out
+++ b/Test/baseResults/specExamples.frag.out
@@ -16,7 +16,7 @@ ERROR: 0:99: 'local_size_y' : there is no such layout identifier for this stage
ERROR: 0:100: 'local_size_x' : there is no such layout identifier for this stage taking an assigned value
ERROR: 0:102: 'color' : redefinition
ERROR: 0:103: 'index' : there is no such layout identifier for this stage taking an assigned value
-ERROR: 0:104: 'location' : repeated use of location 3
+ERROR: 0:104: 'location' : overlapping use of location 3
ERROR: 0:106: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
ERROR: 0:112: 'depth_any' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
ERROR: 0:115: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
diff --git a/Test/baseResults/specExamples.vert.out b/Test/baseResults/specExamples.vert.out
index 1d3416d3..c9ce1621 100644
--- a/Test/baseResults/specExamples.vert.out
+++ b/Test/baseResults/specExamples.vert.out
@@ -1,7 +1,7 @@
specExamples.vert
Warning, version 430 is not yet complete; some version-specific features are present, but many are missing.
ERROR: 0:23: 'transforms' : redeclaration of array with size
-ERROR: 0:29: 's' : location qualifiers only appy to uniform, buffer, in, or out storage qualifiers
+ERROR: 0:29: 'location' : can only appy to uniform, buffer, in, or out storage qualifiers
ERROR: 0:31: 'triangles' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
ERROR: 0:31: 'invocations' : there is no such layout identifier for this stage taking an assigned value
ERROR: 0:33: 'lines' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)
@@ -17,15 +17,15 @@ ERROR: 0:47: 'stream' : there is no such layout identifier for this stage taking
ERROR: 0:50: 'stream' : there is no such layout identifier for this stage taking an assigned value
ERROR: 0:55: 'stream' : there is no such layout identifier for this stage taking an assigned value
ERROR: 0:80: 's17' : redefinition
-ERROR: 0:85: 'offset' : there is no such layout identifier for this stage taking an assigned value
+ERROR: 0:85: 'uniform buffer-member offset' : not supported for this version or the enabled extensions
ERROR: 0:85: 'binding' : requires block, or sampler/image, or atomic-counter type
ERROR: 0:87: 'binding' : requires block, or sampler/image, or atomic-counter type
-ERROR: 0:89: 'offset' : there is no such layout identifier for this stage taking an assigned value
+ERROR: 0:89: 'uniform buffer-member offset' : not supported for this version or the enabled extensions
WARNING: 0:89: 'layout' : useless application of layout qualifier
ERROR: 0:91: 'bar' : redefinition
-ERROR: 0:92: 'offset' : there is no such layout identifier for this stage taking an assigned value
+ERROR: 0:92: 'uniform buffer-member offset' : not supported for this version or the enabled extensions
ERROR: 0:92: 'bar' : redefinition
-ERROR: 0:94: 'offset' : there is no such layout identifier for this stage taking an assigned value
+ERROR: 0:94: 'uniform buffer-member offset' : not supported for this version or the enabled extensions
ERROR: 0:94: 'a2' : redefinition
ERROR: 0:95: 'binding' : requires block, or sampler/image, or atomic-counter type
ERROR: 0:96: 'binding' : requires block, or sampler/image, or atomic-counter type
@@ -291,7 +291,7 @@ ERROR: node is still EOpNull!
0:? '__anon__3' (layout(row_major std140 ) uniform block{layout(row_major std140 ) uniform 4X4 matrix of float M1, layout(column_major std140 ) uniform 4X4 matrix of float M2, layout(row_major std140 ) uniform 3X3 matrix of float N1})
0:? '__anon__4' (layout(column_major shared ) uniform block{layout(column_major shared ) uniform 4X4 matrix of float M13, layout(row_major shared ) uniform 4X4 matrix of float m14, layout(column_major shared ) uniform 3X3 matrix of float N12})
0:? 's17' (layout(binding=3 ) uniform sampler2D)
-0:? 'a2' (layout(binding=2 ) uniform int)
+0:? 'a2' (layout(binding=2 offset=4 ) uniform int)
0:? 'bar' (layout(binding=2 ) uniform int)
0:? 'b2' (layout(binding=2 ) uniform int)
0:? 'c2' (layout(binding=3 ) uniform int)
diff --git a/Test/testlist b/Test/testlist
index 06f8b57f..6e686f3f 100644
--- a/Test/testlist
+++ b/Test/testlist
@@ -59,6 +59,8 @@ numeral.frag
410.geom
430.vert
430.comp
+440.vert
+440.frag
dce.frag
../../LunarGLASS/test/aggOps.frag
../../LunarGLASS/test/always-discard.frag
diff --git a/Todo.txt b/Todo.txt
index 35e8a7eb..83c1a8c3 100644
--- a/Todo.txt
+++ b/Todo.txt
@@ -209,43 +209,39 @@ Shader Functionality to Implement/Finish
- Arrays of arrays are now supported, as per the GL_ARB_arrays_of_arrays extension.
- Compute shaders are now supported, as per the GL_ARB_compute_shader extension.
- Added imageSize() built-ins to query the dimensions of an image.
- - Define robust out-of-bounds access behavior when enabled, as per the GL_ARB_robust_buffer_access_behavior extension.
- All choice of depth or stencil texturing, for a packed depth-stencil texture, as per the
GL_ARB_stencil_texturing extension.
- Allow explicit locations/indexes to be assigned to uniform variables and subroutines, as per the
GL_ARB_explicit_uniform_location extension.
- - Accept ES GLSL shader #version statements, which will request ES functionality for ES GLSL
+ + Accept ES GLSL shader #version statements, which will request ES functionality for ES GLSL
versions 100 and 300, as per the GL_ARB_ES3_compatibility extension.
- - Clarify and correct scoping rules to what would normally be expected and what was intended.
+ + Clarify and correct scoping rules to what would normally be expected and what was intended.
(Function parameters and body nest inside global space. Loop variables and body nest inside
loop scope.)
- - There are no digraphs (trigraphs were already disallowed).
- - Remove the CPP difference that it is a compile-time error to use #if or #elif on expressions
+ + There are no digraphs (trigraphs were already disallowed).
+ + Remove the CPP difference that it is a compile-time error to use #if or #elif on expressions
containing undefined macro names. This reverts back to following expected CPP behavior.
- - Set both gl_MaxFragmentImageUniformsand gl_MaxCombinedImageUniforms to 8.
+ + Set both gl_MaxFragmentImageUniforms and gl_MaxCombinedImageUniforms to 8.
- Clarify textureSize() for cube map arrays.
- For layout qualifiers,
- - make negative output locations a compile-time error, once integer expressions are allowed in layouts
+ + make negative output locations a compile-time error, once integer expressions are allowed in layouts
- make indexes outside the range [0,1] a compile-time error.
- Add textureQueryLevels() built-ins to query the number of mipmap levels, as per the
GL_ARB_texture_query_levels extension.
+ Make gl_Layer and gl_ViewportIndex also be inputs to the fragment shader, as per the
GL_ARB_fragment_layer_viewport extension.
- - Add more examples and rules to be more specific about the required behavior of the precise
- qualifier.
- Clarify fragment output variables cannot be double precision.
- - Allow the new shared keyword to be in layout-qualifier-id, allowing backward compatibility
+ + Allow the new shared keyword to be in layout-qualifier-id, allowing backward compatibility
with the shared identifier that was previously used.
+ Added overlooked texture function float textureOffset (sampler2DArrayShadow sampler, vec4 P, vec2 offset [, float bias] ).
+ Add missing type in grammar, ATOMIC_UINT, and missing qualifiers COHERENT, VOLATILE, RESTRICT, READONLY, and WRITEONLY.
- - do version checking for the above
+ Add missing initializer lists to grammar.
GLSL 4.4
- Incorporate the ARB_enhanced_layouts extension, which adds
- - compile-time constant expressions for layout qualifier integers
+ + compile-time constant expressions for layout qualifier integers
- new offset and align layout qualifiers for control over buffer block layouts
- - add location layout qualifier for input and output blocks and block members
- - new componentlayout qualifier for finer-grained layout control of input and output variables and blocks
+ + add location layout qualifier for input and output blocks and block members
+ + new component layout qualifier for finer-grained layout control of input and output variables and blocks
- new xfb_buffer, xfb_stride, and xfb_offsetlayout qualifiers to allow the shader to control
transform feedback buffering.
+ Bug 10530: To be consistent with ES, include sample types as valid in a precision statement.
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 67ebfd58..84241262 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -353,29 +353,55 @@ public:
{
layoutMatrix = ElmNone;
layoutPacking = ElpNone;
+ layoutOffset = -1;
+ layoutAlign = -1;
+
layoutLocation = layoutLocationEnd;
+ layoutComponent = layoutComponentEnd;
layoutBinding = layoutBindingEnd;
layoutStream = layoutStreamEnd;
+
+ layoutXfbBuffer = layoutXfbBufferEnd;
+ layoutXfbStride = layoutXfbStrideEnd;
+ layoutXfbOffset = layoutXfbOffsetEnd;
}
bool hasLayout() const
{
- return layoutMatrix != ElmNone ||
- layoutPacking != ElpNone ||
+ return hasUniformLayout() ||
hasLocation() ||
hasBinding() ||
- hasStream();
+ hasStream() ||
+ hasXfb();
+ }
+ TLayoutMatrix layoutMatrix : 3;
+ TLayoutPacking layoutPacking : 4;
+ int layoutOffset;
+ int layoutAlign;
+ unsigned int layoutLocation : 7;
+ static const unsigned int layoutLocationEnd = 0x3F;
+ unsigned int layoutComponent : 3;
+ static const unsigned int layoutComponentEnd = 4;
+ unsigned int layoutBinding : 8;
+ static const unsigned int layoutBindingEnd = 0xFF;
+ unsigned int layoutStream : 8;
+ static const unsigned int layoutStreamEnd = 0xFF;
+ unsigned int layoutXfbBuffer : 4;
+ static const unsigned int layoutXfbBufferEnd = 0xF;
+ unsigned int layoutXfbStride : 8;
+ static const unsigned int layoutXfbStrideEnd = 0xFF;
+ unsigned int layoutXfbOffset : 8;
+ static const unsigned int layoutXfbOffsetEnd = 0xFF;
+ bool hasUniformLayout() const
+ {
+ return layoutMatrix != ElmNone ||
+ layoutPacking != ElpNone ||
+ layoutOffset != -1 ||
+ layoutAlign != -1;
}
- TLayoutMatrix layoutMatrix : 3;
- TLayoutPacking layoutPacking : 4;
- unsigned int layoutLocation : 7; // ins/outs should have small numbers, buffer offsets could be large
- static const unsigned int layoutLocationEnd = 0x3F;
- unsigned int layoutBinding : 8;
- static const unsigned int layoutBindingEnd = 0xFF;
- unsigned int layoutStream : 8;
- static const unsigned int layoutStreamEnd = 0xFF;
bool hasLocation() const
{
- return layoutLocation != layoutLocationEnd;
+ return layoutLocation != layoutLocationEnd ||
+ layoutComponent != layoutComponentEnd;
}
bool hasBinding() const
{
@@ -385,6 +411,12 @@ public:
{
return layoutStream != layoutStreamEnd;
}
+ bool hasXfb() const
+ {
+ return layoutXfbBuffer != layoutXfbBufferEnd ||
+ layoutXfbStride != layoutXfbStrideEnd ||
+ layoutXfbOffset != layoutXfbOffsetEnd;
+ }
static const char* getLayoutPackingString(TLayoutPacking packing)
{
switch (packing) {
@@ -824,8 +856,11 @@ public:
if (qualifier.hasLayout()) {
p += snprintf(p, end - p, "layout(");
- if (qualifier.hasLocation())
+ if (qualifier.hasLocation()) {
p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
+ if (qualifier.layoutComponent != qualifier.layoutComponentEnd)
+ p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
+ }
if (qualifier.hasBinding())
p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding);
if (qualifier.hasStream())
@@ -834,6 +869,17 @@ public:
p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
if (qualifier.layoutPacking != ElpNone)
p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking));
+ if (qualifier.layoutOffset != -1)
+ p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
+ if (qualifier.layoutAlign != -1)
+ p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
+
+ if (qualifier.layoutXfbBuffer != qualifier.layoutXfbBufferEnd)
+ p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
+ if (qualifier.layoutXfbOffset != qualifier.layoutXfbOffsetEnd)
+ p += snprintf(p, end - p, "xfb_offset=%d ", qualifier.layoutXfbOffset);
+ if (qualifier.layoutXfbStride != qualifier.layoutXfbStrideEnd)
+ p += snprintf(p, end - p, "xfb_stride=%d ", qualifier.layoutXfbStride);
p += snprintf(p, end - p, ") ");
}
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index 90a7e271..828d5769 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -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 "24674"
-#define GLSLANG_DATE "2014/01/07 10:44:41"
+#define GLSLANG_REVISION "24675"
+#define GLSLANG_DATE "2014/01/07 11:14:48"
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 12cfb59f..632a17f1 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -101,6 +101,8 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb,
globalBufferDefaults.layoutMatrix = ElmColumnMajor;
globalBufferDefaults.layoutPacking = ElpShared;
+ // TODO: 4.4 enhanced layouts: defaults for xfb?
+
globalInputDefaults.clear();
globalOutputDefaults.clear();
@@ -2429,7 +2431,7 @@ void TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& newTypeList
symbolTable.insert(*block);
// Check for general layout qualifier errors
- layoutTypeCheck(loc, *block);
+ layoutObjectCheck(loc, *block);
// Tracking for implicit sizing of array
if (isIoResizeArray(block->getType())) {
@@ -2829,7 +2831,20 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
}
std::transform(id.begin(), id.end(), id.begin(), ::tolower);
- if (id == "location") {
+
+ if (id == "offset") {
+ const char* feature = "uniform buffer-member offset";
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, feature);
+ publicType.qualifier.layoutOffset = value;
+ return;
+ } else if (id == "align") {
+ const char* feature = "uniform buffer-member align";
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, feature);
+ publicType.qualifier.layoutAlign = value;
+ return;
+ } else if (id == "location") {
requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "location");
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 330, 0, "location");
if ((unsigned int)value >= TQualifier::layoutLocationEnd)
@@ -2837,8 +2852,7 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
else
publicType.qualifier.layoutLocation = value;
return;
- }
- if (id == "binding") {
+ } else if (id == "binding") {
requireProfile(loc, ECoreProfile | ECompatibilityProfile, "binding");
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shading_language_420pack, "binding");
if ((unsigned int)value >= TQualifier::layoutBindingEnd)
@@ -2846,7 +2860,37 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
else
publicType.qualifier.layoutBinding = value;
return;
+ } else if (id == "component") {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, "component");
+ if ((unsigned)value >= TQualifier::layoutComponentEnd)
+ error(loc, "component is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutComponent = value;
+ return;
+ } else if (id.compare(0, 4, "xfb_") == 0) {
+ const char* feature = "transform feedback qualifier";
+ requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature);
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, feature);
+ if (id == "xfb_buffer") {
+ if (value >= TQualifier::layoutXfbBufferEnd) // TODO: 4.4 enhanced layouts: also check against gl_MaxTransformFeedbackBuffers
+ error(loc, "buffer is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutXfbBuffer = value;
+ } else if (id == "xfb_offset") {
+ if (value >= TQualifier::layoutXfbOffsetEnd) // TODO: 4.4 enhanced layouts: also check against gl_MaxTransformFeedbackInterleavedComponents
+ error(loc, "offset is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutXfbOffset = value;
+ } else if (id == "xfb_stride") {
+ if (value >= TQualifier::layoutXfbStrideEnd) // TODO: 4.4 enhanced layouts: also check against gl_MaxTransformFeedbackInterleavedComponents
+ error(loc, "stride is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutXfbStride = value;
+ }
}
+
switch (language) {
case EShLangVertex:
break;
@@ -2900,51 +2944,122 @@ void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst,
if (src.layoutPacking != ElpNone)
dst.layoutPacking = src.layoutPacking;
+ if (src.hasStream())
+ dst.layoutStream = src.layoutStream;
+
+ if (src.layoutXfbBuffer != TQualifier::layoutXfbBufferEnd)
+ dst.layoutXfbBuffer = src.layoutXfbBuffer;
+
if (! inheritOnly) {
- if (src.hasLocation())
+ if (src.layoutLocation != TQualifier::layoutLocationEnd)
dst.layoutLocation = src.layoutLocation;
- if (src.hasBinding())
+ if (src.layoutComponent != TQualifier::layoutComponentEnd)
+ dst.layoutComponent = src.layoutComponent;
+
+ if (src.layoutOffset != -1)
+ dst.layoutOffset = src.layoutOffset;
+ if (src.layoutAlign != -1)
+ dst.layoutAlign = src.layoutAlign;
+
+ if (src.layoutBinding != TQualifier::layoutBindingEnd)
dst.layoutBinding = src.layoutBinding;
- }
- if (src.hasStream())
- dst.layoutStream = src.layoutStream;
+ if (src.layoutXfbStride != TQualifier::layoutXfbStrideEnd)
+ dst.layoutXfbStride = src.layoutXfbStride;
+ if (src.layoutXfbOffset != TQualifier::layoutXfbOffsetEnd)
+ dst.layoutXfbOffset = src.layoutXfbOffset;
+ }
}
// Do error layout error checking given a full variable/block declaration.
-void TParseContext::layoutTypeCheck(TSourceLoc loc, const TSymbol& symbol)
+void TParseContext::layoutObjectCheck(TSourceLoc loc, const TSymbol& symbol)
{
const TType& type = symbol.getType();
const TQualifier& qualifier = type.getQualifier();
- // first, qualifier only error checking
+ // first, cross check WRT to just the type
+ layoutTypeCheck(loc, type);
+
+ // now, any remaining error checking based on the object itself
+
+ if (qualifier.hasLocation()) {
+ switch (qualifier.storage) {
+ case EvqUniform:
+ case EvqBuffer:
+ if (symbol.getAsVariable() == 0)
+ error(loc, "can only be used on variable declaration", "location", "");
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check packing and matrix
+ // TODO: 4.4 enhanced layouts: generalize to include offset/align
+ if (qualifier.layoutMatrix || qualifier.layoutPacking) {
+ switch (qualifier.storage) {
+ case EvqBuffer:
+ case EvqUniform:
+ if (type.getBasicType() != EbtBlock) {
+ if (qualifier.layoutMatrix != ElmNone)
+ error(loc, "cannot specify matrix layout on a variable declaration", "layout", "");
+ if (qualifier.layoutPacking != ElpNone)
+ error(loc, "cannot specify packing on a variable declaration", "layout", "");
+ }
+ break;
+ default:
+ if (type.getBasicType() != EbtBlock && symbol.getAsVariable()) {
+ if (qualifier.layoutMatrix != ElmNone ||
+ qualifier.layoutPacking != ElpNone)
+ error(loc, "qualifiers for matrix layout and block packing only apply to uniform or buffer blocks", "layout", "");
+ }
+ }
+ }
+}
+
+// Do error layout error checking with respect to a type.
+void TParseContext::layoutTypeCheck(TSourceLoc loc, const TType& type)
+{
+ const TQualifier& qualifier = type.getQualifier();
+
+ // first, intra layout qualifier-only error checking
layoutQualifierCheck(loc, qualifier);
// now, error checking combining type and qualifier
if (qualifier.hasLocation()) {
+ if (qualifier.layoutComponent != TQualifier::layoutComponentEnd) {
+ // "It is a compile-time error if this sequence of components gets larger than 3."
+ if (qualifier.layoutComponent + type.getVectorSize() > 4)
+ error(loc, "type overflows the available 4 components", "component", "");
+
+ // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these."
+ if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct)
+ error(loc, "cannot apply to a matrix, structure, or block", "component", "");
+ }
+
switch (qualifier.storage) {
case EvqVaryingIn:
case EvqVaryingOut:
if (type.getBasicType() == EbtBlock)
- profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, 0 /* TODO ARB_enhanced_layouts*/, "location qualifier on in/out block");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, "location qualifier on in/out block");
break;
case EvqUniform:
case EvqBuffer:
- {
- const char* feature = "location qualifier on uniform or buffer";
- if (symbol.getAsVariable() == 0)
- error(loc, "can only be used on variable declaration", feature, "");
break;
- }
default:
- error(loc, "location qualifiers only appy to uniform, buffer, in, or out storage qualifiers", symbol.getName().c_str(), "");
+ error(loc, "can only appy to uniform, buffer, in, or out storage qualifiers", "location", "");
break;
}
- int repeated = intermediate.addUsedLocation(qualifier, type);
- if (repeated >= 0)
- error(loc, "repeated use of location", "location", "%d", repeated);
+ bool typeCollision;
+ int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision);
+ if (repeated >= 0 && ! typeCollision)
+ error(loc, "overlapping use of location", "location", "%d", repeated);
+ // "fragment-shader outputs ... if two variables are placed within the same
+ // location, they must have the same underlying type (floating-point or integer)"
+ if (typeCollision && language == EShLangFragment && qualifier.isPipeOutput())
+ error(loc, "fragment outputs sharing the same location must be the same basic type", "location", "%d", repeated);
}
if (qualifier.hasBinding()) {
@@ -2967,34 +3082,22 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TSymbol& symbol)
error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
}
}
-
- // Check packing and matrix
- if (qualifier.layoutMatrix || qualifier.layoutPacking) {
- switch (qualifier.storage) {
- case EvqBuffer:
- case EvqUniform:
- if (symbol.getType().getBasicType() != EbtBlock) {
- if (qualifier.layoutMatrix != ElmNone)
- error(loc, "cannot specify matrix layout on a variable declaration", symbol.getName().c_str(), "");
- if (qualifier.layoutPacking != ElpNone)
- error(loc, "cannot specify packing on a variable declaration", symbol.getName().c_str(), "");
- }
- break;
- default:
- if (symbol.getType().getBasicType() != EbtBlock && symbol.getAsVariable()) {
- if (qualifier.layoutMatrix != ElmNone ||
- qualifier.layoutPacking != ElpNone)
- error(loc, "layout qualifiers for matrix layout and packing only apply to uniform or buffer blocks", symbol.getName().c_str(), "");
- }
- }
- }
}
// Do layout error checking that can be done within a qualifier proper, not needing to know
// if there are blocks, atomic counters, variables, etc.
void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& qualifier)
{
+ // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
+ if (qualifier.layoutComponent != TQualifier::layoutComponentEnd && qualifier.layoutLocation == TQualifier::layoutLocationEnd)
+ error(loc, "must specify 'location' to use 'component'", "component", "");
+
if (qualifier.hasLocation()) {
+
+ // "As with input layout qualifiers, all shaders except compute shaders
+ // allow *location* layout qualifiers on output variable declarations,
+ // output block declarations, and output block member declarations."
+
switch (qualifier.storage) {
case EvqVaryingIn:
{
@@ -3257,7 +3360,7 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
}
// look for errors/adjustments in layout qualifier use
- layoutTypeCheck(loc, *symbol);
+ layoutObjectCheck(loc, *symbol);
// see if it's a linker-level object to track
if (newDeclaration && symbolTable.atGlobalLevel())
@@ -3710,7 +3813,10 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
}
// fix and check for member layout qualifiers
+ // TODO: 4.4 enhanced layouts: generalize to include offset/align
mergeObjectLayoutQualifiers(loc, defaultQualification, currentBlockQualifier, true);
+ bool memberWithLocation = false;
+ bool memberWithoutLocation = false;
for (unsigned int member = 0; member < typeList.size(); ++member) {
TQualifier& memberQualifier = typeList[member].type->getQualifier();
TSourceLoc memberLoc = typeList[member].loc;
@@ -3720,10 +3826,28 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
}
if (memberQualifier.layoutPacking != ElpNone)
error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), "");
+ if (memberQualifier.hasLocation()) {
+ const char* feature = "location on block member";
+ switch (currentBlockQualifier.storage) {
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, feature);
+ memberWithLocation = true;
+ break;
+ default:
+ error(memberLoc, "can only use in an in/out block", feature, "");
+ break;
+ }
+ } else
+ memberWithoutLocation = true;
TQualifier newMemberQualification = defaultQualification;
mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false);
memberQualifier = newMemberQualification;
}
+ fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
+ for (unsigned int member = 0; member < typeList.size(); ++member)
+ layoutTypeCheck(typeList[member].loc, *typeList[member].type);
// reverse merge, so that currentBlockQualifier now has all layout information
// (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers)
@@ -3783,7 +3907,7 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
}
// Check for general layout qualifier errors
- layoutTypeCheck(loc, variable);
+ layoutObjectCheck(loc, variable);
if (isIoResizeArray(blockType)) {
ioArraySymbolResizeList.push_back(&variable);
@@ -3795,6 +3919,46 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
intermediate.addSymbolLinkageNode(linkage, variable);
}
+//
+// "For a block, this process applies to the entire block, or until the first member
+// is reached that has a location layout qualifier. When a block member is declared with a location
+// qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level
+// declaration. Subsequent members are again assigned consecutive locations, based on the newest location,
+// until the next member declared with a location qualifier. The values used for locations do not have to be
+// declared in increasing order."
+void TParseContext::fixBlockLocations(TSourceLoc loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation)
+{
+ // "If a block has no block-level location layout qualifier, it is required that either all or none of its members
+ // have a location layout qualifier, or a compile-time error results."
+ if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation)
+ error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", "");
+ else {
+ if (memberWithLocation) {
+ // remove any block-level location and make it per *every* member
+ int nextLocation; // by the rule above, initial value is not relevant
+ if (qualifier.hasLocation()) {
+ nextLocation = qualifier.layoutLocation;
+ qualifier.layoutLocation = TQualifier::layoutLocationEnd;
+ if (qualifier.layoutComponent != TQualifier::layoutComponentEnd) {
+ // "It is a compile-time error to apply the *component* qualifier to a ... block"
+ error(loc, "cannot apply to a block", "component", "");
+ }
+ }
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ TSourceLoc memberLoc = typeList[member].loc;
+ if (! memberQualifier.hasLocation()) {
+ if (nextLocation >= TQualifier::layoutLocationEnd)
+ error(memberLoc, "location is too large", "location", "");
+ memberQualifier.layoutLocation = nextLocation;
+ memberQualifier.layoutComponent = 0;
+ }
+ nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(*typeList[member].type);
+ }
+ }
+ }
+}
+
// For an identifier that is already declared, add more qualification to it.
void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, const TString& identifier)
{
@@ -3941,6 +4105,7 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
layoutQualifierCheck(loc, qualifier);
+ // TODO: 4.4 enhanced layouts: generalize to include all new ones
switch (qualifier.storage) {
case EvqUniform:
if (qualifier.layoutMatrix != ElmNone)
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index a2dcc605..7a7763ed 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -150,7 +150,8 @@ public:
void setLayoutQualifier(TSourceLoc, TPublicType&, TString&);
void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, const TIntermTyped*);
void mergeObjectLayoutQualifiers(TSourceLoc, TQualifier& dest, const TQualifier& src, bool inheritOnly);
- void layoutTypeCheck(TSourceLoc, const TSymbol&);
+ void layoutObjectCheck(TSourceLoc, const TSymbol&);
+ void layoutTypeCheck(TSourceLoc, const TType&);
void layoutQualifierCheck(TSourceLoc, const TQualifier&);
void checkNoShaderLayouts(TSourceLoc, const TShaderQualifiers&);
@@ -163,6 +164,7 @@ public:
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
void declareBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
+ void fixBlockLocations(TSourceLoc, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void addQualifierToExisting(TSourceLoc, TQualifier, const TString& identifier);
void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&);
void invariantCheck(TSourceLoc, const TType&, const TString& identifier);
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index e62f84f3..0b9b50b3 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -252,7 +252,8 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
writeTypeComparison = true;
}
- // Layouts...
+ // Layouts...
+ // TODO: 4.4 enhanced layouts: generalize to include offset/align
if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix ||
symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking ||
symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation ||
@@ -481,8 +482,14 @@ bool TIntermediate::userOutputUsed() const
// as the accumulation is done.
//
// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
-int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type)
+//
+// typeCollision is set to true if there is no direct collision, but the types in the same location
+// are different.
+//
+int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type, bool& typeCollision)
{
+ typeCollision = false;
+
int set;
if (qualifier.isPipeInput())
set = 0;
@@ -510,20 +517,34 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
size = computeTypeLocationSize(type);
}
- TRange range = { qualifier.layoutLocation, qualifier.layoutLocation + size - 1 };
+ TRange locationRange = { qualifier.layoutLocation, qualifier.layoutLocation + size - 1 };
+ TRange componentRange = { 0, 3 };
+ if (qualifier.layoutComponent != TQualifier::layoutComponentEnd) {
+ componentRange.start = qualifier.layoutComponent;
+ componentRange.last = componentRange.start + type.getVectorSize() - 1;
+ }
// check for collisions, except for vertex inputs on desktop
if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput())) {
- for (size_t r = 0; r < usedLocations[set].size(); ++r) {
- if (range.last >= usedLocations[set][r].start &&
- range.start <= usedLocations[set][r].last) {
+ for (size_t r = 0; r < usedIo[set].size(); ++r) {
+ if (locationRange.last >= usedIo[set][r].location.start &&
+ locationRange.start <= usedIo[set][r].location.last &&
+ componentRange.last >= usedIo[set][r].component.start &&
+ componentRange.start <= usedIo[set][r].component.last) {
// there is a collision; pick one
- return std::max(range.start, usedLocations[set][r].start);
+ return std::max(locationRange.start, usedIo[set][r].location.start);
+ } else if (locationRange.last >= usedIo[set][r].location.start &&
+ locationRange.start <= usedIo[set][r].location.last &&
+ type.getBasicType() != usedIo[set][r].basicType) {
+ typeCollision = true;
+ return std::max(locationRange.start, usedIo[set][r].location.start);
}
}
}
- usedLocations[set].push_back(range);
+ TIoRange range = { locationRange, componentRange, type.getBasicType() };
+
+ usedIo[set].push_back(range);
return -1;
}
@@ -546,7 +567,6 @@ int TIntermediate::computeTypeLocationSize(const TType& type)
// "The locations consumed by block and structure members are determined by applying the rules above
// recursively..."
if (type.isStruct()) {
- // TODO: 440 functionality: input/output block locations when members also have locations
int size = 0;
for (size_t member = 0; member < type.getStruct()->size(); ++member) {
TType memberType(type, member);
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index eb85dafa..2ffda5d6 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -172,7 +172,8 @@ public:
void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
- int addUsedLocation(const TQualifier&, const TType&);
+ int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
+ int computeTypeLocationSize(const TType&);
protected:
void error(TInfoSink& infoSink, const char*);
@@ -183,7 +184,6 @@ protected:
void inOutLocationCheck(TInfoSink&);
TIntermSequence& findLinkerObjects() const;
bool userOutputUsed() const;
- int computeTypeLocationSize(const TType&);
protected:
const EShLanguage language;
@@ -217,11 +217,19 @@ protected:
std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking
+ // A location range is a 2-D rectangle; the set of (location, component) pairs all lying
+ // both within the location range and the component range.
+ // The following are entirely encapsulated by addUsedLocation().
struct TRange {
int start;
int last;
};
- std::vector<TRange> usedLocations[3]; // sets of used locations, one for each of in, out, and uniform
+ struct TIoRange {
+ TRange location;
+ TRange component;
+ TBasicType basicType;
+ };
+ std::vector<TIoRange> usedIo[3]; // sets of used locations, one for each of in, out, and uniform
private:
void operator=(TIntermediate&); // prevent assignments