diff --git a/Test/150.geom b/Test/150.geom index 3d8098237..c09b4ce6d 100644 --- a/Test/150.geom +++ b/Test/150.geom @@ -36,3 +36,57 @@ void main() gl_PrimitiveID = gl_PrimitiveIDIn; gl_Layer = 2; } + +out vec4 ov0; // stream should be 0 +layout(stream = 4) out vec4 ov4; +out vec4 o1v0; // stream should be 0 + +layout(stream = 3) uniform; // ERROR +layout(stream = 3) in; // ERROR +layout(stream = 3) uniform int ua; // ERROR +layout(stream = 3) uniform ubb { int ua; } ibb; // ERROR + +layout(line_strip, points, triangle_strip, stream = 3, points, triangle_strip) out; // just means "stream = 3, triangle_strip" +layout(stream = 3, triangle_strip) out; +out vec4 ov3; // stream should be 3 + +layout(stream = 6) out ooutb { vec4 a; } ouuaa6; + +layout(stream = 6) out ooutb { + layout(stream = 6) vec4 a; +} ouua6; + +layout(stream = 7) out ooutb { + layout(stream = 6) vec4 a; // ERROR +} ouua7; + +out vec4 ov2s3; // stream should be 3 + +void foo(layout(max_vertices = 4) int a) // ERROR +{ + ouuaa6.a = vec4(1.0); +} + +layout(line_strip, points, triangle_strip, stream = 3, points) out; // ERROR, changing output primitive +layout(line_strip, points, stream = 3) out; // ERROR, changing output primitive +layout(triangle_strip) in; // ERROR, not an input primitive +layout(triangle_strip) uniform; // ERROR +layout(triangle_strip) out vec4 badv4; // ERROR, not on a variable +layout(triangle_strip) in vec4 bad2v4; // ERROR, not on a variable or input +layout(invocations = 3) out outbn { int a; }; // ERROR, not on a block +out outbn { + layout(invocations = 3) int a; // ERROR, not on a block member + layout(max_vertices = 3) int b; // ERROR, not on a block member + layout(triangle_strip) int c; // ERROR, not on a block member +} outbi; + +layout(lines) out; // ERROR, not on output +layout(lines_adjancency) in; +layout(triangles) in; // ERROR, can't change it +layout(triangles_adjacency) in; // ERROR, can't change it + +layout(invocations = 4, max_vertices = 127) out; + +in inbn { + layout(stream = 2) int a; // ERROR, stream on input +} inbi; diff --git a/Test/400.geom b/Test/400.geom index cf93da3da..84461be9e 100644 --- a/Test/400.geom +++ b/Test/400.geom @@ -9,3 +9,6 @@ void main() int id = gl_InvocationID; } + +layout(invocations = 3) out outbn { int a; }; // ERROR, not on a block +layout(max_vertices = 127, invocations = 4) out; diff --git a/Test/baseResults/100.frag.out b/Test/baseResults/100.frag.out index 9c30310b9..ffa4adfc6 100644 --- a/Test/baseResults/100.frag.out +++ b/Test/baseResults/100.frag.out @@ -101,6 +101,6 @@ ERROR: node is still EOpNull! 0:? 'uint' (mediump int) 0:? 'v' (smooth in 3-element array of mediump 4-component vector of float) 0:? 'f' (mediump float) -0:? '__anon__0' (layout(shared ) uniform block) +0:? '__anon__0' (layout(column_major shared ) uniform block) 0:? 'fa' (unsized array of mediump float) diff --git a/Test/baseResults/150.geom.out b/Test/baseResults/150.geom.out index 64b78b84f..c17460f2a 100644 --- a/Test/baseResults/150.geom.out +++ b/Test/baseResults/150.geom.out @@ -4,8 +4,35 @@ ERROR: 0:19: 'fromVertex' : redefinition ERROR: 0:21: 'fooC' : block instance name redefinition ERROR: 0:29: 'EmitStreamVertex' : no matching overloaded function found ERROR: 0:30: 'EndStreamPrimitive' : no matching overloaded function found -ERROR: 5 compilation errors. No code generated. +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: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 +ERROR: 0:71: 'points' : cannot change previously set output primitive +ERROR: 0:72: 'triangle_strip' : does not apply to input +ERROR: 0:73: 'triangle_strip' : cannot be used here +ERROR: 0:74: 'triangle_strip' : can only apply to a standalone qualifier +ERROR: 0:75: 'triangle_strip' : can only apply to a standalone qualifier +ERROR: 0:76: 'invocations' : not supported for this version or the enabled extensions +ERROR: 0:76: 'invocations' : can only apply to a standalone qualifier +ERROR: 0:78: 'invocations' : not supported for this version or the enabled extensions +ERROR: 0:78: 'invocations' : can only apply to a standalone qualifier +ERROR: 0:79: 'max_vertices' : can only apply to a standalone qualifier +ERROR: 0:80: 'triangle_strip' : can only apply to a standalone qualifier +ERROR: 0:83: 'lines' : does not only apply to output +ERROR: 0:85: 'triangles' : cannot change previously set input primitive +ERROR: 0:86: 'triangles_adjacency' : cannot change previously set input primitive +ERROR: 0:88: 'invocations' : not supported for this version or the enabled extensions +ERROR: 0:91: 'stream' : member cannot contradict block +ERROR: 28 compilation errors. No code generated. +invocations = 4 +max_vertices = 127 +input primitive = lines_adjancency +output primitive = triangle_strip ERROR: node is still EOpNull! 0:25 Function Definition: main( (void) 0:25 Function Parameters: @@ -17,8 +44,8 @@ ERROR: node is still EOpNull! 0:30 Constant: 0:30 0.000000 0:32 move second child to first child (3-component vector of float) -0:32 color: direct index for structure (3-component vector of float) -0:32 '__anon__0' (out block) +0:32 color: direct index for structure (layout(stream=0 ) 3-component vector of float) +0:32 '__anon__0' (layout(stream=0 ) out block) 0:32 Constant: 0:32 0 (const uint) 0:32 color: direct index for structure (3-component vector of float) @@ -26,9 +53,9 @@ ERROR: node is still EOpNull! 0:32 Constant: 0:32 0 (const int) 0:33 move second child to first child (float) -0:33 direct index (float) -0:33 gl_ClipDistance: direct index for structure (unsized array of float) -0:33 '__anon__1' (out block) +0:33 direct index (layout(stream=0 ) float) +0:33 gl_ClipDistance: direct index for structure (layout(stream=0 ) unsized array of float) +0:33 '__anon__1' (layout(stream=0 ) out block) 0:33 Constant: 0:33 2 (const uint) 0:33 Constant: @@ -44,8 +71,8 @@ ERROR: node is still EOpNull! 0:33 Constant: 0:33 2 (const int) 0:34 move second child to first child (4-component vector of float) -0:34 gl_Position: direct index for structure (4-component vector of float) -0:34 '__anon__1' (out block) +0:34 gl_Position: direct index for structure (layout(stream=0 ) 4-component vector of float) +0:34 '__anon__1' (layout(stream=0 ) out block) 0:34 Constant: 0:34 0 (const uint) 0:34 gl_Position: direct index for structure (4-component vector of float) @@ -56,8 +83,8 @@ ERROR: node is still EOpNull! 0:34 Constant: 0:34 0 (const int) 0:35 move second child to first child (float) -0:35 gl_PointSize: direct index for structure (float) -0:35 '__anon__1' (out block) +0:35 gl_PointSize: direct index for structure (layout(stream=0 ) float) +0:35 '__anon__1' (layout(stream=0 ) out block) 0:35 Constant: 0:35 1 (const uint) 0:35 gl_PointSize: direct index for structure (float) @@ -68,14 +95,43 @@ ERROR: node is still EOpNull! 0:35 Constant: 0:35 1 (const int) 0:36 move second child to first child (int) -0:36 'gl_PrimitiveID' (out int) +0:36 'gl_PrimitiveID' (layout(stream=0 ) out int) 0:36 'gl_PrimitiveIDIn' (in int) 0:37 move second child to first child (int) -0:37 'gl_Layer' (out int) +0:37 'gl_Layer' (layout(stream=0 ) out int) 0:37 Constant: 0:37 2 (const int) +0:65 Function Definition: foo(i1; (void) +0:65 Function Parameters: +0:65 'a' (in int) +0:67 Sequence +0:67 move second child to first child (4-component vector of float) +0:67 a: direct index for structure (layout(stream=6 ) 4-component vector of float) +0:67 'ouuaa6' (layout(stream=6 ) out block) +0:67 Constant: +0:67 0 (const int) +0:67 Constant: +0:67 1.000000 +0:67 1.000000 +0:67 1.000000 +0:67 1.000000 0:? Linker Objects 0:? 'fromV' (in block) -0:? 'toF' (out block) -0:? '__anon__0' (out block) +0:? 'toF' (layout(stream=0 ) out block) +0:? '__anon__0' (layout(stream=0 ) out block) +0:? 'ov0' (layout(stream=0 ) out 4-component vector of float) +0:? 'ov4' (layout(stream=4 ) out 4-component vector of float) +0:? 'o1v0' (layout(stream=0 ) out 4-component vector of float) +0:? 'ua' (layout(stream=3 ) uniform int) +0:? 'ibb' (layout(stream=3 column_major shared ) uniform block) +0:? 'ov3' (layout(stream=3 ) out 4-component vector of float) +0:? 'ouuaa6' (layout(stream=6 ) out block) +0:? 'ouua6' (layout(stream=6 ) out block) +0:? 'ouua7' (layout(stream=7 ) out block) +0:? 'ov2s3' (layout(stream=3 ) out 4-component vector of float) +0:? 'badv4' (layout(stream=3 ) out 4-component vector of float) +0:? 'bad2v4' (in 4-component vector of float) +0:? '__anon__1' (layout(stream=3 ) out block) +0:? 'outbi' (layout(stream=3 ) out block) +0:? 'inbi' (in block) diff --git a/Test/baseResults/150.vert.out b/Test/baseResults/150.vert.out index 7460f7b96..760e60ea7 100644 --- a/Test/baseResults/150.vert.out +++ b/Test/baseResults/150.vert.out @@ -33,7 +33,7 @@ ERROR: node is still EOpNull! 0:? Linker Objects 0:? 'iv4' (in 4-component vector of float) 0:? 'ps' (uniform float) -0:? '__anon__1' (layout(shared ) uniform block) +0:? '__anon__1' (layout(column_major shared ) uniform block) 0:? 'gl_VertexID' (gl_VertexId int) 0:? 'gl_InstanceID' (gl_InstanceId int) diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out index 75f1a8740..19960f53e 100644 --- a/Test/baseResults/300.frag.out +++ b/Test/baseResults/300.frag.out @@ -239,5 +239,5 @@ ERROR: node is still EOpNull! 0:? 'sc' (out lowp 3-component vector of float) 0:? 'sf' (out lowp float) 0:? 'arrayedSampler' (uniform 5-element array of lowp sampler2D) -0:? 'multiInst' (layout(shared ) uniform 2-element array of block) +0:? 'multiInst' (layout(column_major shared ) uniform 2-element array of block) diff --git a/Test/baseResults/300.vert.out b/Test/baseResults/300.vert.out index aa5f8e393..eda546081 100644 --- a/Test/baseResults/300.vert.out +++ b/Test/baseResults/300.vert.out @@ -153,7 +153,7 @@ ERROR: node is still EOpNull! 0:? 's' (smooth out structure) 0:? 'badsize' (unsized array of highp float) 0:? 'badsize2' (unsized array of highp float) -0:? 'ubInst' (layout(shared ) uniform unsized array of block) +0:? 'ubInst' (layout(column_major shared ) uniform unsized array of block) 0:? 'okayA' (2-element array of highp float) 0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int) diff --git a/Test/baseResults/300block.frag.out b/Test/baseResults/300block.frag.out index 18dedaf32..cefa5e456 100644 --- a/Test/baseResults/300block.frag.out +++ b/Test/baseResults/300block.frag.out @@ -16,13 +16,13 @@ ERROR: node is still EOpNull! 0:44 Construct vec3 (3-component vector of float) 0:44 Convert int to float (float) 0:44 ni: direct index for structure (layout(column_major shared ) mediump int) -0:44 'inst' (layout(shared ) uniform block) +0:44 'inst' (layout(column_major shared ) uniform block) 0:44 Constant: 0:44 1 (const int) 0:44 Convert uint to float (float) 0:44 direct index (mediump uint) 0:44 bv: direct index for structure (layout(column_major shared ) mediump 4-component vector of uint) -0:44 '__anon__0' (layout(shared ) uniform block) +0:44 '__anon__0' (layout(column_major shared ) uniform block) 0:44 Constant: 0:44 0 (const uint) 0:44 Constant: @@ -30,16 +30,16 @@ ERROR: node is still EOpNull! 0:44 Convert uint to float (float) 0:44 direct index (mediump uint) 0:44 nbv: direct index for structure (layout(column_major shared ) mediump 4-component vector of uint) -0:44 direct index (layout(shared ) uniform block) -0:44 'insts' (layout(shared ) uniform 4-element array of block) +0:44 direct index (layout(column_major shared ) uniform block) +0:44 'insts' (layout(column_major shared ) uniform 4-element array of block) 0:44 Constant: 0:44 2 (const int) 0:44 Constant: 0:44 0 (const int) 0:44 Constant: 0:44 2 (const int) -0:45 indirect index (layout(shared ) uniform block) -0:45 'insts' (layout(shared ) uniform 4-element array of block) +0:45 indirect index (layout(column_major shared ) uniform block) +0:45 'insts' (layout(column_major shared ) uniform 4-element array of block) 0:45 direct index (mediump uint) 0:45 v: direct index for structure (mediump 4-component vector of uint) 0:45 's' (uniform structure) @@ -49,8 +49,8 @@ ERROR: node is still EOpNull! 0:45 0 (const int) 0:? Linker Objects 0:? 's' (uniform structure) -0:? '__anon__0' (layout(shared ) uniform block) -0:? 'inst' (layout(shared ) uniform block) -0:? 'insts' (layout(shared ) uniform 4-element array of block) -0:? '__anon__1' (layout(shared ) uniform block) +0:? '__anon__0' (layout(column_major shared ) uniform block) +0:? 'inst' (layout(column_major shared ) uniform block) +0:? 'insts' (layout(column_major shared ) uniform 4-element array of block) +0:? '__anon__1' (layout(column_major shared ) uniform block) diff --git a/Test/baseResults/300layout.vert.out b/Test/baseResults/300layout.vert.out index e8d6c5de5..631e69b6e 100644 --- a/Test/baseResults/300layout.vert.out +++ b/Test/baseResults/300layout.vert.out @@ -25,11 +25,11 @@ ERROR: node is still EOpNull! 0:43 add (highp 4X4 matrix of float) 0:43 add (highp 4X4 matrix of float) 0:43 M1: direct index for structure (layout(row_major std140 ) highp 4X4 matrix of float) -0:43 'tblock' (layout(std140 ) uniform block) +0:43 'tblock' (layout(row_major std140 ) uniform block) 0:43 Constant: 0:43 0 (const int) 0:43 M2: direct index for structure (layout(column_major std140 ) highp 4X4 matrix of float) -0:43 'tblock' (layout(std140 ) uniform block) +0:43 'tblock' (layout(row_major std140 ) uniform block) 0:43 Constant: 0:43 1 (const int) 0:43 M4: direct index for structure (layout(row_major shared ) highp 4X4 matrix of float) @@ -41,7 +41,7 @@ ERROR: node is still EOpNull! 0:43 Constant: 0:43 0 (const uint) 0:43 t2m: direct index for structure (layout(row_major shared ) highp 4X4 matrix of float) -0:43 '__anon__0' (layout(shared ) uniform block) +0:43 '__anon__0' (layout(row_major shared ) uniform block) 0:43 Constant: 0:43 1 (const uint) 0:44 move second child to first child (highp 3-component vector of float) @@ -49,7 +49,7 @@ ERROR: node is still EOpNull! 0:44 vector-times-matrix (highp 3-component vector of float) 0:44 'c' (layout(location=7 ) in highp 3-component vector of float) 0:44 N1: direct index for structure (layout(row_major std140 ) highp 3X3 matrix of float) -0:44 'tblock' (layout(std140 ) uniform block) +0:44 'tblock' (layout(row_major std140 ) uniform block) 0:44 Constant: 0:44 2 (const int) 0:? Linker Objects @@ -60,8 +60,8 @@ ERROR: node is still EOpNull! 0:? 'pos' (smooth out highp 4-component vector of float) 0:? 'color' (smooth out highp 3-component vector of float) 0:? 'badm4' (layout(column_major shared ) uniform highp 4X4 matrix of float) -0:? 'tblock' (layout(std140 ) uniform block) -0:? '__anon__0' (layout(shared ) uniform block) +0:? 'tblock' (layout(row_major std140 ) uniform block) +0:? '__anon__0' (layout(row_major shared ) uniform block) 0:? '__anon__2' (out block) 0:? 'badoutA' (layout(location=10 ) smooth out highp 4-component vector of float) 0:? 'compute_only' (shared highp 4-component vector of float) diff --git a/Test/baseResults/300operations.frag.out b/Test/baseResults/300operations.frag.out index b4807855b..b694cd9a9 100644 --- a/Test/baseResults/300operations.frag.out +++ b/Test/baseResults/300operations.frag.out @@ -1,5 +1,5 @@ ERROR: 0:11: 'float' : type requires declaration of default precision qualifier -ERROR: 0:30: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type 'layout(shared ) uniform block' and a right operand of type 'layout(shared ) uniform block' (or there is no acceptable conversion) +ERROR: 0:30: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type 'layout(column_major shared ) uniform block' and a right operand of type 'layout(column_major shared ) uniform block' (or there is no acceptable conversion) ERROR: 0:31: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type 'structure' and a right operand of type 'structure' (or there is no acceptable conversion) ERROR: 0:32: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type 'mediump int' and a right operand of type 'mediump float' (or there is no acceptable conversion) ERROR: 0:33: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type 'mediump uint' and a right operand of type 'mediump float' (or there is no acceptable conversion) @@ -14,7 +14,7 @@ ERROR: 0:42: '%' : wrong operand types: no operation '%' exists that takes a le ERROR: 0:43: '%' : wrong operand types: no operation '%' exists that takes a left-hand operand of type 'mediump int' and a right operand of type 'mediump float' (or there is no acceptable conversion) ERROR: 0:44: '%' : wrong operand types: no operation '%' exists that takes a left-hand operand of type 'mediump float' and a right operand of type 'mediump uint' (or there is no acceptable conversion) ERROR: 0:45: '++' : l-value required "instanceName" (can't modify a uniform) -ERROR: 0:45: '++' : wrong operand type no operation '++' exists that takes an operand of type layout(shared ) uniform block (or there is no acceptable conversion) +ERROR: 0:45: '++' : wrong operand type no operation '++' exists that takes an operand of type layout(column_major shared ) uniform block (or there is no acceptable conversion) ERROR: 0:46: '++' : wrong operand type no operation '++' exists that takes an operand of type structure (or there is no acceptable conversion) ERROR: 0:47: '--' : wrong operand type no operation '--' exists that takes an operand of type 5-element array of mediump float (or there is no acceptable conversion) ERROR: 0:48: '++' : wrong operand type no operation '++' exists that takes an operand of type 3-component vector of bool (or there is no acceptable conversion) @@ -39,7 +39,7 @@ ERROR: 0:70: '~' : wrong operand type no operation '~' exists that takes an ope ERROR: 0:71: '~' : wrong operand type no operation '~' exists that takes an operand of type mediump 4X4 matrix of float (or there is no acceptable conversion) ERROR: 0:72: '~' : wrong operand type no operation '~' exists that takes an operand of type mediump 3-component vector of float (or there is no acceptable conversion) ERROR: 0:73: '~' : wrong operand type no operation '~' exists that takes an operand of type 5-element array of mediump float (or there is no acceptable conversion) -ERROR: 0:74: '~' : wrong operand type no operation '~' exists that takes an operand of type layout(shared ) uniform block (or there is no acceptable conversion) +ERROR: 0:74: '~' : wrong operand type no operation '~' exists that takes an operand of type layout(column_major shared ) uniform block (or there is no acceptable conversion) ERROR: 0:76: '<<' : wrong operand types: no operation '<<' exists that takes a left-hand operand of type 'mediump int' and a right operand of type 'mediump 3-component vector of int' (or there is no acceptable conversion) ERROR: 0:77: '<<' : wrong operand types: no operation '<<' exists that takes a left-hand operand of type 'mediump uint' and a right operand of type 'mediump 3-component vector of uint' (or there is no acceptable conversion) ERROR: 0:78: '>>' : wrong operand types: no operation '>>' exists that takes a left-hand operand of type 'mediump int' and a right operand of type 'mediump float' (or there is no acceptable conversion) @@ -60,7 +60,7 @@ ERROR: node is still EOpNull! 0:13 Function Definition: main( (void) 0:13 Function Parameters: 0:? Sequence -0:30 'instanceName' (layout(shared ) uniform block) +0:30 'instanceName' (layout(column_major shared ) uniform block) 0:31 's' (structure) 0:32 'i' (mediump int) 0:33 'u' (mediump uint) @@ -74,7 +74,7 @@ ERROR: node is still EOpNull! 0:42 'f' (mediump float) 0:43 'i' (mediump int) 0:44 'f' (mediump float) -0:45 'instanceName' (layout(shared ) uniform block) +0:45 'instanceName' (layout(column_major shared ) uniform block) 0:46 's' (structure) 0:47 'a' (5-element array of mediump float) 0:48 'b3' (3-component vector of bool) @@ -111,7 +111,7 @@ ERROR: node is still EOpNull! 0:71 'm4' (mediump 4X4 matrix of float) 0:72 'v3' (mediump 3-component vector of float) 0:73 'a' (5-element array of mediump float) -0:74 'instanceName' (layout(shared ) uniform block) +0:74 'instanceName' (layout(column_major shared ) uniform block) 0:76 'i' (mediump int) 0:77 'u' (mediump uint) 0:78 'i' (mediump int) @@ -212,7 +212,7 @@ ERROR: node is still EOpNull! 0:127 'iv3' (mediump 3-component vector of int) 0:127 'iv3' (mediump 3-component vector of int) 0:? Linker Objects -0:? 'instanceName' (layout(shared ) uniform block) +0:? 'instanceName' (layout(column_major shared ) uniform block) 0:? 's' (structure) 0:? 'a' (5-element array of mediump float) diff --git a/Test/baseResults/400.geom.out b/Test/baseResults/400.geom.out index f59b8e296..5c41c3eac 100644 --- a/Test/baseResults/400.geom.out +++ b/Test/baseResults/400.geom.out @@ -1,5 +1,12 @@ Warning, version 400 is not yet complete; some version-specific features are present, but many are missing. -0:? Sequence +ERROR: 0:13: 'invocations' : can only apply to a standalone qualifier +ERROR: 1 compilation errors. No code generated. + +invocations = 4 +max_vertices = 127 +input primitive = none +output primitive = none +ERROR: node is still EOpNull! 0:3 Function Definition: main( (void) 0:3 Function Parameters: 0:5 Sequence @@ -16,4 +23,5 @@ Warning, version 400 is not yet complete; some version-specific features are pre 0:10 'id' (int) 0:10 'gl_InvocationID' (in int) 0:? Linker Objects +0:? '__anon__0' (layout(stream=0 ) out block) diff --git a/Test/baseResults/410.geom.out b/Test/baseResults/410.geom.out index 2dcd03d29..c8c6cb821 100644 --- a/Test/baseResults/410.geom.out +++ b/Test/baseResults/410.geom.out @@ -1,10 +1,14 @@ Warning, version 410 is not yet complete; some version-specific features are present, but many are missing. +invocations = 0 +max_vertices = 0 +input primitive = none +output primitive = none 0:? Sequence 0:3 Function Definition: main( (void) 0:3 Function Parameters: 0:5 Sequence 0:5 move second child to first child (int) -0:5 'gl_ViewportIndex' (out int) +0:5 'gl_ViewportIndex' (layout(stream=0 ) out int) 0:5 Constant: 0:5 7 (const int) 0:? Linker Objects diff --git a/Test/baseResults/420.vert.out b/Test/baseResults/420.vert.out index 263651d78..d5eeb5260 100644 --- a/Test/baseResults/420.vert.out +++ b/Test/baseResults/420.vert.out @@ -116,10 +116,10 @@ ERROR: node is still EOpNull! 0:? 4.200000 0:? 'dx' (const float) 0:? 4.200000 -0:? 'boundInst' (layout(binding=3 shared ) uniform block) -0:? '__anon__0' (layout(binding=7 shared ) uniform block) +0:? 'boundInst' (layout(binding=3 column_major shared ) uniform block) +0:? '__anon__0' (layout(binding=7 column_major shared ) uniform block) 0:? '__anon__1' (layout(binding=1 ) in block) -0:? '__anon__2' (layout(shared ) uniform block) +0:? '__anon__2' (layout(column_major shared ) uniform block) 0:? 'sampb1' (layout(binding=4 ) uniform sampler2D) 0:? 'sampb2' (layout(binding=5 ) uniform 10-element array of sampler2D) 0:? 'gl_VertexID' (gl_VertexId int) diff --git a/Test/baseResults/mains1.frag.out b/Test/baseResults/mains1.frag.out index 6acc69d5e..43dba1490 100644 --- a/Test/baseResults/mains1.frag.out +++ b/Test/baseResults/mains1.frag.out @@ -20,6 +20,10 @@ Warning, version 150 is not yet complete; some version-specific features are pre ERROR: 1 compilation errors. No code generated. +invocations = 0 +max_vertices = 0 +input primitive = none +output primitive = none ERROR: node is still EOpNull! 0:3 Function Definition: foo( (void) 0:3 Function Parameters: @@ -28,6 +32,10 @@ ERROR: node is still EOpNull! noMain2.geom Warning, version 150 is not yet complete; some version-specific features are present, but many are missing. +invocations = 0 +max_vertices = 0 +input primitive = none +output primitive = none 0:? Sequence 0:3 Function Definition: bar( (void) 0:3 Function Parameters: @@ -43,6 +51,10 @@ Linked fragment stage: ERROR: Linking fragment stage: Multiple function bodies in multiple compilation units for the same signature in the same stage: main( +invocations = 0 +max_vertices = 0 +input primitive = none +output primitive = none ERROR: node is still EOpNull! 0:3 Function Definition: foo( (void) 0:3 Function Parameters: diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out index 74070946a..d2ee6bcdc 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -6,21 +6,21 @@ ERROR: 0:37: 'view' : redefinition ERROR: 0:68: 'lightPosition' : redefinition ERROR: 0:75: 'Atten' : member storage qualifier cannot contradict block storage qualifier ERROR: 0:87: 'Color' : redefinition -ERROR: 0:92: 'origin_upper_left' : unrecognized layout identifier -ERROR: 0:93: 'pixel_center_integer' : unrecognized layout identifier -ERROR: 0:94: 'origin_upper_left' : unrecognized layout identifier -ERROR: 0:94: 'pixel_center_integer' : unrecognized layout identifier -ERROR: 0:96: 'early_fragment_tests' : unrecognized layout identifier -ERROR: 0:99: 'local_size_x' : there is no such layout identifier taking an assigned value -ERROR: 0:99: 'local_size_y' : there is no such layout identifier taking an assigned value -ERROR: 0:100: 'local_size_x' : there is no such layout identifier taking an assigned value +ERROR: 0:92: 'origin_upper_left' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:93: 'pixel_center_integer' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:94: 'origin_upper_left' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:94: 'pixel_center_integer' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:96: 'early_fragment_tests' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:99: 'local_size_x' : there is no such layout identifier for this stage taking an assigned value +ERROR: 0:99: 'local_size_y' : there is no such layout identifier for this stage taking an assigned value +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 taking an assigned value -ERROR: 0:106: 'depth_greater' : unrecognized layout identifier -ERROR: 0:112: 'depth_any' : unrecognized layout identifier -ERROR: 0:115: 'depth_greater' : unrecognized layout identifier -ERROR: 0:118: 'depth_less' : unrecognized layout identifier -ERROR: 0:121: 'depth_unchanged' : unrecognized layout identifier +ERROR: 0:103: 'index' : there is no such layout identifier for this stage taking an assigned value +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) +ERROR: 0:118: 'depth_less' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:121: 'depth_unchanged' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) ERROR: 0:150: 'constructor' : constructing from a non-dereferenced array ERROR: 0:150: '=' : cannot convert from 'const float' to '3-element array of 4-component vector of float' ERROR: 0:152: 'constructor' : cannot convert parameter 1 from 'const 2-element array of 4-component vector of float' to '4-component vector of float' diff --git a/Test/baseResults/specExamples.vert.out b/Test/baseResults/specExamples.vert.out index 50603c52e..1de3092a9 100644 --- a/Test/baseResults/specExamples.vert.out +++ b/Test/baseResults/specExamples.vert.out @@ -1,30 +1,30 @@ 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:31: 'triangles' : unrecognized layout identifier -ERROR: 0:31: 'invocations' : there is no such layout identifier taking an assigned value -ERROR: 0:33: 'lines' : unrecognized layout identifier -ERROR: 0:35: 'triangle_strip' : unrecognized layout identifier -ERROR: 0:35: 'max_vertices' : there is no such layout identifier taking an assigned value -ERROR: 0:36: 'max_vertices' : there is no such layout identifier taking an assigned value -ERROR: 0:37: 'triangle_strip' : unrecognized layout identifier -ERROR: 0:41: 'stream' : there is no such layout identifier taking an assigned value -ERROR: 0:43: 'stream' : there is no such layout identifier taking an assigned value -ERROR: 0:45: 'stream' : there is no such layout identifier taking an assigned value -ERROR: 0:46: 'stream' : there is no such layout identifier taking an assigned value -ERROR: 0:47: 'stream' : there is no such layout identifier taking an assigned value -ERROR: 0:50: 'stream' : there is no such layout identifier taking an assigned value -ERROR: 0:55: 'stream' : there is no such layout identifier taking an assigned value +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) +ERROR: 0:35: 'triangle_strip' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:35: 'max_vertices' : there is no such layout identifier for this stage taking an assigned value +ERROR: 0:36: 'max_vertices' : there is no such layout identifier for this stage taking an assigned value +ERROR: 0:37: 'triangle_strip' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:41: 'stream' : there is no such layout identifier for this stage taking an assigned value +ERROR: 0:43: 'stream' : there is no such layout identifier for this stage taking an assigned value +ERROR: 0:45: 'stream' : there is no such layout identifier for this stage taking an assigned value +ERROR: 0:46: 'stream' : there is no such layout identifier for this stage taking an assigned value +ERROR: 0:47: 'stream' : there is no such layout identifier for this stage taking an assigned value +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 taking an assigned value +ERROR: 0:85: 'offset' : there is no such layout identifier for this stage taking an assigned value 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 taking an assigned value +ERROR: 0:89: 'offset' : there is no such layout identifier for this stage taking an assigned value WARNING: 0:89: '' : cannot set qualifier defaults when using a type and no identifier ERROR: 0:91: 'bar' : redefinition -ERROR: 0:92: 'offset' : there is no such layout identifier taking an assigned value +ERROR: 0:92: 'offset' : there is no such layout identifier for this stage taking an assigned value ERROR: 0:92: 'bar' : redefinition -ERROR: 0:94: 'offset' : there is no such layout identifier taking an assigned value +ERROR: 0:94: 'offset' : there is no such layout identifier for this stage taking an assigned value 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 @@ -34,8 +34,8 @@ ERROR: 0:112: 'ColorIvn' : identifier not previously declared ERROR: 0:132: 'shared' : not supported in this stage: vertex ERROR: 0:134: '' : function does not return a value: funcA ERROR: 0:136: '' : function does not return a value: funcB -ERROR: 0:137: 'rgba32f' : unrecognized layout identifier -ERROR: 0:138: 'rgba32f' : unrecognized layout identifier +ERROR: 0:137: 'rgba32f' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:138: 'rgba32f' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) ERROR: 0:153: '' : function does not return a value: func3 ERROR: 0:192: 'constructor' : constructing from a non-dereferenced array ERROR: 0:193: 'constructor' : constructing from a non-dereferenced array @@ -276,7 +276,7 @@ ERROR: node is still EOpNull! 0:? Linker Objects 0:? 'Coords' (out block) 0:? '__anon__0' (out block) -0:? 'transforms' (layout(shared ) uniform 4-element array of block) +0:? 'transforms' (layout(column_major shared ) uniform 4-element array of block) 0:? 'normal' (layout(location=3 ) in 4-component vector of float) 0:? 'colors' (layout(location=6 ) in 3-element array of 4-component vector of float) 0:? 's' (layout(location=3 ) structure) @@ -285,7 +285,7 @@ ERROR: node is still EOpNull! 0:? 'var5' (smooth out 4-component vector of float) 0:? '__anon__2' (out block) 0:? 'var7' (smooth out 4-component vector of float) -0:? '__anon__3' (layout(std140 ) uniform block) +0:? '__anon__3' (layout(row_major std140 ) uniform block) 0:? '__anon__4' (layout(column_major shared ) uniform block) 0:? 's17' (layout(binding=3 ) uniform sampler2D) 0:? 'a2' (layout(binding=2 ) uniform int) @@ -303,8 +303,8 @@ ERROR: node is still EOpNull! 0:? 'c' (in 4-component vector of float) 0:? 'd' (in 4-component vector of float) 0:? 'v' (smooth out 4-component vector of float) -0:? '__anon__6' (layout(shared ) coherent uniform block) -0:? '__anon__7' (layout(shared ) uniform block) +0:? '__anon__6' (layout(row_major shared ) coherent uniform block) +0:? '__anon__7' (layout(row_major shared ) uniform block) 0:? 'shv' (shared 4-component vector of float) 0:? 'img1' (uniform image2D) 0:? 'img2' (coherent uniform image2D) diff --git a/Todo.txt b/Todo.txt index 2b5d34218..a69618af4 100644 --- a/Todo.txt +++ b/Todo.txt @@ -37,6 +37,9 @@ Link Validation - Non ES: matching redeclarations of interface blocks - Non ES: read or write to both gl_ClipVertex and gl_ClipDistance - Non ES: write to only one of gl_FragColor, gl_FragData, or user-declared + - 1.50: at least one geometry shader says input primitive and at least one says output primitive... + - 1.50: at least one geometry shader says max_vertices... + - 1.50: match between all explicit input array sizes and input primitive - 4.3: Be clear that early_fragment_tests is only needed in one fragment-stage compilation unit. - 4.3: Be clear that implicit array sizing is only within a stage, not cross stage. - 4.4: overlapping transform/feedback offsets, offset/stride overflow checks, and stride matching @@ -50,11 +53,12 @@ Shader Functionality to Implement/Finish + implement non-inductive array accesses limitation detection ESSL 3.0 - "const" compile-time constant propagation in the front-end has to be complete, for all built-in functions + - add limitation around #define GL_FRAGMENT_PRECISION_HIGH 1 ? GLSL 1.2 + Handle multiple compilation units per stage + Allow initializers on uniform declarations - signature matching takes type conversions into account, ambiguity is an error - - all constructors to contain non-dereferenced arrays? + - allow constructors to contain non-dereferenced arrays? GLSL 1.3 . flat is for both user and predeclared built-in in/out variables GLSL 1.3 (Non-ES) @@ -77,7 +81,7 @@ Shader Functionality to Implement/Finish + ftransform(). Use invariant outputs instead. GLSL 1.5 (Non-ES) - Deprecated gl_MaxVaryingComponents - - Add new minimum maximums for gl_MaxVertexOutputComponents, gl_MaxGeometryInputComponents, gl_MaxGeometryOutputComponents, and gl_MaxFragmentInputComponents, + + Add new minimum maximums for gl_MaxVertexOutputComponents, gl_MaxGeometryInputComponents, gl_MaxGeometryOutputComponents, and gl_MaxFragmentInputComponents, rather than relying on gl_MaxVaryingComponents. Also, corrected gl_MaxVaryingComponents to be 60 instead of 64. + Added gl_PrimitiveID as an input to fragment shaders. - Added gl_FragCoord qualifiers origin_upper_left, and pixel_center_integer to modify the values returned by gl_FragCoord (and have no affect on any other aspect of the pipeline or language). @@ -85,10 +89,10 @@ Shader Functionality to Implement/Finish - Added support for multi-sample textures through sampler2DMS and sampler2DMSArray support in texelFetch() and textureSize(). + Broadened interface blocks from just uniforms to in and out interfaces as well. + Broaden array usage to include vertex shader inputs (vertex in). - - Added geometry shaders. This includes targeting layers in FBO rendering. - - geometry shader layouts: they must be declared, telling the system the primitive input and output types and maximum number of vertices. - - Added geometry shader constants. - - Broaden structure usage to include geometry inputs and geometry outputs. + + Added geometry shaders. This includes targeting layers in FBO rendering. + + geometry shader layouts: they must be declared, telling the system the primitive input and output types and maximum number of vertices. + + Added geometry shader constants. + + Broaden structure usage to include geometry inputs and geometry outputs. GLSL 4.0 - tessellation control stage and tessellation evaluation stage. Includes barrier() built-in for synchronization. - Polymorphic functions: Run-time selection of what function gets called, through the new keyword subroutine. @@ -203,7 +207,7 @@ Shader Functionality to Implement/Finish - Set both gl_MaxFragmentImageUniformsand gl_MaxCombinedImageUniforms to 8. - Clarify textureSize() for cube map arrays. - For layout qualifiers, - - make negative output locations a compile-time error, and + - 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. diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 442e3ae49..98e119705 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -176,14 +176,8 @@ protected: }; // -// TPublicType (coming up after some dependent declarations) -// is a workaround for a problem with the yacc stack, It can't have -// types that it thinks have non-trivial constructors. It should -// just be used while recognizing the grammar, not anything else. Pointers -// could be used, but also trying to avoid lots of memory management overhead. -// -// Not as bad as it looks, there is no actual assumption that the fields -// match up or are named the same or anything like that. +// Following are a series of helper enums for managing layouts and qualifiers, +// used for TPublicType, TType, others. // enum TLayoutPacking { @@ -191,14 +185,32 @@ enum TLayoutPacking { ElpShared, // default, but different than saying nothing ElpStd140, ElpStd430, - ElpPacked // see bitfield width below + ElpPacked + // If expanding, see bitfield width below }; enum TLayoutMatrix { ElmNone, ElmRowMajor, ElmColumnMajor // default, but different than saying nothing -}; // see bitfield width below + // If expanding, see bitfield width below +}; + +// Union of geometry shader and tessellation shader geometry types. +// They don't go into TType, but rather have current state per shader or +// active parser type (TPublicType). +enum TLayoutGeometry { + ElgNone, + ElgPoints, + ElgLines, + ElgLinesAdjacency, + ElgLineStrip, + ElgTriangles, + ElgTrianglesAdjacency, + ElgTriangleStrip, + ElgQuads, + ElgIsolines, +}; class TQualifier { public: @@ -298,13 +310,15 @@ public: layoutPacking = ElpNone; layoutSlotLocation = layoutLocationEnd; layoutBinding = layoutBindingEnd; + layoutStream = layoutStreamEnd; } bool hasLayout() const { return layoutMatrix != ElmNone || layoutPacking != ElpNone || hasLocation() || - hasBinding(); + hasBinding() || + hasStream(); } TLayoutMatrix layoutMatrix : 3; TLayoutPacking layoutPacking : 4; @@ -312,6 +326,8 @@ public: 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 layoutSlotLocation != layoutLocationEnd; @@ -320,6 +336,10 @@ public: { return layoutBinding != layoutBindingEnd; } + bool hasStream() const + { + return layoutStream != layoutStreamEnd; + } static const char* getLayoutPackingString(TLayoutPacking packing) { switch (packing) { @@ -338,13 +358,50 @@ public: default: return "none"; } } + static const char* getGeometryString(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return "points"; + case ElgLines: return "lines"; + case ElgLinesAdjacency: return "lines_adjancency"; + case ElgLineStrip: return "line_strip"; + case ElgTriangles: return "triangles"; + case ElgTrianglesAdjacency: return "triangles_adjacency"; + case ElgTriangleStrip: return "triangle_strip"; + case ElgQuads: return "quads"; + case ElgIsolines: return "isolines"; + default: return "none"; + } + } + static int mapGeometryToSize(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return 1; + case ElgLines: return 2; + case ElgLinesAdjacency: return 4; + case ElgTriangles: return 3; + case ElgTrianglesAdjacency: return 6; + default: return 0; + } + } }; +// +// TPublicType is just temporarily used while parsing and not quite the same +// information kept per node in TType. Due to the bison stack, it can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. +// Once enough is known about the situation, the proper information +// moved into a TType, or the parse context, etc. +// class TPublicType { public: TBasicType basicType; TSampler sampler; TQualifier qualifier; + TLayoutGeometry geometry; // don't keep this in the qualifier; it's more a per shader than per type + int invocations; // 0 means no declaration + int maxVertices; int vectorSize : 4; int matrixCols : 4; int matrixRows : 4; @@ -375,6 +432,9 @@ public: initType(loc); sampler.clear(); initQualifiers(global); + geometry = ElgNone; + invocations = 0; // 0 means no declaration + maxVertices = 0; } void setVector(int s) @@ -641,6 +701,8 @@ public: p += snprintf(p, end - p, "location=%d ", qualifier.layoutSlotLocation); if (qualifier.hasBinding()) p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding); + if (qualifier.hasStream()) + p += snprintf(p, end - p, "stream=%d ", qualifier.layoutStream); if (qualifier.layoutMatrix != ElmNone) p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); if (qualifier.layoutPacking != ElpNone) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 87a3e9376..451c25c2a 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -77,19 +77,17 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; switch (language) { - case EShLangVertex: - defaultPrecision[EbtInt] = EpqHigh; - defaultPrecision[EbtUint] = EpqHigh; - defaultPrecision[EbtFloat] = EpqHigh; - defaultPrecision[EbtSampler] = EpqLow; - break; case EShLangFragment: defaultPrecision[EbtInt] = EpqMedium; defaultPrecision[EbtUint] = EpqMedium; defaultPrecision[EbtSampler] = EpqLow; break; default: - infoSink.info.message(EPrefixError, "unexpected es-profile stage"); + defaultPrecision[EbtInt] = EpqHigh; + defaultPrecision[EbtUint] = EpqHigh; + defaultPrecision[EbtFloat] = EpqHigh; + defaultPrecision[EbtSampler] = EpqLow; + break; } } @@ -104,6 +102,8 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, globalInputDefaults.clear(); globalOutputDefaults.clear(); + if (language == EShLangGeometry) + globalOutputDefaults.layoutStream = 0; } // @@ -1587,7 +1587,7 @@ void TParseContext::mergeQualifiers(TSourceLoc loc, TQualifier& dst, const TQual dst.precision = src.precision; // Layout qualifiers - mergeLayoutQualifiers(loc, dst, src); + mergeObjectLayoutQualifiers(loc, dst, src); // individual qualifiers bool repeated = false; @@ -2109,26 +2109,68 @@ void TParseContext::finalize() void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id) { std::transform(id.begin(), id.end(), id.begin(), ::tolower); - if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) + + if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) { publicType.qualifier.layoutMatrix = ElmColumnMajor; - else if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) + return; + } + if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) { publicType.qualifier.layoutMatrix = ElmRowMajor; - else if (id == TQualifier::getLayoutPackingString(ElpPacked)) + return; + } + if (id == TQualifier::getLayoutPackingString(ElpPacked)) { publicType.qualifier.layoutPacking = ElpPacked; - else if (id == TQualifier::getLayoutPackingString(ElpShared)) + return; + } + if (id == TQualifier::getLayoutPackingString(ElpShared)) { publicType.qualifier.layoutPacking = ElpShared; - else if (id == TQualifier::getLayoutPackingString(ElpStd140)) + return; + } + if (id == TQualifier::getLayoutPackingString(ElpStd140)) { publicType.qualifier.layoutPacking = ElpStd140; - else if (id == TQualifier::getLayoutPackingString(ElpStd430)) { + return; + } + if (id == TQualifier::getLayoutPackingString(ElpStd430)) { requireProfile(loc, ECoreProfile | ECompatibilityProfile, "std430"); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "std430"); publicType.qualifier.layoutPacking = ElpStd430; - } else if (id == "location") - error(loc, "requires an integer assignment (e.g., location = 4)", "location", ""); - else if (id == "binding") { - error(loc, "requires an integer assignment (e.g., binding = 4)", "binding", ""); - } else - error(loc, "unrecognized layout identifier", id.c_str(), ""); + return; + } + if (language == EShLangGeometry || language == EShLangTessEvaluation) { + if (id == TQualifier::getGeometryString(ElgTriangles)) { + publicType.geometry = ElgTriangles; + return; + } + if (language == EShLangGeometry) { + if (id == TQualifier::getGeometryString(ElgPoints)) { + publicType.geometry = ElgPoints; + return; + } + if (id == TQualifier::getGeometryString(ElgLineStrip)) { + publicType.geometry = ElgLineStrip; + return; + } + if (id == TQualifier::getGeometryString(ElgLines)) { + publicType.geometry = ElgLines; + return; + } + if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { + publicType.geometry = ElgLinesAdjacency; + return; + } + if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { + publicType.geometry = ElgTrianglesAdjacency; + return; + } + if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { + publicType.geometry = ElgTriangleStrip; + return; + } + } else { + // TODO: tessellation evaluation + } + } + error(loc, "unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)", id.c_str(), ""); } // Put the id's layout qualifier value into the public type. This is before we know any @@ -2143,22 +2185,54 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, error(loc, "location is too large", id.c_str(), ""); else publicType.qualifier.layoutSlotLocation = value; - } else if (id == "binding") { + return; + } + 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) error(loc, "binding is too large", id.c_str(), ""); else publicType.qualifier.layoutBinding = value; - } else - error(loc, "there is no such layout identifier taking an assigned value", id.c_str(), ""); + return; + } + if (language == EShLangGeometry) { + if (id == "invocations") { + profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, 0, "invocations"); + publicType.invocations = value; + return; + } + if (id == "max_vertices") { + publicType.maxVertices = value; + return; + } + if (id == "stream") { + publicType.qualifier.layoutStream = value; + return; + } + } + error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); // TODO: semantics: error check: make sure locations are non-overlapping across the whole stage // TODO: semantics: error check: output arrays can only be indexed with a constant (es 300) } +// +// Merge characteristics of the 'src' qualifier into the 'dst', at the TPublicType level, +// which means for layout-qualifier information not kept per qualifier. +// +void TParseContext::mergeShaderLayoutQualifiers(TSourceLoc loc, TPublicType& dst, const TPublicType& src) +{ + if (src.geometry != ElgNone) + dst.geometry = src.geometry; + if (src.invocations != 0) + dst.invocations = src.invocations; + if (src.maxVertices != 0) + dst.maxVertices = src.maxVertices; +} + // Merge any layout qualifier information from src into dst, leaving everything else in dst alone -void TParseContext::mergeLayoutQualifiers(TSourceLoc loc, TQualifier& dst, const TQualifier& src) +void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst, const TQualifier& src) { if (src.layoutMatrix != ElmNone) dst.layoutMatrix = src.layoutMatrix; @@ -2171,40 +2245,31 @@ void TParseContext::mergeLayoutQualifiers(TSourceLoc loc, TQualifier& dst, const if (src.hasBinding()) dst.layoutBinding = src.layoutBinding; + + if (src.hasStream()) + dst.layoutStream = src.layoutStream; } // Do error layout error checking given a full variable/block declaration. -void TParseContext::layoutCheck(TSourceLoc loc, const TSymbol& symbol) +void TParseContext::layoutTypeCheck(TSourceLoc loc, const TSymbol& symbol) { const TType& type = symbol.getType(); const TQualifier& qualifier = type.getQualifier(); + + // first, qualifier only error checking + layoutQualifierCheck(loc, qualifier); + // now, error checking combining type and qualifier if (qualifier.hasLocation()) { switch (qualifier.storage) { case EvqVaryingIn: { - const char* feature = "location qualifier on input"; - if (profile == EEsProfile) - requireStage(loc, EShLangVertex, feature); - requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); - if (language == EShLangVertex) - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 330, 0, feature); - else - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, feature); if (type.getBasicType() == EbtBlock) profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, 0 /* TODO ARB_enhanced_layouts*/, "location qualifier on input block"); break; } case EvqVaryingOut: { - const char* feature = "location qualifier on output"; - if (profile == EEsProfile) - requireStage(loc, EShLangFragment, feature); - requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); - if (language == EShLangFragment) - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 330, 0, feature); - else - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, feature); if (type.getBasicType() == EbtBlock) profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, 0 /* TODO ARB_enhanced_layouts*/, "location qualifier on output block"); break; @@ -2213,8 +2278,6 @@ void TParseContext::layoutCheck(TSourceLoc loc, const TSymbol& symbol) case EvqBuffer: { const char* feature = "location qualifier on uniform or buffer"; - requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, feature); if (symbol.getAsVariable() == 0) error(loc, "can only be used on variable declaration", feature, ""); break; @@ -2235,19 +2298,78 @@ void TParseContext::layoutCheck(TSourceLoc loc, const TSymbol& symbol) // // TODO: binding error checking against limits, arrays // - if (qualifier.storage != EvqUniform && qualifier.storage != EvqBuffer) - error(loc, "requires uniform or buffer storage qualifier", "binding", ""); if (type.getBasicType() != EbtSampler && type.getBasicType() != EbtBlock) error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", ""); // TODO: atomic counter functionality: include in test above } } -///////////////////////////////////////////////////////////////////////////////// -// -// Non-Errors. -// -///////////////////////////////////////////////////////////////////////////////// +// 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) +{ + if (qualifier.hasLocation()) { + switch (qualifier.storage) { + case EvqVaryingIn: + { + const char* feature = "location qualifier on input"; + if (profile == EEsProfile) + requireStage(loc, EShLangVertex, feature); + requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); + if (language == EShLangVertex) + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 330, 0, feature); + else + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, feature); + break; + } + case EvqVaryingOut: + { + const char* feature = "location qualifier on output"; + if (profile == EEsProfile) + requireStage(loc, EShLangFragment, feature); + requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); + if (language == EShLangFragment) + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 330, 0, feature); + else + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, feature); + break; + } + case EvqUniform: + case EvqBuffer: + { + const char* feature = "location qualifier on uniform or buffer"; + requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, feature); + break; + } + default: + break; + } + } + + if (qualifier.hasBinding()) { + if (qualifier.storage != EvqUniform && qualifier.storage != EvqBuffer) + error(loc, "requires uniform or buffer storage qualifier", "binding", ""); + } + + if (qualifier.hasStream()) { + if (qualifier.storage != EvqVaryingOut) + error(loc, "can only be used on an output", "stream", ""); + } +} + +// For places that can't have shader-level layout qualifiers +void TParseContext::checkNoShaderLayouts(TSourceLoc loc, const TPublicType& publicType) +{ + const char* message = "can only apply to a standalone qualifier"; + + if (publicType.geometry != ElgNone) + error(loc, message, TQualifier::getGeometryString(publicType.geometry), ""); + if (publicType.invocations > 0) + error(loc, message, "invocations", ""); + if (publicType.maxVertices > 0) + error(loc, message, "max_vertices", ""); +} // // Look up a function name in the symbol table, and make sure it is a function. @@ -2292,6 +2414,13 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, if (! initializer) nonInitConstCheck(loc, identifier, type); + // Pick up defaults + if (! type.getQualifier().hasStream() && language == EShLangGeometry && type.getQualifier().storage == EvqVaryingOut) + type.getQualifier().layoutStream = globalOutputDefaults.layoutStream; + + if (publicType.geometry != ElgNone) + error(loc, "geometry primitive qualifier cannot be applied to a variable declaration", TQualifier::getGeometryString(publicType.geometry), ""); + // Check for redeclaration of built-ins and/or attempting to declare a reserved name bool newDeclaration = false; // true if a new entry gets added to the symbol table TSymbol* symbol = redeclareBuiltin(loc, identifier, newDeclaration); @@ -2331,9 +2460,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, initNode = executeInitializer(loc, identifier, initializer, variable); } - // look for errors in layout qualifier use + // look for errors/adjustments in layout qualifier use if (symbol) - layoutCheck(loc, *symbol); + layoutTypeCheck(loc, *symbol); // see if it's a linker-level object to track if (symbol && newDeclaration && symbolTable.atGlobalLevel()) @@ -2732,7 +2861,7 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* if (profile == EEsProfile && arraySizes) arraySizeRequiredCheck(loc, arraySizes->getSize()); - switch (currentBlockDefaults.storage) { + switch (currentBlockQualifier.storage) { case EvqBuffer: requireProfile(loc, ECoreProfile | ECompatibilityProfile, "buffer block"); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "buffer block"); @@ -2754,14 +2883,14 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* arrayDimCheck(loc, arraySizes, 0); - // fix and check for member qualifiers and types that don't belong within a block + // fix and check for member storage qualifiers and types that don't belong within a block for (unsigned int member = 0; member < typeList.size(); ++member) { TQualifier& memberQualifier = typeList[member].type->getQualifier(); TSourceLoc memberLoc = typeList[member].loc; pipeInOutFix(memberLoc, memberQualifier); - if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockDefaults.storage) + if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage) error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), ""); - if ((currentBlockDefaults.storage == EvqUniform && memberQualifier.isInterpolation()) || memberQualifier.isAuxiliary()) + if ((currentBlockQualifier.storage == EvqUniform && memberQualifier.isInterpolation()) || memberQualifier.isAuxiliary()) error(memberLoc, "member of uniform block cannot have an auxiliary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), ""); TBasicType basicType = typeList[member].type->getBasicType(); @@ -2772,7 +2901,7 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* // Make default block qualification, and adjust the member qualifications TQualifier defaultQualification; - switch (currentBlockDefaults.storage) { + switch (currentBlockQualifier.storage) { case EvqBuffer: defaultQualification = globalBufferDefaults; break; case EvqUniform: defaultQualification = globalUniformDefaults; break; case EvqVaryingIn: defaultQualification = globalInputDefaults; break; @@ -2780,19 +2909,31 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* default: defaultQualification.clear(); break; } - mergeLayoutQualifiers(loc, defaultQualification, currentBlockDefaults); + // fix and check for member layout qualifiers + mergeObjectLayoutQualifiers(loc, defaultQualification, currentBlockQualifier); for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier memberQualification = defaultQualification; - mergeQualifiers(loc, memberQualification, typeList[member].type->getQualifier(), false); - typeList[member].type->getQualifier() = memberQualification; + TQualifier& memberQualifier = typeList[member].type->getQualifier(); + TSourceLoc memberLoc = typeList[member].loc; + if (memberQualifier.hasStream()) { + if (defaultQualification.layoutStream != memberQualifier.layoutStream) + error(memberLoc, "member cannot contradict block", "stream", ""); + } + TQualifier newMemberQualification = defaultQualification; + mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false); + memberQualifier = newMemberQualification; } + // // Build and add the interface block as a new type named blockName + // - TType blockType(&typeList, *blockName, currentBlockDefaults); + // reverse merge, so that currentBlockQualifier now has all layout information + // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) + mergeObjectLayoutQualifiers(loc, currentBlockQualifier, defaultQualification); + + TType blockType(&typeList, *blockName, currentBlockQualifier); if (arraySizes) blockType.setArraySizes(arraySizes); - blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking; // // Don't make a user-defined type out of block name; that will cause an error @@ -2834,7 +2975,7 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* } // Check for general layout qualifier errors - layoutCheck(loc, variable); + layoutTypeCheck(loc, variable); // Save it in the AST for linker use. intermediate.addSymbolLinkageNode(linkage, variable); @@ -2879,55 +3020,76 @@ void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, } // -// Update qualifier defaults for all forms of declarations, which -// must error check for their form before calling here. +// Updating default qualifier for the case of a declaration with just a qualifier, +// no type, block, or identifier. // -void TParseContext::updateQualifierDefaults(TQualifier qualifier) +void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPublicType& publicType) { - switch (qualifier.storage) { - case EvqBuffer: - if (qualifier.layoutMatrix != ElmNone) - globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.layoutPacking != ElpNone) - globalBufferDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqUniform: - if (qualifier.layoutMatrix != ElmNone) - globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.layoutPacking != ElpNone) - globalUniformDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqVaryingIn: - if (qualifier.hasLocation()) - globalInputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation; - break; - case EvqVaryingOut: - if (qualifier.hasLocation()) - globalOutputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation; - break; - default: - // error handling should be done by callers of this function - break; + if (publicType.maxVertices) { + if (! intermediate.setMaxVertices(publicType.maxVertices)) + error(loc, "cannot change previously set layout value", "max_vertices", ""); + } + if (publicType.invocations) { + if (! intermediate.setInvocations(publicType.invocations)) + error(loc, "cannot change previously set layout value", "invocations", ""); + } + if (publicType.geometry != ElgNone) { + if (publicType.qualifier.storage == EvqVaryingIn) { + switch (publicType.geometry) { + case ElgPoints: + case ElgLines: + case ElgLinesAdjacency: + case ElgTriangles: + case ElgTrianglesAdjacency: + if (! intermediate.setInputPrimitive(publicType.geometry)) + error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.geometry), ""); + break; + default: + error(loc, "does not apply to input", TQualifier::getGeometryString(publicType.geometry), ""); + } + } else if (publicType.qualifier.storage == EvqVaryingOut) { + switch (publicType.geometry) { + case ElgPoints: + case ElgLineStrip: + case ElgTriangleStrip: + if (! intermediate.setOutputPrimitive(publicType.geometry)) + error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.geometry), ""); + break; + default: + error(loc, "does not only apply to output", TQualifier::getGeometryString(publicType.geometry), ""); + } + } else + error(loc, "cannot be used here", TQualifier::getGeometryString(publicType.geometry), ""); } -} -// -// Update defaults for qualifiers. This is called directly for the case -// of a declaration with just a qualifier. -// -void TParseContext::updateQualifierDefaults(TSourceLoc loc, TQualifier qualifier) -{ + const TQualifier& qualifier = publicType.qualifier; + if (qualifier.isAuxiliary() || qualifier.isMemory() || qualifier.isInterpolation() || qualifier.precision != EpqNone) error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "", ""); + layoutQualifierCheck(loc, qualifier); + switch (qualifier.storage) { case EvqUniform: + if (qualifier.layoutMatrix != ElmNone) + globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; + if (qualifier.layoutPacking != ElpNone) + globalUniformDefaults.layoutPacking = qualifier.layoutPacking; + break; case EvqBuffer: + if (qualifier.layoutMatrix != ElmNone) + globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; + if (qualifier.layoutPacking != ElpNone) + globalBufferDefaults.layoutPacking = qualifier.layoutPacking; + break; case EvqVaryingIn: + break; case EvqVaryingOut: + if (qualifier.hasStream()) + globalOutputDefaults.layoutStream = qualifier.layoutStream; break; default: error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); @@ -2938,18 +3100,14 @@ void TParseContext::updateQualifierDefaults(TSourceLoc loc, TQualifier qualifier error(loc, "cannot declare a default, include a type or full declaration", "binding", ""); if (qualifier.hasLocation()) error(loc, "cannot declare a default, use a full declaration", "location", ""); - - updateQualifierDefaults(qualifier); } // // Update defaults for qualifiers when declared with a type, and optionally an identifier. -// (But, not the case of just a qualifier; only when a type is present.) +// (But, not the case of just a qualifier.) // -void TParseContext::updateTypedDefaults(TSourceLoc loc, TQualifier qualifier, const TString* id) +void TParseContext::updateTypedDefaults(TSourceLoc loc, const TQualifier& qualifier, const TString* id) { - bool cantHaveId = false; - if (! id) { if (qualifier.hasLayout()) warn(loc, "cannot set qualifier defaults when using a type and no identifier", "", ""); @@ -2966,8 +3124,12 @@ void TParseContext::updateTypedDefaults(TSourceLoc loc, TQualifier qualifier, co error(loc, "cannot specify packing on a variable declaration", id->c_str(), ""); break; case EvqVaryingIn: + if (qualifier.hasLocation()) + globalInputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation; break; case EvqVaryingOut: + if (qualifier.hasLocation()) + globalOutputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation; break; default: if (qualifier.layoutMatrix != ElmNone || @@ -2976,11 +3138,6 @@ void TParseContext::updateTypedDefaults(TSourceLoc loc, TQualifier qualifier, co else if (qualifier.hasLocation()) error(loc, "location qualifiers only appy to uniform, buffer, in, or out storage qualifiers", id->c_str(), ""); } - - if (cantHaveId) - error(loc, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), ""); - - updateQualifierDefaults(qualifier); } // diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 3e7e1c1d7..ef9212978 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -126,8 +126,11 @@ public: void setLayoutQualifier(TSourceLoc, TPublicType&, TString&); void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int); - void mergeLayoutQualifiers(TSourceLoc, TQualifier& dest, const TQualifier& src); - void layoutCheck(TSourceLoc, const TSymbol&); + void mergeShaderLayoutQualifiers(TSourceLoc, TPublicType& dst, const TPublicType& src); + void mergeObjectLayoutQualifiers(TSourceLoc, TQualifier& dest, const TQualifier& src); + void layoutTypeCheck(TSourceLoc, const TSymbol&); + void layoutQualifierCheck(TSourceLoc, const TQualifier&); + void checkNoShaderLayouts(TSourceLoc, const TPublicType&); const TFunction* findFunction(TSourceLoc, TFunction* pfnCall, bool *builtIn = 0); TIntermNode* declareVariable(TSourceLoc, TString& identifier, TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); @@ -137,9 +140,8 @@ public: void addBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); void addQualifierToExisting(TSourceLoc, TQualifier, const TString& identifier); void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&); - void updateQualifierDefaults(TQualifier); - void updateQualifierDefaults(TSourceLoc, TQualifier); - void updateTypedDefaults(TSourceLoc, TQualifier, const TString* id); + void updateStandaloneQualifierDefaults(TSourceLoc, const TPublicType&); + void updateTypedDefaults(TSourceLoc, const TQualifier&, const TString* id); void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); TIntermNode* addSwitch(TSourceLoc, TIntermTyped* expression, TIntermAggregate* body); TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc); @@ -202,7 +204,7 @@ public: const TType* currentFunctionType; // the return type of the function that's currently being parsed bool functionReturnsValue; // true if a non-void function has a return const TString* blockName; - TQualifier currentBlockDefaults; + TQualifier currentBlockQualifier; TIntermAggregate *linkage; // aggregate node of objects the linker may need, if not referenced by the rest of the AST TPrecisionQualifier defaultPrecision[EbtNumTypes]; TSourceLoc currentLoc; @@ -214,7 +216,7 @@ protected: TPpContext* ppContext; int numErrors; // number of compile-time errors encountered bool parsingBuiltins; // true if parsing built-in symbols/functions - TMap extensionBehavior; // for each extension string, what it's current behavior is set to + TMap extensionBehavior; // for each extension string, what its current behavior is set to static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2)); // see computeSamplerTypeIndex() TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; bool afterEOF; diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 10384d998..f6cf13fa7 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -159,7 +159,8 @@ const char* TParseContext::getPreamble() return "#define GL_ES 1\n"; } else { - return + return + "#define GL_FRAGMENT_PRECISION_HIGH 1\n" "#define GL_ARB_texture_rectangle 1\n" "#define GL_ARB_shading_language_420pack 1\n" "#define GL_ARB_texture_gather 1\n" diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 4c4f08c2e..20b80281f 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -774,16 +774,18 @@ declaration } | type_qualifier SEMICOLON { parseContext.pipeInOutFix($1.loc, $1.qualifier); - parseContext.updateQualifierDefaults($1.loc, $1.qualifier); + parseContext.updateStandaloneQualifierDefaults($1.loc, $1); $$ = 0; } | type_qualifier IDENTIFIER SEMICOLON { parseContext.pipeInOutFix($1.loc, $1.qualifier); + parseContext.checkNoShaderLayouts($1.loc, $1); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string); $$ = 0; } | type_qualifier IDENTIFIER identifier_list SEMICOLON { parseContext.pipeInOutFix($1.loc, $1.qualifier); + parseContext.checkNoShaderLayouts($1.loc, $1); $3->push_back($2.string); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3); $$ = 0; @@ -795,7 +797,8 @@ block_structure --parseContext.structNestingLevel; parseContext.blockName = $2.string; parseContext.pipeInOutFix($1.loc, $1.qualifier); - parseContext.currentBlockDefaults = $1.qualifier; + parseContext.checkNoShaderLayouts($1.loc, $1); + parseContext.currentBlockQualifier = $1.qualifier; $$.loc = $1.loc; $$.typeList = $5; } @@ -915,7 +918,8 @@ parameter_declaration $$ = $2; if ($1.qualifier.precision != EpqNone) $$.param.type->getQualifier().precision = $1.qualifier.precision; - + + parseContext.checkNoShaderLayouts($1.loc, $1); parseContext.parameterSamplerCheck($2.loc, $1.qualifier.storage, *$$.param.type); parseContext.paramCheck($1.loc, $1.qualifier.storage, $$.param.type); } @@ -932,7 +936,8 @@ parameter_declaration $$ = $2; if ($1.qualifier.precision != EpqNone) $$.param.type->getQualifier().precision = $1.qualifier.precision; - + + parseContext.checkNoShaderLayouts($1.loc, $1); parseContext.parameterSamplerCheck($2.loc, $1.qualifier.storage, *$$.param.type); parseContext.paramCheck($1.loc, $1.qualifier.storage, $$.param.type); } @@ -1033,6 +1038,7 @@ fully_specified_type if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1.qualifier)) $2.arraySizes = 0; + parseContext.checkNoShaderLayouts($2.loc, $1); parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); parseContext.precisionQualifierCheck($2.loc, $2); @@ -1089,7 +1095,8 @@ layout_qualifier_id_list } | layout_qualifier_id_list COMMA layout_qualifier_id { $$ = $1; - parseContext.mergeLayoutQualifiers($2.loc, $$.qualifier, $3.qualifier); + parseContext.mergeShaderLayoutQualifiers($2.loc, $$, $3); + parseContext.mergeObjectLayoutQualifiers($2.loc, $$.qualifier, $3.qualifier); } layout_qualifier_id @@ -1127,6 +1134,7 @@ type_qualifier if ($$.basicType == EbtVoid) $$.basicType = $2.basicType; + parseContext.mergeShaderLayoutQualifiers($$.loc, $$, $2); parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false); } ; @@ -2043,6 +2051,7 @@ struct_declaration $$ = $3; + parseContext.checkNoShaderLayouts($1.loc, $1); parseContext.voidErrorCheck($2.loc, (*$3)[0].type->getFieldName(), $2.basicType); parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); parseContext.precisionQualifierCheck($2.loc, $2); diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 5bb81d2f2..e16d9705f 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -579,6 +579,13 @@ bool OutputSwitch(bool /* preVisit */, TIntermSwitch* node, TIntermTraverser* it // void TIntermediate::outputTree(TInfoSink& infoSink) { + if (language == EShLangGeometry) { + infoSink.debug << "invocations = " << invocations << "\n"; + infoSink.debug << "max_vertices = " << maxVertices << "\n"; + infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; + infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n"; + } + if (treeRoot == 0) return; diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 769167e4b..cdcf177d3 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -56,7 +56,8 @@ class TSymbol; // class TIntermediate { public: - explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), numMains(0), numErrors(0) { } + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), numMains(0), numErrors(0), + invocations(0), maxVertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone) { } void setVersion(int v) { version = v; } int getVersion() const { return version; } @@ -99,6 +100,36 @@ public: void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); + bool setInvocations(int i) + { + if (invocations > 0) + return false; + invocations = i; + return true; + } + bool setMaxVertices(int m) + { + if (maxVertices > 0) + return maxVertices == m; + maxVertices = m; + return true; + } + bool setInputPrimitive(TLayoutGeometry p) + { + if (inputPrimitive != ElgNone) + return inputPrimitive == p; + inputPrimitive = p; + return true; + } + TLayoutGeometry getInputPrimitive() { return inputPrimitive; } + bool setOutputPrimitive(TLayoutGeometry p) + { + if (outputPrimitive != ElgNone) + return outputPrimitive == p; + outputPrimitive = p; + return true; + } + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); void merge(TInfoSink&, TIntermediate&); void errorCheck(TInfoSink&); @@ -122,6 +153,10 @@ protected: int version; int numMains; int numErrors; + int invocations; + int maxVertices; + TLayoutGeometry inputPrimitive; + TLayoutGeometry outputPrimitive; // for detecting recursion: pair is struct TCall {