diff --git a/Test/330.frag b/Test/330.frag index b90ae54e36a3786f01251a4329a76c6e84fe455d..3fad83b829776486e1e88e734b65a1984952b0b3 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 0000000000000000000000000000000000000000..23c43b476ea2e604dd4fb70252a55bfac7db5425 --- /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 0000000000000000000000000000000000000000..3aeebaa8f8194db74afa1ded7625d25f7884a105 --- /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 59180a7069c4bb458badd9af868b078112721b0f..30fd4babc9fcf8cc9379c7084d29b72e46b6acf7 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 f6258e9efb7d429fe602cc0257598429b83dc937..30646f91bc51eec53cec8a6faec42c8a1f873673 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 ac6656968efb7f2676b8739c92f365c8a83f1d6d..0c952e44cb41db654dc562aaf8c31b05ff870357 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 a34e63f1724ab3964f853eb5ea429571baff5a77..4ce58fa083cd3321c3d682aa785ea2f6edba297b 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 0ada0598c21204dddac71feeea88e9fd52b5bf6e..f8e9f2b4c188150a4a9efc9e806647ac27fdfa13 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 d2e69a8be1b8dfa15cec5b4b8c55677283759403..163ebfd3fe19ffe69961a67e4f8c74842c30aa4a 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 f407711ce2365daf000359dd8a9fe063838c395e..9176bfa27fe8c8802616a01fe9a921594af2e9fe 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 0000000000000000000000000000000000000000..771715ff25b3ae4934b9e816d430f35345762627 --- /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 0000000000000000000000000000000000000000..ed94e0518d2e62ba2c16d9422a6a49b9c094c17f --- /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 cc136af96044d2a0832a4f825ea34eb3ff52c390..9c0c1c526d1e795365491d715b84201c6de17411 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 1d3416d39b46c7387d72c84de74eb3421726167b..c9ce1621493b2d83b3b8a6157277d8a516cd6a3b 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 06f8b57fdcfac6f69ebb904d000f9c4b652337f0..6e686f3f1e7c41db3898d14f40fe47ed670c16a5 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 35e8a7eb2589d582b49eec00c8e46b3a10f0ad62..83c1a8c349ad5146a2cea02cdb6993c74e557a59 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 67ebfd58d145eb5bb71335ea59e9f167ece94ae3..84241262186dc2f3fc65dc0afc93d5b063450850 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 90a7e2716079047fe6a31a5884e4a5d678514ef2..828d5769bfe58bc4e7701a43d351363cda27fd52 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 12cfb59f41fd5549856abd251048cb03084c9bbc..632a17f132bab59b49ac90ba9cbbd770c5d94a1d 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 a2dcc605efe889756cc490fbadefbf45261d4b9c..7a7763ed9e86a7ae1ea277f095cbe90e6c55237e 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 e62f84f33c35ab05466b7acc3b0c6caed55b96b5..0b9b50b3d452bf9b39756ba4fc459dad4902d302 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 eb85dafa22b516cc848c546ff3028e980400396f..2ffda5d674c5d265d44011494eed18da25269ad9 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