Link: Merge all the settings in TIntermediate.
authorJohn Kessenich <cepheus@frii.com>
Fri, 20 Jul 2018 05:10:32 +0000 (23:10 -0600)
committerJohn Kessenich <cepheus@frii.com>
Fri, 20 Jul 2018 18:34:59 +0000 (12:34 -0600)
Fixes #1309.

Test/baseResults/spv.unit1.frag.out
Test/spv.unit1.frag
Test/spv.unit2.frag
Test/spv.unit3.frag
glslang/Include/Types.h
glslang/MachineIndependent/linkValidate.cpp
glslang/MachineIndependent/localintermediate.h

index a925724..d64d437 100755 (executable)
@@ -2,60 +2,65 @@ spv.unit1.frag
 Shader version: 460
 gl_FragCoord origin is upper left
 0:? Sequence
-0:8  Function Definition: main( ( global void)
-0:8    Function Parameters: 
-0:10    Sequence
-0:10      move second child to first child ( temp highp float)
-0:10        'f' ( global highp float)
-0:10        Constant:
-0:10          10.000000
-0:11      Sequence
-0:11        move second child to first child ( temp highp float)
-0:11          'g' ( temp highp float)
-0:11          Function Call: foo( ( global highp float)
-0:12      add second child into first child ( temp highp float)
+0:10  Function Definition: main( ( global void)
+0:10    Function Parameters: 
+0:12    Sequence
+0:12      move second child to first child ( temp highp float)
 0:12        'f' ( global highp float)
-0:12        'g' ( temp highp float)
-0:13      add second child into first child ( temp highp float)
-0:13        'f' ( global highp float)
-0:13        direct index ( temp highp float)
-0:13          'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
-0:13          Constant:
-0:13            1 (const int)
+0:12        Constant:
+0:12          10.000000
+0:13      Sequence
+0:13        move second child to first child ( temp highp float)
+0:13          'g' ( temp highp float)
+0:13          Function Call: foo( ( global highp float)
+0:14      add second child into first child ( temp highp float)
+0:14        'f' ( global highp float)
+0:14        'g' ( temp highp float)
+0:15      add second child into first child ( temp highp float)
+0:15        'f' ( global highp float)
+0:15        direct index ( temp highp float)
+0:15          'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
+0:15          Constant:
+0:15            1 (const int)
 0:?   Linker Objects
 0:?     'f' ( global highp float)
 0:?     'a1' ( global highp float)
+0:?     'cout' ( out highp float)
 
 spv.unit2.frag
 Shader version: 410
 gl_FragCoord origin is upper left
 0:? Sequence
-0:9  Function Definition: foo( ( global highp float)
-0:9    Function Parameters: 
-0:11    Sequence
-0:11      Sequence
-0:11        move second child to first child ( temp highp float)
-0:11          'h2' ( temp highp float)
-0:11          component-wise multiply ( temp highp float)
-0:11            Constant:
-0:11              2.000000
-0:11            'f' ( global highp float)
-0:12      Sequence
-0:12        move second child to first child ( temp highp float)
-0:12          'g2' ( temp highp float)
-0:12          Function Call: bar( ( global highp float)
-0:13      Branch: Return with expression
-0:13        add ( temp highp float)
-0:13          add ( temp highp float)
-0:13            'h2' ( temp highp float)
-0:13            'g2' ( temp highp float)
-0:13          direct index ( temp highp float)
-0:13            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
-0:13            Constant:
-0:13              1 (const int)
+0:12  Function Definition: foo( ( global highp float)
+0:12    Function Parameters: 
+0:14    Sequence
+0:14      Sequence
+0:14        move second child to first child ( temp highp float)
+0:14          'h2' ( temp highp float)
+0:14          add ( temp highp float)
+0:14            component-wise multiply ( temp highp float)
+0:14              Constant:
+0:14                2.000000
+0:14              'f' ( global highp float)
+0:14            'cin' ( smooth in highp float)
+0:15      Sequence
+0:15        move second child to first child ( temp highp float)
+0:15          'g2' ( temp highp float)
+0:15          Function Call: bar( ( global highp float)
+0:16      Branch: Return with expression
+0:16        add ( temp highp float)
+0:16          add ( temp highp float)
+0:16            'h2' ( temp highp float)
+0:16            'g2' ( temp highp float)
+0:16          direct index ( temp highp float)
+0:16            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
+0:16            Constant:
+0:16              1 (const int)
 0:?   Linker Objects
 0:?     'a2' ( global highp float)
 0:?     'f' ( global highp float)
+0:?     'cout' ( out highp float)
+0:?     'cin' ( smooth in highp float)
 
 spv.unit3.frag
 Shader version: 460
@@ -66,31 +71,36 @@ gl_FragCoord origin is upper left
 0:4      'h3' ( global highp float)
 0:4      Constant:
 0:4        3.000000
-0:6  Function Definition: bar( ( global highp float)
-0:6    Function Parameters: 
-0:8    Sequence
-0:8      multiply second child into first child ( temp highp float)
-0:8        'h3' ( global highp float)
-0:8        'f' ( global highp float)
-0:9      Sequence
-0:9        move second child to first child ( temp highp float)
-0:9          'g3' ( temp highp float)
-0:9          component-wise multiply ( temp highp float)
-0:9            Constant:
-0:9              2.000000
-0:9            'h3' ( global highp float)
-0:10      Branch: Return with expression
-0:10        add ( temp highp float)
-0:10          add ( temp highp float)
-0:10            'h3' ( global highp float)
-0:10            'g3' ( temp highp float)
-0:10          direct index ( temp highp float)
-0:10            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
-0:10            Constant:
-0:10              1 (const int)
+0:9  Function Definition: bar( ( global highp float)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      multiply second child into first child ( temp highp float)
+0:11        'h3' ( global highp float)
+0:11        'f' ( global highp float)
+0:12      Sequence
+0:12        move second child to first child ( temp highp float)
+0:12          'g3' ( temp highp float)
+0:12          component-wise multiply ( temp highp float)
+0:12            Constant:
+0:12              2.000000
+0:12            'h3' ( global highp float)
+0:13      move second child to first child ( temp highp float)
+0:13        'cout' ( out highp float)
+0:13        'g3' ( temp highp float)
+0:14      Branch: Return with expression
+0:14        add ( temp highp float)
+0:14          add ( temp highp float)
+0:14            'h3' ( global highp float)
+0:14            'g3' ( temp highp float)
+0:14          direct index ( temp highp float)
+0:14            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
+0:14            Constant:
+0:14              1 (const int)
 0:?   Linker Objects
 0:?     'f' ( global highp float)
 0:?     'h3' ( global highp float)
+0:?     'cout' ( out highp float)
+0:?     'cin' ( smooth in highp float)
 
 
 Linked fragment stage:
@@ -99,90 +109,97 @@ Linked fragment stage:
 Shader version: 460
 gl_FragCoord origin is upper left
 0:? Sequence
-0:8  Function Definition: main( ( global void)
-0:8    Function Parameters: 
-0:10    Sequence
-0:10      move second child to first child ( temp highp float)
-0:10        'f' ( global highp float)
-0:10        Constant:
-0:10          10.000000
-0:11      Sequence
-0:11        move second child to first child ( temp highp float)
-0:11          'g' ( temp highp float)
-0:11          Function Call: foo( ( global highp float)
-0:12      add second child into first child ( temp highp float)
+0:10  Function Definition: main( ( global void)
+0:10    Function Parameters: 
+0:12    Sequence
+0:12      move second child to first child ( temp highp float)
 0:12        'f' ( global highp float)
-0:12        'g' ( temp highp float)
-0:13      add second child into first child ( temp highp float)
-0:13        'f' ( global highp float)
-0:13        direct index ( temp highp float)
-0:13          'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
-0:13          Constant:
-0:13            1 (const int)
-0:9  Function Definition: foo( ( global highp float)
-0:9    Function Parameters: 
-0:11    Sequence
-0:11      Sequence
-0:11        move second child to first child ( temp highp float)
-0:11          'h2' ( temp highp float)
-0:11          component-wise multiply ( temp highp float)
-0:11            Constant:
-0:11              2.000000
-0:11            'f' ( global highp float)
-0:12      Sequence
-0:12        move second child to first child ( temp highp float)
-0:12          'g2' ( temp highp float)
-0:12          Function Call: bar( ( global highp float)
-0:13      Branch: Return with expression
-0:13        add ( temp highp float)
-0:13          add ( temp highp float)
-0:13            'h2' ( temp highp float)
-0:13            'g2' ( temp highp float)
-0:13          direct index ( temp highp float)
-0:13            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
-0:13            Constant:
-0:13              1 (const int)
+0:12        Constant:
+0:12          10.000000
+0:13      Sequence
+0:13        move second child to first child ( temp highp float)
+0:13          'g' ( temp highp float)
+0:13          Function Call: foo( ( global highp float)
+0:14      add second child into first child ( temp highp float)
+0:14        'f' ( global highp float)
+0:14        'g' ( temp highp float)
+0:15      add second child into first child ( temp highp float)
+0:15        'f' ( global highp float)
+0:15        direct index ( temp highp float)
+0:15          'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
+0:15          Constant:
+0:15            1 (const int)
+0:12  Function Definition: foo( ( global highp float)
+0:12    Function Parameters: 
+0:14    Sequence
+0:14      Sequence
+0:14        move second child to first child ( temp highp float)
+0:14          'h2' ( temp highp float)
+0:14          add ( temp highp float)
+0:14            component-wise multiply ( temp highp float)
+0:14              Constant:
+0:14                2.000000
+0:14              'f' ( global highp float)
+0:14            'cin' ( smooth in highp float)
+0:15      Sequence
+0:15        move second child to first child ( temp highp float)
+0:15          'g2' ( temp highp float)
+0:15          Function Call: bar( ( global highp float)
+0:16      Branch: Return with expression
+0:16        add ( temp highp float)
+0:16          add ( temp highp float)
+0:16            'h2' ( temp highp float)
+0:16            'g2' ( temp highp float)
+0:16          direct index ( temp highp float)
+0:16            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
+0:16            Constant:
+0:16              1 (const int)
 0:4  Sequence
 0:4    move second child to first child ( temp highp float)
 0:4      'h3' ( global highp float)
 0:4      Constant:
 0:4        3.000000
-0:6  Function Definition: bar( ( global highp float)
-0:6    Function Parameters: 
-0:8    Sequence
-0:8      multiply second child into first child ( temp highp float)
-0:8        'h3' ( global highp float)
-0:8        'f' ( global highp float)
-0:9      Sequence
-0:9        move second child to first child ( temp highp float)
-0:9          'g3' ( temp highp float)
-0:9          component-wise multiply ( temp highp float)
-0:9            Constant:
-0:9              2.000000
-0:9            'h3' ( global highp float)
-0:10      Branch: Return with expression
-0:10        add ( temp highp float)
-0:10          add ( temp highp float)
-0:10            'h3' ( global highp float)
-0:10            'g3' ( temp highp float)
-0:10          direct index ( temp highp float)
-0:10            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
-0:10            Constant:
-0:10              1 (const int)
+0:9  Function Definition: bar( ( global highp float)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      multiply second child into first child ( temp highp float)
+0:11        'h3' ( global highp float)
+0:11        'f' ( global highp float)
+0:12      Sequence
+0:12        move second child to first child ( temp highp float)
+0:12          'g3' ( temp highp float)
+0:12          component-wise multiply ( temp highp float)
+0:12            Constant:
+0:12              2.000000
+0:12            'h3' ( global highp float)
+0:13      move second child to first child ( temp highp float)
+0:13        'cout' ( out highp float)
+0:13        'g3' ( temp highp float)
+0:14      Branch: Return with expression
+0:14        add ( temp highp float)
+0:14          add ( temp highp float)
+0:14            'h3' ( global highp float)
+0:14            'g3' ( temp highp float)
+0:14          direct index ( temp highp float)
+0:14            'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
+0:14            Constant:
+0:14              1 (const int)
 0:?   Linker Objects
 0:?     'f' ( global highp float)
 0:?     'a1' ( global highp float)
+0:?     'cout' ( out highp float)
 0:?     'a2' ( global highp float)
+0:?     'cin' ( smooth in highp float)
 0:?     'h3' ( global highp float)
 
 // Module Version 10000
 // Generated by (magic number): 80007
-// Id's are bound by 63
+// Id's are bound by 69
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Fragment 4  "main" 25
+                              EntryPoint Fragment 4  "main" 25 37 57
                               ExecutionMode 4 OriginUpperLeft
                               Source GLSL 460
                               Name 4  "main"
@@ -193,10 +210,12 @@ gl_FragCoord origin is upper left
                               Name 18  "g"
                               Name 25  "gl_FragCoord"
                               Name 33  "h2"
-                              Name 37  "g2"
-                              Name 50  "g3"
-                              Name 61  "a1"
-                              Name 62  "a2"
+                              Name 37  "cin"
+                              Name 40  "g2"
+                              Name 53  "g3"
+                              Name 57  "cout"
+                              Name 67  "a1"
+                              Name 68  "a2"
                               Decorate 25(gl_FragCoord) BuiltIn FragCoord
                2:             TypeVoid
                3:             TypeFunction 2
@@ -215,8 +234,11 @@ gl_FragCoord origin is upper left
               27:     26(int) Constant 1
               28:             TypePointer Input 6(float)
               34:    6(float) Constant 1073741824
-          61(a1):     12(ptr) Variable Private
-          62(a2):     12(ptr) Variable Private
+         37(cin):     28(ptr) Variable Input
+              56:             TypePointer Output 6(float)
+        57(cout):     56(ptr) Variable Output
+          67(a1):     12(ptr) Variable Private
+          68(a2):     12(ptr) Variable Private
          4(main):           2 Function None 3
                5:             Label
            18(g):     17(ptr) Variable Function
@@ -238,35 +260,39 @@ gl_FragCoord origin is upper left
          8(foo():    6(float) Function None 7
                9:             Label
           33(h2):     17(ptr) Variable Function
-          37(g2):     17(ptr) Variable Function
+          40(g2):     17(ptr) Variable Function
               35:    6(float) Load 15(f)
               36:    6(float) FMul 34 35
-                              Store 33(h2) 36
-              38:    6(float) FunctionCall 10(bar()
-                              Store 37(g2) 38
-              39:    6(float) Load 33(h2)
-              40:    6(float) Load 37(g2)
-              41:    6(float) FAdd 39 40
-              42:     28(ptr) AccessChain 25(gl_FragCoord) 27
-              43:    6(float) Load 42
-              44:    6(float) FAdd 41 43
-                              ReturnValue 44
+              38:    6(float) Load 37(cin)
+              39:    6(float) FAdd 36 38
+                              Store 33(h2) 39
+              41:    6(float) FunctionCall 10(bar()
+                              Store 40(g2) 41
+              42:    6(float) Load 33(h2)
+              43:    6(float) Load 40(g2)
+              44:    6(float) FAdd 42 43
+              45:     28(ptr) AccessChain 25(gl_FragCoord) 27
+              46:    6(float) Load 45
+              47:    6(float) FAdd 44 46
+                              ReturnValue 47
                               FunctionEnd
         10(bar():    6(float) Function None 7
               11:             Label
-          50(g3):     17(ptr) Variable Function
-              47:    6(float) Load 15(f)
-              48:    6(float) Load 13(h3)
-              49:    6(float) FMul 48 47
-                              Store 13(h3) 49
+          53(g3):     17(ptr) Variable Function
+              50:    6(float) Load 15(f)
               51:    6(float) Load 13(h3)
-              52:    6(float) FMul 34 51
-                              Store 50(g3) 52
-              53:    6(float) Load 13(h3)
-              54:    6(float) Load 50(g3)
-              55:    6(float) FAdd 53 54
-              56:     28(ptr) AccessChain 25(gl_FragCoord) 27
-              57:    6(float) Load 56
-              58:    6(float) FAdd 55 57
-                              ReturnValue 58
+              52:    6(float) FMul 51 50
+                              Store 13(h3) 52
+              54:    6(float) Load 13(h3)
+              55:    6(float) FMul 34 54
+                              Store 53(g3) 55
+              58:    6(float) Load 53(g3)
+                              Store 57(cout) 58
+              59:    6(float) Load 13(h3)
+              60:    6(float) Load 53(g3)
+              61:    6(float) FAdd 59 60
+              62:     28(ptr) AccessChain 25(gl_FragCoord) 27
+              63:    6(float) Load 62
+              64:    6(float) FAdd 61 63
+                              ReturnValue 64
                               FunctionEnd
index f6c7850..d84f821 100755 (executable)
@@ -5,6 +5,8 @@ float a1;
 
 float foo();
 
+out float cout;
+
 void main()
 {
     f = 10;
index 6a6d528..d17e7e7 100755 (executable)
@@ -6,9 +6,12 @@ float f;
 
 float bar();
 
+out float cout;
+in float cin;
+
 float foo()
 {
-    float h2 = 2 * f;
+    float h2 = 2 * f + cin;
     float g2 = bar();
     return h2 + g2 + gl_FragCoord.y;
 }
\ No newline at end of file
index 0ab667c..4c96597 100755 (executable)
@@ -3,9 +3,13 @@
 float f;
 float h3 = 3.0;
 
+out float cout;
+in float cin;
+
 float bar()
 {
     h3 *= f;
     float g3 = 2 * h3;
+    cout = g3;
     return h3 + g3 + gl_FragCoord.y;
 }
index 2b0c7a1..b877c15 100755 (executable)
@@ -616,6 +616,22 @@ public:
         }
     }
 
+    // non-built-in symbols that might link between compilation units
+    bool isLinkable() const
+    {
+        switch (storage) {
+        case EvqGlobal:
+        case EvqVaryingIn:
+        case EvqVaryingOut:
+        case EvqUniform:
+        case EvqBuffer:
+        case EvqShared:
+            return true;
+        default:
+            return false;
+        }
+    }
+
     // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
     bool isArrayedIo(EShLanguage language) const
     {
index f99b5da..5089062 100755 (executable)
@@ -77,12 +77,13 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message)
 //
 void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 {
-    if (source == EShSourceNone)
-        source = unit.source;
-
-    if (source != unit.source)
-        error(infoSink, "can't link compilation units from different source languages");
+    mergeCallGraphs(infoSink, unit);
+    mergeModes(infoSink, unit);
+    mergeTrees(infoSink, unit);
+}
 
+void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
+{
     if (unit.getNumEntryPoints() > 0) {
         if (getNumEntryPoints() > 0)
             error(infoSink, "can't handle multiple entry points per stage");
@@ -92,35 +93,50 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
         }
     }
     numEntryPoints += unit.getNumEntryPoints();
-    numErrors += unit.getNumErrors();
-    numPushConstants += unit.numPushConstants;
+
     callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
+}
 
-    if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
-        error(infoSink, "gl_FragCoord redeclarations must match across shaders");
+#define MERGE_MAX(member) member = std::max(member, unit.member)
+#define MERGE_TRUE(member) if (unit.member) member = unit.member;
 
-    if (! earlyFragmentTests)
-        earlyFragmentTests = unit.earlyFragmentTests;
+void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
+{
+    if (language != unit.language)
+        error(infoSink, "stages must match when linking into a single stage");
 
-    if (!postDepthCoverage)
-        postDepthCoverage = unit.postDepthCoverage;
+    if (source == EShSourceNone)
+        source = unit.source;
+    if (source != unit.source)
+        error(infoSink, "can't link compilation units from different source languages");
 
-    if (depthLayout == EldNone)
-        depthLayout = unit.depthLayout;
-    else if (depthLayout != unit.depthLayout)
-        error(infoSink, "Contradictory depth layouts");
+    if (treeRoot == nullptr) {
+        profile = unit.profile;
+        version = unit.version;
+        requestedExtensions = unit.requestedExtensions;
+    } else {
+        if ((profile == EEsProfile) != (unit.profile == EEsProfile))
+            error(infoSink, "Cannot cross link ES and desktop profiles");
+        else if (unit.profile == ECompatibilityProfile)
+            profile = ECompatibilityProfile;
+        version = std::max(version, unit.version);
+        requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
+    }
 
-    blendEquations |= unit.blendEquations;
+    MERGE_MAX(spvVersion.spv);
+    MERGE_MAX(spvVersion.vulkanGlsl);
+    MERGE_MAX(spvVersion.vulkan);
+    MERGE_MAX(spvVersion.openGl);
 
-    if (inputPrimitive == ElgNone)
-        inputPrimitive = unit.inputPrimitive;
-    else if (inputPrimitive != unit.inputPrimitive)
-        error(infoSink, "Contradictory input layout primitives");
+    numErrors += unit.getNumErrors();
+    numPushConstants += unit.numPushConstants;
 
-    if (outputPrimitive == ElgNone)
-        outputPrimitive = unit.outputPrimitive;
-    else if (outputPrimitive != unit.outputPrimitive)
-        error(infoSink, "Contradictory output layout primitives");
+    if (unit.invocations != TQualifier::layoutNotSet) {
+        if (invocations == TQualifier::layoutNotSet)
+            invocations = unit.invocations;
+        else if (invocations != unit.invocations)
+            error(infoSink, "number of invocations must match between compilation units");
+    }
 
     if (vertices == TQualifier::layoutNotSet)
         vertices = unit.vertices;
@@ -133,6 +149,19 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
             assert(0);
     }
 
+    if (inputPrimitive == ElgNone)
+        inputPrimitive = unit.inputPrimitive;
+    else if (inputPrimitive != unit.inputPrimitive)
+        error(infoSink, "Contradictory input layout primitives");
+
+    if (outputPrimitive == ElgNone)
+        outputPrimitive = unit.outputPrimitive;
+    else if (outputPrimitive != unit.outputPrimitive)
+        error(infoSink, "Contradictory output layout primitives");
+
+    if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
+        error(infoSink, "gl_FragCoord redeclarations must match across shaders");
+
     if (vertexSpacing == EvsNone)
         vertexSpacing = unit.vertexSpacing;
     else if (vertexSpacing != unit.vertexSpacing)
@@ -143,8 +172,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
     else if (vertexOrder != unit.vertexOrder)
         error(infoSink, "Contradictory triangle ordering");
 
-    if (unit.pointMode)
-        pointMode = true;
+    MERGE_TRUE(pointMode);
 
     for (int i = 0; i < 3; ++i) {
         if (localSize[i] > 1)
@@ -158,8 +186,21 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
             error(infoSink, "Contradictory local size specialization ids");
     }
 
-    if (unit.xfbMode)
-        xfbMode = true;
+    MERGE_TRUE(earlyFragmentTests);
+    MERGE_TRUE(postDepthCoverage);
+
+    if (depthLayout == EldNone)
+        depthLayout = unit.depthLayout;
+    else if (depthLayout != unit.depthLayout)
+        error(infoSink, "Contradictory depth layouts");
+
+    MERGE_TRUE(depthReplacing);
+    MERGE_TRUE(hlslFunctionality1);
+
+    blendEquations |= unit.blendEquations;
+
+    MERGE_TRUE(xfbMode);
+
     for (size_t b = 0; b < xfbBuffers.size(); ++b) {
         if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
             xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
@@ -171,22 +212,40 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
         // TODO: 4.4 link: enhanced layouts: compare ranges
     }
 
-    if (unit.treeRoot == 0)
-        return;
+    MERGE_TRUE(multiStream);
 
-    if (treeRoot == 0) {
-        treeRoot = unit.treeRoot;
-        version = unit.version;
-        requestedExtensions = unit.requestedExtensions;
-        return;
+#ifdef NV_EXTENSIONS
+    MERGE_TRUE(layoutOverrideCoverage);
+    MERGE_TRUE(geoPassthroughEXT);
+#endif
+
+    for (unsigned int i = 0; i < unit.shiftBinding.size(); ++i) {
+        if (unit.shiftBinding[i] > 0)
+            setShiftBinding((TResourceType)i, unit.shiftBinding[i]);
     }
 
-    // Getting this far means we have two existing trees to merge...
-    mergeTree(infoSink, unit);
+    for (unsigned int i = 0; i < unit.shiftBindingForSet.size(); ++i) {
+        for (auto it = unit.shiftBindingForSet[i].begin(); it != unit.shiftBindingForSet[i].end(); ++it)
+            setShiftBindingForSet((TResourceType)i, it->second, it->first);
+    }
 
-    version = std::max(version, unit.version);
-    requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
-    ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
+    resourceSetBinding.insert(resourceSetBinding.end(), unit.resourceSetBinding.begin(), unit.resourceSetBinding.end());
+
+    MERGE_TRUE(autoMapBindings);
+    MERGE_TRUE(autoMapLocations);
+    MERGE_TRUE(invertY);
+    MERGE_TRUE(flattenUniformArrays);
+    MERGE_TRUE(useUnknownFormat);
+    MERGE_TRUE(hlslOffsets);
+    MERGE_TRUE(useStorageBuffer);
+    MERGE_TRUE(hlslIoMapping);
+
+    // TODO: sourceFile
+    // TODO: sourceText
+    // TODO: processes
+
+    MERGE_TRUE(needToLegalize);
+    MERGE_TRUE(binaryDoubleOutput);
 }
 
 //
@@ -195,8 +254,18 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 // and might have overlaps that are not the same symbol, or might have different
 // IDs for what should be the same shared symbol.
 //
-void TIntermediate::mergeTree(TInfoSink& infoSink, TIntermediate& unit)
+void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
 {
+    if (unit.treeRoot == nullptr)
+        return;
+
+    if (treeRoot == nullptr) {
+        treeRoot = unit.treeRoot;
+        return;
+    }
+
+    // Getting this far means we have two existing trees to merge...
+
     // Get the top-level globals of each unit
     TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
     TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
@@ -214,6 +283,7 @@ void TIntermediate::mergeTree(TInfoSink& infoSink, TIntermediate& unit)
 
     mergeBodies(infoSink, globals, unitGlobals);
     mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
+    ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
 }
 
 // Traverser that seeds an ID map with all built-ins, and tracks the
@@ -240,7 +310,7 @@ protected:
     int maxId;
 };
 
-// Traverser that seeds an ID map with non-builtin globals.
+// Traverser that seeds an ID map with non-builtins.
 // (It would be nice to put this in a function, but that causes warnings
 // on having no bodies for the copy-constructor/operator=.)
 class TUserIdTraverser : public TIntermTraverser {
@@ -250,7 +320,7 @@ public:
     virtual void visitSymbol(TIntermSymbol* symbol)
     {
         const TQualifier& qualifier = symbol->getType().getQualifier();
-        if (qualifier.storage == EvqGlobal && qualifier.builtIn == EbvNone)
+        if (qualifier.builtIn == EbvNone)
             idMap[symbol->getName()] = symbol->getId();
     }
 
@@ -286,7 +356,7 @@ public:
     {
         const TQualifier& qualifier = symbol->getType().getQualifier();
         bool remapped = false;
-        if (qualifier.storage == EvqGlobal || qualifier.builtIn != EbvNone) {
+        if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
             auto it = idMap.find(symbol->getName());
             if (it != idMap.end()) {
                 symbol->changeId(it->second);
index e593fcd..9cbc4c8 100755 (executable)
@@ -645,7 +645,9 @@ protected:
     TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
     void error(TInfoSink& infoSink, const char*);
     void warn(TInfoSink& infoSink, const char*);
-    void mergeTree(TInfoSink&, TIntermediate&);
+    void mergeCallGraphs(TInfoSink&, TIntermediate&);
+    void mergeModes(TInfoSink&, TIntermediate&);
+    void mergeTrees(TInfoSink&, TIntermediate&);
     void seedIdMap(TMap<TString, int>& idMap, int& maxId);
     void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
@@ -677,6 +679,8 @@ protected:
     EShSource source;            // source language, known a bit later
     std::string entryPointName;
     std::string entryPointMangledName;
+    typedef std::list<TCall> TGraph;
+    TGraph callGraph;
 
     EProfile profile;                           // source profile
     int version;                                // source version
@@ -706,6 +710,7 @@ protected:
     bool hlslFunctionality1;
     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
     bool xfbMode;
+    std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
     bool multiStream;
 
 #ifdef NV_EXTENSIONS
@@ -717,7 +722,7 @@ protected:
     std::array<unsigned int, EResCount> shiftBinding;
 
     // Per-descriptor-set shift values
-    std::array<std::map<int, int>, EResCount>  shiftBindingForSet;
+    std::array<std::map<int, int>, EResCount> shiftBindingForSet;
 
     std::vector<std::string> resourceSetBinding;
     bool autoMapBindings;
@@ -729,13 +734,9 @@ protected:
     bool useStorageBuffer;
     bool hlslIoMapping;
 
-    typedef std::list<TCall> TGraph;
-    TGraph callGraph;
-
     std::set<TString> ioAccessed;           // set of names of statically read/written I/O that might need extra checking
     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
-    std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
     std::unordered_set<int> usedConstantId; // specialization constant ids used
     std::set<TString> semanticNameSet;