From: John Kessenich Date: Wed, 18 Dec 2013 03:06:24 +0000 (+0000) Subject: Additional semantic checking for tessellation shaders and related clean up: X-Git-Tag: upstream/0.1~768 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7c908d2543eced651a2f6e3f5fb26f2efcf557f9;p=platform%2Fupstream%2Fglslang.git Additional semantic checking for tessellation shaders and related clean up: - non-arrayed geometry inputs and tessellation-control outputs - include user blocks in i/o array resizing based on primitive type - things belonging only to 'in' or 'out' are verified only on 'in' or 'out' - invocation number changing - move shader-scoped qualifier checking into its class - remove an incidental union of two levels of the node hierarchy in the yacc stack - remove layout(location=) default tracking when setting on a variable git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24551 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- diff --git a/Test/150.geom b/Test/150.geom index 70ce7f2..ffb7286 100644 --- a/Test/150.geom +++ b/Test/150.geom @@ -2,7 +2,7 @@ in fromVertex { vec3 color; -} fromV; +} fromV[]; out toFragment { vec3 color; @@ -29,7 +29,7 @@ void main() EmitStreamVertex(1); // ERROR EndStreamPrimitive(0); // ERROR - color = fromV.color; + color = fromV[0].color; gl_ClipDistance[3] = gl_in[1].gl_ClipDistance[2]; gl_Position = gl_in[0].gl_Position; gl_PointSize = gl_in[3].gl_PointSize; @@ -72,7 +72,7 @@ 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(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 outbn2 { layout(invocations = 3) int a; // ERROR, not on a block member @@ -84,16 +84,16 @@ 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 = 300) out; +layout(invocations = 4) in; +layout(max_vertices = 300) out; in inbn { layout(stream = 2) int a; // ERROR, stream on input -} inbi; +} inbi[]; in sameName { int a15; -}; +} insn[]; out sameName { float f15; diff --git a/Test/300layout.vert b/Test/300layout.vert index 6a863cf..b5e1dbe 100644 --- a/Test/300layout.vert +++ b/Test/300layout.vert @@ -51,7 +51,7 @@ shared vec4 compute_only; // ERROR layout(packed) uniform; -layout(packed) float aoeuntaoeu; +layout(packed) float aoeuntaoeu; // ERROR, packed on variable layout(location = 40) in float cd; layout(location = 37) in mat4x3 ce; // ERROR, overlap diff --git a/Test/400.geom b/Test/400.geom index 51c78fe..adb29f6 100644 --- a/Test/400.geom +++ b/Test/400.geom @@ -6,12 +6,12 @@ void main() EndStreamPrimitive(0); EmitVertex(); EndPrimitive(); - int id = gl_InvocationID; } -layout(invocations = 3) out outbn { int a; }; // ERROR, not on a block -layout(max_vertices = 127, invocations = 4) out; +layout(invocations = 4) in outbn { int a; } bn[]; // ERROR, not on a block +layout(max_vertices = 127) out; +layout(invocations = 4) in; #extension GL_ARB_separate_shader_objects : enable @@ -55,5 +55,19 @@ layout(location = 4) in vec4 cva[3]; layout(location = 5) in vec4 cvb[3]; layout(location = 2) in mat3 cmc[3]; // ERROR, collision -patch in vec4 patchIn; // ERROR -patch out vec4 patchOut; // ERROR \ No newline at end of file +patch in vec4 patchIn[]; // ERROR +patch out vec4 patchOut; // ERROR + +in float scalar; // ERROR, no array + +layout(max_vertices = 127, invocations = 4) out; // ERROR +layout(invocations = 4, max_vertices = 127) in; // ERROR +layout(max_vertices = 127, invocations = 4) uniform; // 2 ERRORs + +in inblockscalar { + int a; +} inbls; // ERROR, not an array + +in inblocka { + int a; +} inbla[17]; // ERROR, wrong array size diff --git a/Test/400.tese b/Test/400.tese index 20f52bb..2933493 100644 --- a/Test/400.tese +++ b/Test/400.tese @@ -5,8 +5,8 @@ layout(quads, cw) in; layout(triangles) in; // ERROR layout(isolines) in; // ERROR -layout(cw) in; layout(ccw) in; // ERROR +layout(cw) in; layout(fractional_odd_spacing) in; layout(equal_spacing) in; // ERROR @@ -60,3 +60,13 @@ in gl_PerVertex { float gl_ClipDistance[1]; } gl_in[gl_MaxPatchVertices]; + +layout(quads, cw) out; // ERROR +layout(triangles) out; // ERROR +layout(isolines) out; // ERROR +layout(cw) out; // ERROR +layout(fractional_odd_spacing) out; // ERROR +layout(equal_spacing) out; // ERROR +layout(fractional_even_spacing) out; // ERROR +layout(point_mode) out; // ERROR + diff --git a/Test/420.geom b/Test/420.geom index 2d63256..e883f0b 100644 --- a/Test/420.geom +++ b/Test/420.geom @@ -23,7 +23,7 @@ void foo3() } uniform sampler2D s2D; -in vec2 coord; +in vec2 coord[]; uniform vec4 v4; void foo4() @@ -37,7 +37,7 @@ void foo4() ivec2(2,1) }; - vec4 v = textureGatherOffset(s2D, coord, offsets[i].xy); + vec4 v = textureGatherOffset(s2D, coord[0], offsets[i].xy); offsets[i].xy = ivec2(3); // ERROR v4.x = 3.2; // ERROR diff --git a/Test/420.tesc b/Test/420.tesc index e289238..dcee3ca 100644 --- a/Test/420.tesc +++ b/Test/420.tesc @@ -25,3 +25,5 @@ void main() gl_out[1].gl_Position = p; gl_out[1].gl_PointSize = ps; // ERROR } + +out float outf; // ERROR, no array diff --git a/Test/baseResults/150.geom.out b/Test/baseResults/150.geom.out index ab9c71e..e1c1ae4 100644 --- a/Test/baseResults/150.geom.out +++ b/Test/baseResults/150.geom.out @@ -13,8 +13,8 @@ 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:72: 'triangle_strip' : cannot apply to input +ERROR: 0:73: 'triangle_strip' : cannot apply to: uniform 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 @@ -23,10 +23,10 @@ ERROR: 0:78: 'invocations' : not supported for this version or the enabled exten 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 apply to output +ERROR: 0:83: 'lines' : cannot apply to 'out' 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: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. @@ -52,7 +52,10 @@ ERROR: node is still EOpNull! 0:32 Constant: 0:32 0 (const uint) 0:32 color: direct index for structure (3-component vector of float) -0:32 'fromV' (in block{color}) +0:32 direct index (block{color}) +0:32 'fromV' (in 4-element array of block{color}) +0:32 Constant: +0:32 0 (const int) 0:32 Constant: 0:32 0 (const int) 0:33 move second child to first child (float) @@ -119,7 +122,7 @@ ERROR: node is still EOpNull! 0:67 1.000000 0:67 1.000000 0:? Linker Objects -0:? 'fromV' (in block{color}) +0:? 'fromV' (in 4-element array of block{color}) 0:? 'toF' (layout(stream=0 ) out block{color}) 0:? '__anon__0' (layout(stream=0 ) out block{color}) 0:? 'gl_in' (in 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance}) @@ -134,13 +137,13 @@ ERROR: node is still EOpNull! 0:? 'ouua7' (layout(stream=7 ) out block{a}) 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:? 'bad2v4' (in 4-element array of 4-component vector of float) 0:? '__anon__1' (layout(stream=3 ) out block{a}) 0:? 'outbi' (layout(stream=3 ) out block{a,b,c}) -0:? 'inbi' (in block{a}) -0:? '__anon__2' (in block{a15}) -0:? '__anon__3' (layout(stream=3 ) out block{f15}) -0:? '__anon__4' (layout(column_major shared ) uniform block{b15}) +0:? 'inbi' (in 4-element array of block{a}) +0:? 'insn' (in 4-element array of block{a15}) +0:? '__anon__2' (layout(stream=3 ) out block{f15}) +0:? '__anon__3' (layout(column_major shared ) uniform block{b15}) Linked geometry stage: diff --git a/Test/baseResults/400.geom.out b/Test/baseResults/400.geom.out index a9d7408..58a17b7 100644 --- a/Test/baseResults/400.geom.out +++ b/Test/baseResults/400.geom.out @@ -1,17 +1,24 @@ 400.geom Warning, version 400 is not yet complete; some version-specific features are present, but many are missing. -ERROR: 0:13: 'invocations' : can only apply to a standalone qualifier +ERROR: 0:12: 'invocations' : can only apply to a standalone qualifier ERROR: 0:20: 'patch' : not supported in this stage: geometry ERROR: 0:20: 'gl_PointSize' : cannot add layout to redeclared block member ERROR: 0:20: 'gl_PointSize' : cannot add patch to redeclared block member ERROR: 0:25: 'length' : array must first be sized by a redeclaration or layout qualifier ERROR: 0:36: 'length' : array must first be sized by a redeclaration or layout qualifier -ERROR: 0:40: 'triangles' : inconsistent input primitive for array size colorBad -ERROR: 0:44: 'triangles' : inconsistent input primitive for array size colorbad2 +ERROR: 0: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:58: 'patch' : not supported in this stage: geometry ERROR: 0:59: 'patch' : not supported in this stage: geometry -ERROR: 11 compilation errors. No code generated. +ERROR: 0:61: 'in' : type must be an array: scalar +ERROR: 0:63: 'invocations' : can only apply to 'in' +ERROR: 0:64: 'max_vertices' : can only apply to 'out' +ERROR: 0:65: 'max_vertices' : can only apply to 'out' +ERROR: 0:65: 'invocations' : can only apply to 'in' +ERROR: 0:67: 'in' : type must be an array: inbls +ERROR: 0:71: 'triangles' : inconsistent input primitive for array size of inbla +ERROR: 18 compilation errors. No code generated. invocations = 4 @@ -30,10 +37,10 @@ ERROR: node is still EOpNull! 0:6 0 (const int) 0:7 EmitVertex (void) 0:8 EndPrimitive (void) -0:10 Sequence -0:10 move second child to first child (int) -0:10 'id' (int) -0:10 'gl_InvocationID' (in int) +0:9 Sequence +0:9 move second child to first child (int) +0:9 'id' (int) +0:9 'gl_InvocationID' (in int) 0:23 Function Definition: foo( (void) 0:23 Function Parameters: 0:25 Sequence @@ -65,7 +72,7 @@ ERROR: node is still EOpNull! 0:51 Constant: 0:51 3 (const int) 0:? Linker Objects -0:? '__anon__0' (layout(stream=0 ) out block{a}) +0:? 'bn' (in 3-element array of block{a}) 0:? 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize}) 0:? 'color' (in 3-element array of 4-component vector of float) 0:? 'color2' (in 3-element array of 4-component vector of float) @@ -75,8 +82,11 @@ ERROR: node is still EOpNull! 0:? 'cva' (layout(location=4 ) in 3-element array of 4-component vector of float) 0:? 'cvb' (layout(location=5 ) in 3-element array of 4-component vector of float) 0:? 'cmc' (layout(location=2 ) in 3-element array of 3X3 matrix of float) -0:? 'patchIn' (patch in 4-component vector of float) +0:? 'patchIn' (patch in 3-element array of 4-component vector of float) 0:? 'patchOut' (layout(stream=0 ) patch out 4-component vector of float) +0:? 'scalar' (in float) +0:? 'inbls' (in block{a}) +0:? 'inbla' (in 17-element array of block{a}) Linked geometry stage: diff --git a/Test/baseResults/400.tese.out b/Test/baseResults/400.tese.out index 763ca31..121f32f 100644 --- a/Test/baseResults/400.tese.out +++ b/Test/baseResults/400.tese.out @@ -3,7 +3,7 @@ Warning, version 400 is not yet complete; some version-specific features are pre ERROR: 0:3: 'vertices' : there is no such layout identifier for this stage taking an assigned value ERROR: 0:5: 'triangles' : cannot change previously set input primitive ERROR: 0:6: 'isolines' : cannot change previously set input primitive -ERROR: 0:9: 'ccw' : cannot change previously set vertex order +ERROR: 0:8: 'ccw' : cannot change previously set vertex order ERROR: 0:12: 'equal_spacing' : cannot change previously set vertex spacing ERROR: 0:13: 'fractional_even_spacing' : cannot change previously set vertex spacing ERROR: 0:18: 'patch' : can only use on input in tessellation-evaluation shader @@ -14,7 +14,16 @@ ERROR: 0:49: 'patch' : cannot use interpolation qualifiers with patch ERROR: 0:50: '' : can only have one auxiliary qualifier (centroid, patch, and sample) ERROR: 0:54: 'gl_PerVertex' : block already declared with size, can't redeclare as unsized ERROR: 0:59: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use -ERROR: 14 compilation errors. No code generated. +ERROR: 0:64: 'quads' : cannot apply to 'out' +ERROR: 0:64: 'cw' : can only apply to 'in' +ERROR: 0:65: 'triangles' : cannot apply to 'out' +ERROR: 0:66: 'isolines' : cannot apply to 'out' +ERROR: 0:67: 'cw' : can only apply to 'in' +ERROR: 0:68: 'fractional_odd_spacing' : can only apply to 'in' +ERROR: 0:69: 'equal_spacing' : can only apply to 'in' +ERROR: 0:70: 'fractional_even_spacing' : can only apply to 'in' +ERROR: 0:71: 'point_mode' : can only apply to 'in' +ERROR: 23 compilation errors. No code generated. input primitive = quads diff --git a/Test/baseResults/420.geom.out b/Test/baseResults/420.geom.out index fc6e6c9..6865fa9 100644 --- a/Test/baseResults/420.geom.out +++ b/Test/baseResults/420.geom.out @@ -53,7 +53,10 @@ ERROR: node is still EOpNull! 0:40 'v' (4-component vector of float) 0:40 Function Call: textureGatherOffset(s21;vf2;vi2; (4-component vector of float) 0:40 's2D' (uniform sampler2D) -0:40 'coord' (in 2-component vector of float) +0:40 direct index (2-component vector of float) +0:40 'coord' (in 3-element array of 2-component vector of float) +0:40 Constant: +0:40 0 (const int) 0:40 vector swizzle (2-component vector of int) 0:40 indirect index (2-component vector of int) 0:40 Constant: @@ -115,7 +118,7 @@ ERROR: node is still EOpNull! 0:? 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance}) 0:? 'color3' (in 3-element array of 4-component vector of float) 0:? 's2D' (uniform sampler2D) -0:? 'coord' (in 2-component vector of float) +0:? 'coord' (in 3-element array of 2-component vector of float) 0:? 'v4' (uniform 4-component vector of float) 0:? '__anon__0' (layout(stream=0 ) out block{gl_PointSize,gl_ClipDistance}) diff --git a/Test/baseResults/420.tesc.out b/Test/baseResults/420.tesc.out index 4ffba0b..12794d1 100644 --- a/Test/baseResults/420.tesc.out +++ b/Test/baseResults/420.tesc.out @@ -1,11 +1,12 @@ 420.tesc Warning, version 400 is not yet complete; some version-specific features are present, but many are missing. -ERROR: 0:7: 'vertices' : inconsistent output number of vertices for array size gl_out -ERROR: 0:11: 'vertices' : inconsistent output number of vertices for array size a -ERROR: 0:12: 'vertices' : inconsistent output number of vertices for array size outb +ERROR: 0:7: 'vertices' : inconsistent output number of vertices for array size of gl_out +ERROR: 0:11: 'vertices' : inconsistent output number of vertices for array size of a +ERROR: 0:12: 'vertices' : inconsistent output number of vertices for array size of outb ERROR: 0:26: 'gl_PointSize' : no such field in structure ERROR: 0:26: 'assign' : cannot convert from 'float' to 'block{gl_Position}' -ERROR: 5 compilation errors. No code generated. +ERROR: 0:29: 'out' : type must be an array: outf +ERROR: 6 compilation errors. No code generated. vertices = 4 @@ -76,6 +77,7 @@ ERROR: node is still EOpNull! 0:? 'a' (out 3-element array of int) 0:? 'outb' (out 5-element array of int) 0:? 'outc' (out 4-element array of int) +0:? 'outf' (out float) Linked tessellation control stage: diff --git a/Test/baseResults/specExamples.vert.out b/Test/baseResults/specExamples.vert.out index 29bc8c9..f7aa45c 100644 --- a/Test/baseResults/specExamples.vert.out +++ b/Test/baseResults/specExamples.vert.out @@ -21,7 +21,7 @@ ERROR: 0:85: 'offset' : there is no such layout identifier for this stage taking 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 -WARNING: 0:89: '' : cannot set qualifier defaults when using a type and no identifier +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: 'bar' : redefinition diff --git a/Todo.txt b/Todo.txt index c3b9413..35e8a7e 100644 --- a/Todo.txt +++ b/Todo.txt @@ -17,6 +17,7 @@ Link Validation - 1.3: only statically used built-ins have to be redeclared as flat - 1.5: matching between gl_PerVertex blocks and gl_PerFragment blocks - 1.3: deprecated mixing fixed vertex/fragment stage with programmable fragment/vertex stage. + + 4.0: tessellation primitive, vertices, spacing, order, - 4.3: compute shader not combined with any other stages - 4.3: remove cross-version linking restrictions. - 4.3: Allow mismatches in interpolation and auxiliary qualification across stages. @@ -26,8 +27,8 @@ Link Validation - limits checking: + bindings - number of input/output compononents - - tessellation limits - - tessellation primitive array sizing consistency + + tessellation limits + + tessellation primitive array sizing consistency + Non ES: gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords + Non ES: gl_ClipDistance ... - ... @@ -106,10 +107,10 @@ Shader Functionality to Implement/Finish + texel offset limit checking + 1.50: geometry shaders: max_vertices must be checked against gl_MaxGeometryOutputVertices (maybe at compile time) GLSL 4.0 - - tessellation control stage and tessellation evaluation stage. Includes barrier() built-in for synchronization. - - patch in, patch out - - input/output arrays - - unsized array sizing to gl_MaxPatchVertices, including gl_in/gl_out + + tessellation control stage and tessellation evaluation stage. Includes barrier() built-in for synchronization. + + patch in, patch out + + input/output arrays + + unsized array sizing to gl_MaxPatchVertices, including gl_in/gl_out + built-in variables, functions, and constants verification + layout qualifiers for primitive types - Polymorphic functions: Run-time selection of what function gets called, through the new keyword subroutine. diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 872477d..83e5105 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -471,6 +471,28 @@ struct TShaderQualifiers { order = EvoNone; pointMode = false; } + + // Merge in characteristics from the 'src' qualifier. They can override when + // set, but never erase when not set. + void merge(const TShaderQualifiers& src) + { + if (src.geometry != ElgNone) + geometry = src.geometry; + if (src.pixelCenterInteger) + pixelCenterInteger = src.pixelCenterInteger; + if (src.originUpperLeft) + originUpperLeft = src.originUpperLeft; + if (src.invocations != 0) + invocations = src.invocations; + if (src.vertices != 0) + vertices = src.vertices; + if (src.spacing != EvsNone) + spacing = src.spacing; + if (src.order != EvoNone) + order = src.order; + if (src.pointMode) + pointMode = true; + } }; // diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 9f79c7f..fd61d29 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 "24522" -#define GLSLANG_DATE "2013/12/13 12:26:54" +#define GLSLANG_REVISION "24530" +#define GLSLANG_DATE "2013/12/16 16:58:15" diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 7e071e8..ac576f2 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -1285,8 +1285,6 @@ void TBuiltIns::initialize(int version, EProfile profile) "patch out float gl_TessLevelOuter[4];" "patch out float gl_TessLevelInner[2];" "\n"); - - // TODO 4.0 tessellation: do we also need to support the gl_VerticesOut mentioned in the extension specification? } //============================================================================ diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index d208056..c13c1da 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -529,13 +529,25 @@ void TParseContext::handleIndexLimits(TSourceLoc loc, TIntermTyped* base, TInter } // Return true if this is a geometry shader input array or tessellation control output array. -bool TParseContext::isIoResizeArray(const TType& type) +bool TParseContext::isIoResizeArray(const TType& type) const { return type.isArray() && ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch)); } +// Issue any errors if the non-array object is missing arrayness WRT +// shader I/O that has array requirements. +// All arrayness checking is handled in array paths, this is for +void TParseContext::ioArrayCheck(TSourceLoc loc, const TType& type, const TString& identifier) +{ + if (! type.isArray() && ! symbolTable.atBuiltInLevel()) { + if ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || + (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch)) + error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str()); + } +} + // Handle a dereference of a geometry shader input array or tessellation control output array. // See ioArrayNodeResizeList comment in ParseHelper.h. // @@ -615,9 +627,9 @@ void TParseContext::checkIoArrayConsistency(TSourceLoc loc, int requiredSize, co type.changeArraySize(requiredSize); else if (type.getArraySize() != requiredSize) { if (language == EShLangGeometry) - error(loc, "inconsistent input primitive for array size", feature, name.c_str()); + error(loc, "inconsistent input primitive for array size of", feature, name.c_str()); else if (language == EShLangTessControl) - error(loc, "inconsistent output number of vertices for array size", feature, name.c_str()); + error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str()); else assert(0); } @@ -871,43 +883,14 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(TSourceLoc loc, TFunct // - user function // - subroutine call (not implemented yet) // -TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCall, TIntermNode* intermNode, TIntermAggregate* intermAggregate) +TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCall, TIntermNode* intermNode) { TIntermTyped* result = 0; TOperator op = fnCall->getBuiltInOp(); - if (op == EOpArrayLength) { - if (fnCall->getParamCount() > 0) - error(loc, "method does not accept any arguments", fnCall->getName().c_str(), ""); - int length = 0; - if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray()) - error(loc, "", fnCall->getName().c_str(), "can only be applied to an array"); - else if (intermNode->getAsTyped()->getType().getArraySize() == 0) { - bool implicitlySized = false; - if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType())) { - // We could be between a layout declaration that gives a built-in io array implicit size and - // a user redeclaration of that array, meaning we have to substitute its implicit size here - // without actually redeclaring the array. (It is an error to use a member before the - // redeclaration, but not an error to use the array name itself.) - const TString& name = intermNode->getAsSymbolNode()->getName(); - if (name == "gl_in" || name == "gl_out") - length = getIoArrayImplicitSize(); - } - if (length == 0) { - if (isIoResizeArray(intermNode->getAsTyped()->getType())) - error(loc, "", fnCall->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); - else - error(loc, "", fnCall->getName().c_str(), "array must be declared with a size before using this method"); - } - } else - length = intermNode->getAsTyped()->getType().getArraySize(); - - if (length == 0) - length = 1; - TConstUnionArray unionArray(1); - unionArray[0].setIConst(length); - result = intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc); - } else if (op != EOpNull) { + if (op == EOpArrayLength) + result = handleLengthMethod(loc, fnCall, intermNode); + else if (op != EOpNull) { // // Then this should be a constructor. // Don't go through the symbol table for constructors. @@ -949,7 +932,7 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal } } else { // This is a function call not mapped to built-in operation - result = intermediate.setAggregateOperator(intermAggregate, EOpFunctionCall, fnCandidate->getType(), loc); + result = intermediate.setAggregateOperator(intermNode, EOpFunctionCall, fnCandidate->getType(), loc); result->getAsAggregate()->setName(fnCandidate->getMangledName()); // this is how we know whether the given function is a built-in function or a user-defined function @@ -989,6 +972,43 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal return result; } +// Do all processing handling object.length(). +// Return resulting tree node. +TIntermTyped* TParseContext::handleLengthMethod(TSourceLoc loc, TFunction* fnCall, TIntermNode* intermNode) +{ + int length = 0; + + if (fnCall->getParamCount() > 0) + error(loc, "method does not accept any arguments", fnCall->getName().c_str(), ""); + if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray()) + error(loc, "", fnCall->getName().c_str(), "can only be applied to an array"); + else if (intermNode->getAsTyped()->getType().getArraySize() == 0) { + bool implicitlySized = false; + if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType())) { + // We could be between a layout declaration that gives a built-in io array implicit size and + // a user redeclaration of that array, meaning we have to substitute its implicit size here + // without actually redeclaring the array. (It is an error to use a member before the + // redeclaration, but not an error to use the array name itself.) + const TString& name = intermNode->getAsSymbolNode()->getName(); + if (name == "gl_in" || name == "gl_out") + length = getIoArrayImplicitSize(); + } + if (length == 0) { + if (isIoResizeArray(intermNode->getAsTyped()->getType())) + error(loc, "", fnCall->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); + else + error(loc, "", fnCall->getName().c_str(), "array must be declared with a size before using this method"); + } + } else + length = intermNode->getAsTyped()->getType().getArraySize(); + + if (length == 0) + length = 1; + TConstUnionArray unionArray(1); + unionArray[0].setIConst(length); + + return intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc); +} // // Do additional checking of built-in function calls that were not mapped // to built-in operations (e.g., texturing functions). @@ -2696,8 +2716,7 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, return; } } else { - // tessellation evaluation - // TODO: tessellation: semantic check these are on the in qualifier only + assert(language == EShLangTessEvaluation); // input primitive if (id == TQualifier::getGeometryString(ElgTriangles)) { @@ -2833,24 +2852,6 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); } -// -// 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, TShaderQualifiers& dst, const TShaderQualifiers& src) -{ - if (src.geometry != ElgNone) - dst.geometry = src.geometry; - if (src.invocations != 0) - dst.invocations = src.invocations; - if (src.vertices != 0) - dst.vertices = src.vertices; - if (src.pixelCenterInteger) - dst.pixelCenterInteger = src.pixelCenterInteger; - if (src.originUpperLeft) - dst.originUpperLeft = src.originUpperLeft; -} - // Merge any layout qualifier information from src into dst, leaving everything else in dst alone void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst, const TQualifier& src) { @@ -2880,6 +2881,7 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TSymbol& symbol) layoutQualifierCheck(loc, qualifier); // now, error checking combining type and qualifier + if (qualifier.hasLocation()) { switch (qualifier.storage) { case EvqVaryingIn: @@ -2903,6 +2905,7 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TSymbol& symbol) break; } default: + error(loc, "location qualifiers only appy to uniform, buffer, in, or out storage qualifiers", symbol.getName().c_str(), ""); break; } @@ -2931,6 +2934,27 @@ 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 @@ -3220,6 +3244,7 @@ TVariable* TParseContext::declareNonArray(TSourceLoc loc, TString& identifier, T // make a new variable TVariable* variable = new TVariable(&identifier, type); + ioArrayCheck(loc, type, identifier); // add variable to symbol table if (! symbolTable.insert(*variable)) { error(loc, "redefinition", variable->getName().c_str(), ""); @@ -3677,6 +3702,8 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr TType blockType(&typeList, *blockName, currentBlockQualifier); if (arraySizes) blockType.setArraySizes(arraySizes); + else + ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName); // // Don't make a user-defined type out of block name; that will cause an error @@ -3724,6 +3751,11 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr // Check for general layout qualifier errors layoutTypeCheck(loc, variable); + if (isIoResizeArray(blockType)) { + ioArraySymbolResizeList.push_back(&variable); + checkIoArraysConsistency(loc, true); + } + // Save it in the AST for linker use. intermediate.addSymbolLinkageNode(linkage, variable); } @@ -3793,21 +3825,20 @@ void TParseContext::invariantCheck(TSourceLoc loc, const TType& type, const TStr void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPublicType& publicType) { if (publicType.shaderQualifiers.vertices) { - if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) { - if (language == EShLangGeometry) - error(loc, "cannot change previously set layout value", "max_vertices", ""); - else if (language == EShLangTessControl) - error(loc, "cannot change previously set layout value", "vertices", ""); - else - assert(0); - } else if (language == EShLangTessControl) { - if (publicType.qualifier.storage != EvqVaryingOut) - error(loc, "can only apply to 'out'", "vertices", ""); - else - checkIoArraysConsistency(loc); - } + assert(language == EShLangTessControl || language == EShLangGeometry); + const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; + + if (publicType.qualifier.storage != EvqVaryingOut) + error(loc, "can only apply to 'out'", id, ""); + if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) + error(loc, "cannot change previously set layout value", id, ""); + + if (language == EShLangTessControl) + checkIoArraysConsistency(loc); } if (publicType.shaderQualifiers.invocations) { + if (publicType.qualifier.storage != EvqVaryingIn) + error(loc, "can only apply to 'in'", "invocations", ""); if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) error(loc, "cannot change previously set layout value", "invocations", ""); } @@ -3828,7 +3859,7 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); break; default: - error(loc, "does not apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); + error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); } } else if (publicType.qualifier.storage == EvqVaryingOut) { switch (publicType.shaderQualifiers.geometry) { @@ -3839,21 +3870,31 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); break; default: - error(loc, "does not apply to output", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); + error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); } } else - error(loc, "cannot be used here", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); + error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage)); } if (publicType.shaderQualifiers.spacing != EvsNone) { - if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing)) - error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); + if (publicType.qualifier.storage == EvqVaryingIn) { + if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing)) + error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); + } else + error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); } if (publicType.shaderQualifiers.order != EvoNone) { - if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order)) - error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); + if (publicType.qualifier.storage == EvqVaryingIn) { + if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order)) + error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); + } else + error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); + } + if (publicType.shaderQualifiers.pointMode) { + if (publicType.qualifier.storage == EvqVaryingIn) + intermediate.setPointMode(); + else + error(loc, "can only apply to 'in'", "point_mode", ""); } - if (publicType.shaderQualifiers.pointMode) - intermediate.setPointMode(); const TQualifier& qualifier = publicType.qualifier; @@ -3896,44 +3937,6 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub } // -// Update defaults for qualifiers when declared with a type, and optionally an identifier. -// (But, not the case of just a qualifier.) -// -void TParseContext::updateTypedDefaults(TSourceLoc loc, const TQualifier& qualifier, const TString* id) -{ - if (! id) { - if (qualifier.hasLayout()) - warn(loc, "cannot set qualifier defaults when using a type and no identifier", "", ""); - - return; - } - - switch (qualifier.storage) { - case EvqBuffer: - case EvqUniform: - if (qualifier.layoutMatrix != ElmNone) - error(loc, "cannot specify matrix layout on a variable declaration", id->c_str(), ""); - if (qualifier.layoutPacking != ElpNone) - 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 || - qualifier.layoutPacking != ElpNone) - error(loc, "layout qualifiers for matrix layout and packing only apply to uniform or buffer blocks", id->c_str(), ""); - else if (qualifier.hasLocation()) - error(loc, "location qualifiers only appy to uniform, buffer, in, or out storage qualifiers", id->c_str(), ""); - } -} - -// // Take the sequence of statements that has been built up since the last case/default, // put it on the list of top-level nodes for the current (inner-most) switch statement, // and follow that by the case/default we are on now. (See switch topology comment on @@ -4009,4 +4012,3 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression, } } // end namespace glslang -// TODO: geometry and tessellation: make sure all inputs/outputs that should have extra level of arrayness do have the extra level of arrayness \ No newline at end of file diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 3d4713b..50acbcf 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -85,7 +85,8 @@ public: void checkIndex(TSourceLoc, const TType&, int& index); void handleIndexLimits(TSourceLoc, TIntermTyped* base, TIntermTyped* index); - bool isIoResizeArray(const TType&); + bool isIoResizeArray(const TType&) const; + void ioArrayCheck(TSourceLoc, const TType&, const TString& identifier); void handleIoResizeArrayAccess(TSourceLoc, TIntermTyped* base); void checkIoArraysConsistency(TSourceLoc, bool tailOnly = false); int getIoArrayImplicitSize() const; @@ -94,7 +95,8 @@ public: TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field); TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype); TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&); - TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*, TIntermAggregate*); + TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*); + TIntermTyped* handleLengthMethod(TSourceLoc, TFunction*, TIntermNode*); void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate&); TFunction* handleConstructorCall(TSourceLoc, TPublicType&); @@ -146,7 +148,6 @@ public: void setLayoutQualifier(TSourceLoc, TPublicType&, TString&); void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int); - void mergeShaderLayoutQualifiers(TSourceLoc, TShaderQualifiers& dst, const TShaderQualifiers& src); void mergeObjectLayoutQualifiers(TSourceLoc, TQualifier& dest, const TQualifier& src); void layoutTypeCheck(TSourceLoc, const TSymbol&); void layoutQualifierCheck(TSourceLoc, const TQualifier&); @@ -165,7 +166,6 @@ public: void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&); void invariantCheck(TSourceLoc, const TType&, const TString& identifier); 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); diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 696006d..cd20b3e 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -82,7 +82,6 @@ using namespace glslang; TIntermNode* intermNode; glslang::TIntermNodePair nodePair; glslang::TIntermTyped* intermTypedNode; - glslang::TIntermAggregate* intermAggregate; }; union { glslang::TPublicType type; @@ -184,7 +183,7 @@ extern int yylex(YYSTYPE*, TParseContext&); %type translation_unit function_definition %type statement simple_statement -%type statement_list switch_statement_list compound_statement +%type statement_list switch_statement_list compound_statement %type declaration_statement selection_statement expression_statement %type switch_statement case_label %type declaration external_declaration @@ -300,7 +299,7 @@ integer_expression function_call : function_call_or_method { - $$ = parseContext.handleFunctionCall($1.loc, $1.function, $1.intermNode, $1.intermAggregate); + $$ = parseContext.handleFunctionCall($1.loc, $1.function, $1.intermNode); delete $1.function; } ; @@ -753,9 +752,9 @@ declaration // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature } | init_declarator_list SEMICOLON { - if ($1.intermAggregate) - $1.intermAggregate->setOperator(EOpSequence); - $$ = $1.intermAggregate; + if ($1.intermNode && $1.intermNode->getAsAggregate()) + $1.intermNode->getAsAggregate()->setOperator(EOpSequence); + $$ = $1.intermNode; } | PRECISION precision_qualifier type_specifier SEMICOLON { parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "precision statement"); @@ -980,42 +979,41 @@ init_declarator_list | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer { $$.type = $1.type; TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes, $6); - $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermAggregate, initNode, $5.loc); + $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $5.loc); } | init_declarator_list COMMA IDENTIFIER EQUAL initializer { $$.type = $1.type; TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, 0, $5); - $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermAggregate, initNode, $4.loc); + $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $4.loc); } ; single_declaration : fully_specified_type { $$.type = $1; - $$.intermAggregate = 0; - parseContext.updateTypedDefaults($1.loc, $$.type.qualifier, 0); + $$.intermNode = 0; + if ($$.type.qualifier.hasLayout()) + parseContext.warn($1.loc, "useless application of layout qualifier", "layout", ""); } | fully_specified_type IDENTIFIER { $$.type = $1; - $$.intermAggregate = 0; + $$.intermNode = 0; parseContext.declareVariable($2.loc, *$2.string, $1); - parseContext.updateTypedDefaults($2.loc, $$.type.qualifier, $2.string); } | fully_specified_type IDENTIFIER array_specifier { $$.type = $1; - $$.intermAggregate = 0; + $$.intermNode = 0; parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes); - parseContext.updateTypedDefaults($2.loc, $$.type.qualifier, $2.string); } | fully_specified_type IDENTIFIER array_specifier EQUAL initializer { $$.type = $1; TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes, $5); - $$.intermAggregate = parseContext.intermediate.growAggregate(0, initNode, $4.loc); + $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $4.loc); } | fully_specified_type IDENTIFIER EQUAL initializer { $$.type = $1; TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4); - $$.intermAggregate = parseContext.intermediate.growAggregate(0, initNode, $3.loc); + $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $3.loc); } // Grammar Note: No 'enum', or 'typedef'. @@ -1045,7 +1043,7 @@ fully_specified_type $2.arraySizes = 0; parseContext.checkNoShaderLayouts($2.loc, $1.shaderQualifiers); - parseContext.mergeShaderLayoutQualifiers($2.loc, $2.shaderQualifiers, $1.shaderQualifiers); + $2.shaderQualifiers.merge($1.shaderQualifiers); parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); parseContext.precisionQualifierCheck($2.loc, $2); @@ -1103,7 +1101,7 @@ layout_qualifier_id_list } | layout_qualifier_id_list COMMA layout_qualifier_id { $$ = $1; - parseContext.mergeShaderLayoutQualifiers($2.loc, $$.shaderQualifiers, $3.shaderQualifiers); + $$.shaderQualifiers.merge($3.shaderQualifiers); parseContext.mergeObjectLayoutQualifiers($2.loc, $$.qualifier, $3.qualifier); } @@ -1142,7 +1140,7 @@ type_qualifier if ($$.basicType == EbtVoid) $$.basicType = $2.basicType; - parseContext.mergeShaderLayoutQualifiers($$.loc, $$.shaderQualifiers, $2.shaderQualifiers); + $$.shaderQualifiers.merge($2.shaderQualifiers); parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false); } ; @@ -2159,8 +2157,8 @@ compound_statement --parseContext.controlFlowNestingLevel; } RIGHT_BRACE { - if ($3 != 0) - $3->setOperator(EOpSequence); + if ($3 && $3->getAsAggregate()) + $3->getAsAggregate()->setOperator(EOpSequence); $$ = $3; } ; @@ -2188,8 +2186,8 @@ compound_statement_no_new_scope $$ = 0; } | LEFT_BRACE statement_list RIGHT_BRACE { - if ($2) - $2->setOperator(EOpSequence); + if ($2 && $2->getAsAggregate()) + $2->getAsAggregate()->setOperator(EOpSequence); $$ = $2; } ; @@ -2206,7 +2204,7 @@ statement_list | statement_list statement { if ($2 && $2->getAsBranchNode() && ($2->getAsBranchNode()->getFlowOp() == EOpCase || $2->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence($1, $2); + parseContext.wrapupSwitchSubsequence($1 ? $1->getAsAggregate() : 0, $2); $$ = 0; // start a fresh subsequence for what's after this case } else $$ = parseContext.intermediate.growAggregate($1, $2); @@ -2261,7 +2259,7 @@ switch_statement parseContext.switchLevel.push_back(parseContext.controlFlowNestingLevel); } LEFT_BRACE switch_statement_list RIGHT_BRACE { - $$ = parseContext.addSwitch($1.loc, $3, $7); + $$ = parseContext.addSwitch($1.loc, $3, $7 ? $7->getAsAggregate() : 0); delete parseContext.switchSequenceStack.back(); parseContext.switchSequenceStack.pop_back(); parseContext.switchLevel.pop_back(); @@ -2422,14 +2420,14 @@ external_declaration function_definition : function_prototype { $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); - $1.intermAggregate = parseContext.handleFunctionDefinition($1.loc, *$1.function); + $1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function); } compound_statement_no_new_scope { // May be best done as post process phase on intermediate code if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) parseContext.error($1.loc, "function does not return a value:", "", $1.function->getName().c_str()); parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - $$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3); + $$ = parseContext.intermediate.growAggregate($1.intermNode, $3); parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getType(), $1.loc); $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 539a947..2ce1f1f 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -118,7 +118,7 @@ public: bool setInvocations(int i) { if (invocations > 0) - return false; + return invocations == i; invocations = i; return true; }