Merge pull request #1595 from dgkoch/EXT_fragment_invocation_density

Implement GL_EXT_fragment_invocation_density
diff --git a/SPIRV/GLSL.ext.EXT.h b/SPIRV/GLSL.ext.EXT.h
index c4a2430..e29c055 100644
--- a/SPIRV/GLSL.ext.EXT.h
+++ b/SPIRV/GLSL.ext.EXT.h
@@ -28,10 +28,11 @@
 #define GLSLextEXT_H
 
 static const int GLSLextEXTVersion = 100;
-static const int GLSLextEXTRevision = 1;
+static const int GLSLextEXTRevision = 2;
 
 static const char* const E_SPV_EXT_shader_stencil_export        = "SPV_EXT_shader_stencil_export";
 static const char* const E_SPV_EXT_shader_viewport_index_layer  = "SPV_EXT_shader_viewport_index_layer";
 static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
+static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
 
 #endif  // #ifndef GLSLextEXT_H
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 2e2a2fe..5c00024 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -833,6 +833,16 @@
         builder.addCapability(spv::CapabilityMultiView);
         return spv::BuiltInViewIndex;
 
+    case glslang::EbvFragSizeEXT:
+        builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density);
+        builder.addCapability(spv::CapabilityFragmentDensityEXT);
+        return spv::BuiltInFragSizeEXT;
+
+    case glslang::EbvFragInvocationCountEXT:
+        builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density);
+        builder.addCapability(spv::CapabilityFragmentDensityEXT);
+        return spv::BuiltInFragInvocationCountEXT;
+
 #ifdef NV_EXTENSIONS
     case glslang::EbvViewportMaskNV:
         if (!memberDeclaration) {
diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp
index 4f7c198..b0b01fb 100644
--- a/SPIRV/doc.cpp
+++ b/SPIRV/doc.cpp
@@ -388,12 +388,15 @@
     case BuiltInSecondaryViewportMaskNV:    return "SecondaryViewportMaskNV";
     case BuiltInPositionPerViewNV:          return "PositionPerViewNV";
     case BuiltInViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
-    case BuiltInFragmentSizeNV:             return "FragmentSizeNV";
-    case BuiltInInvocationsPerPixelNV:      return "InvocationsPerPixelNV";
+//    case BuiltInFragmentSizeNV:             return "FragmentSizeNV";        // superseded by BuiltInFragSizeEXT
+//    case BuiltInInvocationsPerPixelNV:      return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
     case BuiltInBaryCoordNV:                return "BaryCoordNV";
     case BuiltInBaryCoordNoPerspNV:         return "BaryCoordNoPerspNV";
 #endif
 
+    case BuiltInFragSizeEXT:                return "FragSizeEXT";
+    case BuiltInFragInvocationCountEXT:     return "FragInvocationCountEXT";
+
     case 5264: return "FullyCoveredEXT";
 
 
@@ -897,8 +900,9 @@
     case CapabilityComputeDerivativeGroupLinearNV:  return "ComputeDerivativeGroupLinearNV";
     case CapabilityFragmentBarycentricNV:           return "FragmentBarycentricNV";
     case CapabilityMeshShadingNV:                   return "MeshShadingNV";
-    case CapabilityShadingRateNV:                   return "ShadingRateNV";
+//    case CapabilityShadingRateNV:                   return "ShadingRateNV";  // superseded by CapabilityFragmentDensityEXT
 #endif
+    case CapabilityFragmentDensityEXT:              return "FragmentDensityEXT";
 
     case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT";
 
diff --git a/Test/baseResults/spv.fragmentDensity-es.frag.out b/Test/baseResults/spv.fragmentDensity-es.frag.out
new file mode 100644
index 0000000..01ac383
--- /dev/null
+++ b/Test/baseResults/spv.fragmentDensity-es.frag.out
@@ -0,0 +1,45 @@
+spv.fragmentDensity-es.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 18
+
+                              Capability Shader
+                              Capability FragmentDensityEXT
+                              Extension  "SPV_EXT_fragment_invocation_density"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 9 11 14 16
+                              ExecutionMode 4 OriginUpperLeft
+                              Source ESSL 310
+                              SourceExtension  "GL_EXT_fragment_invocation_density"
+                              Name 4  "main"
+                              Name 9  "FragSize"
+                              Name 11  "gl_FragSizeEXT"
+                              Name 14  "FragInvocationCount"
+                              Name 16  "gl_FragInvocationCountEXT"
+                              Decorate 9(FragSize) Location 0
+                              Decorate 11(gl_FragSizeEXT) Flat
+                              Decorate 11(gl_FragSizeEXT) BuiltIn FragSizeEXT
+                              Decorate 14(FragInvocationCount) Location 2
+                              Decorate 16(gl_FragInvocationCountEXT) Flat
+                              Decorate 16(gl_FragInvocationCountEXT) BuiltIn FragInvocationCountEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypeVector 6(int) 2
+               8:             TypePointer Output 7(ivec2)
+     9(FragSize):      8(ptr) Variable Output
+              10:             TypePointer Input 7(ivec2)
+11(gl_FragSizeEXT):     10(ptr) Variable Input
+              13:             TypePointer Output 6(int)
+14(FragInvocationCount):     13(ptr) Variable Output
+              15:             TypePointer Input 6(int)
+16(gl_FragInvocationCountEXT):     15(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+              12:    7(ivec2) Load 11(gl_FragSizeEXT)
+                              Store 9(FragSize) 12
+              17:      6(int) Load 16(gl_FragInvocationCountEXT)
+                              Store 14(FragInvocationCount) 17
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.fragmentDensity-neg.frag.out b/Test/baseResults/spv.fragmentDensity-neg.frag.out
new file mode 100644
index 0000000..6b5078b
--- /dev/null
+++ b/Test/baseResults/spv.fragmentDensity-neg.frag.out
@@ -0,0 +1,7 @@
+spv.fragmentDensity-neg.frag
+ERROR: 0:10: 'gl_FragSizeEXT' : required extension not requested: GL_EXT_fragment_invocation_density
+ERROR: 0:11: 'gl_FragInvocationCountEXT' : required extension not requested: GL_EXT_fragment_invocation_density
+ERROR: 2 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/Test/baseResults/spv.fragmentDensity.frag.out b/Test/baseResults/spv.fragmentDensity.frag.out
new file mode 100644
index 0000000..8bbc37c
--- /dev/null
+++ b/Test/baseResults/spv.fragmentDensity.frag.out
@@ -0,0 +1,48 @@
+spv.fragmentDensity.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 21
+
+                              Capability Shader
+                              Capability FragmentDensityEXT
+                              Extension  "SPV_EXT_fragment_invocation_density"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 9 13 17 19
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_fragment_invocation_density"
+                              Name 4  "main"
+                              Name 9  "FragSize"
+                              Name 13  "gl_FragSizeEXT"
+                              Name 17  "FragInvocationCount"
+                              Name 19  "gl_FragInvocationCountEXT"
+                              Decorate 9(FragSize) Location 0
+                              Decorate 13(gl_FragSizeEXT) Flat
+                              Decorate 13(gl_FragSizeEXT) BuiltIn FragSizeEXT
+                              Decorate 17(FragInvocationCount) Location 2
+                              Decorate 19(gl_FragInvocationCountEXT) Flat
+                              Decorate 19(gl_FragInvocationCountEXT) BuiltIn FragInvocationCountEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 2
+               8:             TypePointer Output 7(fvec2)
+     9(FragSize):      8(ptr) Variable Output
+              10:             TypeInt 32 1
+              11:             TypeVector 10(int) 2
+              12:             TypePointer Input 11(ivec2)
+13(gl_FragSizeEXT):     12(ptr) Variable Input
+              16:             TypePointer Output 10(int)
+17(FragInvocationCount):     16(ptr) Variable Output
+              18:             TypePointer Input 10(int)
+19(gl_FragInvocationCountEXT):     18(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+              14:   11(ivec2) Load 13(gl_FragSizeEXT)
+              15:    7(fvec2) ConvertSToF 14
+                              Store 9(FragSize) 15
+              20:     10(int) Load 19(gl_FragInvocationCountEXT)
+                              Store 17(FragInvocationCount) 20
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.fragmentDensity.vert.out b/Test/baseResults/spv.fragmentDensity.vert.out
new file mode 100644
index 0000000..ff77a3e
--- /dev/null
+++ b/Test/baseResults/spv.fragmentDensity.vert.out
@@ -0,0 +1,9 @@
+spv.fragmentDensity.vert
+ERROR: 0:10: 'gl_FragSizeEXT' : undeclared identifier 
+ERROR: 0:10: 'assign' :  cannot convert from ' temp float' to 'layout( location=0) smooth out highp 2-component vector of uint'
+ERROR: 0:11: 'gl_FragInvocationCountEXT' : undeclared identifier 
+ERROR: 0:11: 'assign' :  cannot convert from ' temp float' to 'layout( location=2) smooth out highp int'
+ERROR: 4 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/Test/baseResults/spv.shadingRate.frag.out b/Test/baseResults/spv.shadingRate.frag.out
index 2b6bd31..1147776 100644
--- a/Test/baseResults/spv.shadingRate.frag.out
+++ b/Test/baseResults/spv.shadingRate.frag.out
@@ -4,7 +4,7 @@
 // Id's are bound by 21
 
                               Capability Shader
-                              Capability ShadingRateNV
+                              Capability FragmentDensityEXT
                               Extension  "SPV_NV_shading_rate"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
@@ -19,10 +19,10 @@
                               Name 19  "gl_InvocationsPerPixelNV"
                               Decorate 9(FragmentSize) Location 0
                               Decorate 13(gl_FragmentSizeNV) Flat
-                              Decorate 13(gl_FragmentSizeNV) BuiltIn FragmentSizeNV
+                              Decorate 13(gl_FragmentSizeNV) BuiltIn FragSizeEXT
                               Decorate 17(InvocationsPerPixel) Location 2
                               Decorate 19(gl_InvocationsPerPixelNV) Flat
-                              Decorate 19(gl_InvocationsPerPixelNV) BuiltIn InvocationsPerPixelNV
+                              Decorate 19(gl_InvocationsPerPixelNV) BuiltIn FragInvocationCountEXT
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
diff --git a/Test/spv.fragmentDensity-es.frag b/Test/spv.fragmentDensity-es.frag
new file mode 100644
index 0000000..35fb96e
--- /dev/null
+++ b/Test/spv.fragmentDensity-es.frag
@@ -0,0 +1,11 @@
+#version 310 es
+
+#extension GL_EXT_fragment_invocation_density : require
+
+layout (location = 0) out highp ivec2 FragSize;
+layout (location = 2) out highp int FragInvocationCount;
+
+void main () {
+    FragSize = gl_FragSizeEXT;
+    FragInvocationCount = gl_FragInvocationCountEXT;
+}
diff --git a/Test/spv.fragmentDensity-neg.frag b/Test/spv.fragmentDensity-neg.frag
new file mode 100644
index 0000000..68e736c
--- /dev/null
+++ b/Test/spv.fragmentDensity-neg.frag
@@ -0,0 +1,12 @@
+#version 450
+
+//make sure the builtins don't exist if the extension isn't enabled.
+//#extension GL_EXT_fragment_invocation_density : require
+
+layout (location = 0) out vec2 FragSize;
+layout (location = 2) out int FragInvocationCount;
+
+void main () {
+    FragSize = gl_FragSizeEXT;
+    FragInvocationCount = gl_FragInvocationCountEXT;
+}
diff --git a/Test/spv.fragmentDensity.frag b/Test/spv.fragmentDensity.frag
new file mode 100644
index 0000000..9b37ba4
--- /dev/null
+++ b/Test/spv.fragmentDensity.frag
@@ -0,0 +1,11 @@
+#version 450
+
+#extension GL_EXT_fragment_invocation_density : require
+
+layout (location = 0) out vec2 FragSize;
+layout (location = 2) out int FragInvocationCount;
+
+void main () {
+    FragSize = gl_FragSizeEXT;
+    FragInvocationCount = gl_FragInvocationCountEXT;
+}
diff --git a/Test/spv.fragmentDensity.vert b/Test/spv.fragmentDensity.vert
new file mode 100644
index 0000000..eaef72d
--- /dev/null
+++ b/Test/spv.fragmentDensity.vert
@@ -0,0 +1,12 @@
+#version 450
+
+// try using a fragment-only extension in a vertex shader
+#extension GL_EXT_fragment_invocation_density : require
+
+layout (location = 0) out uvec2 FragSize;
+layout (location = 2) out int FragInvocationCount;
+
+void main () {
+    FragSize = gl_FragSizeEXT;
+    FragInvocationCount = gl_FragInvocationCountEXT;
+}
diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h
index 4a7c056..fabd613 100644
--- a/glslang/Include/BaseTypes.h
+++ b/glslang/Include/BaseTypes.h
@@ -232,6 +232,9 @@
     EbvViewIndex,
     EbvDeviceIndex,
 
+    EbvFragSizeEXT,
+    EbvFragInvocationCountEXT,
+
 #ifdef NV_EXTENSIONS
     EbvViewportMaskNV,
     EbvSecondaryPositionNV,
@@ -404,6 +407,9 @@
     case EbvViewIndex:                  return "ViewIndex";
     case EbvDeviceIndex:                return "DeviceIndex";
 
+    case EbvFragSizeEXT:                return "FragSizeEXT";
+    case EbvFragInvocationCountEXT:     return "FragInvocationCountEXT";
+
 #ifdef NV_EXTENSIONS
     case EbvViewportMaskNV:             return "ViewportMaskNV";
     case EbvSecondaryPositionNV:        return "SecondaryPositionNV";
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index a17ea1a..7118d06 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -5939,6 +5939,12 @@
                 "bool gl_HelperInvocation;"     // needs qualifier fixed later
                 );
 
+        if (version >= 450)
+            stageBuiltins[EShLangFragment].append( // GL_EXT_fragment_invocation_density
+                "flat in ivec2 gl_FragSizeEXT;"
+                "flat in int   gl_FragInvocationCountEXT;"
+                );
+
 #ifdef AMD_EXTENSIONS
         if (version >= 450)
             stageBuiltins[EShLangFragment].append(
@@ -5959,9 +5965,9 @@
                 );
         if (version >= 450)
             stageBuiltins[EShLangFragment].append(
-                "flat in ivec2 gl_FragmentSizeNV;"
+                "flat in ivec2 gl_FragmentSizeNV;"          // GL_NV_shading_rate_image
                 "flat in int   gl_InvocationsPerPixelNV;"
-                "in vec3 gl_BaryCoordNV;"
+                "in vec3 gl_BaryCoordNV;"                   // GL_NV_fragment_shader_barycentric
                 "in vec3 gl_BaryCoordNoPerspNV;"
                 );
 
@@ -6006,13 +6012,19 @@
         stageBuiltins[EShLangFragment].append(
             "highp float gl_FragDepthEXT;"       // GL_EXT_frag_depth
             );
+
+        if (version >= 310)
+            stageBuiltins[EShLangFragment].append( // GL_EXT_fragment_invocation_density
+                "flat in ivec2 gl_FragSizeEXT;"
+                "flat in int   gl_FragInvocationCountEXT;"
+            );
 #ifdef NV_EXTENSIONS
         if (version >= 320)
-            stageBuiltins[EShLangFragment].append(
+            stageBuiltins[EShLangFragment].append( // GL_NV_shading_rate_image
                 "flat in ivec2 gl_FragmentSizeNV;"
                 "flat in int   gl_InvocationsPerPixelNV;"
             );
-       if (version >= 320)
+        if (version >= 320)
             stageBuiltins[EShLangFragment].append(
                 "in vec3 gl_BaryCoordNV;"
                 "in vec3 gl_BaryCoordNoPerspNV;"
@@ -8342,6 +8354,14 @@
         }
 #endif
 
+        if ((profile != EEsProfile && version >= 450) ||
+            (profile == EEsProfile && version >= 310)) {
+            symbolTable.setVariableExtensions("gl_FragSizeEXT",            1, &E_GL_EXT_fragment_invocation_density);
+            symbolTable.setVariableExtensions("gl_FragInvocationCountEXT", 1, &E_GL_EXT_fragment_invocation_density);
+            BuiltInVariable("gl_FragSizeEXT",            EbvFragSizeEXT, symbolTable);
+            BuiltInVariable("gl_FragInvocationCountEXT", EbvFragInvocationCountEXT, symbolTable);
+        }
+
         symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth);
 
         if (profile == EEsProfile && version < 320) {
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 89c0333..16265a3 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -205,6 +205,7 @@
     extensionBehavior[E_GL_EXT_nonuniform_qualifier]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_samplerless_texture_functions]           = EBhDisable;
     extensionBehavior[E_GL_EXT_scalar_block_layout]                     = EBhDisable;
+    extensionBehavior[E_GL_EXT_fragment_invocation_density]             = EBhDisable;
 
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
@@ -380,6 +381,7 @@
             "#define GL_EXT_shader_8bit_storage 1\n"
             "#define GL_EXT_samplerless_texture_functions 1\n"
             "#define GL_EXT_scalar_block_layout 1\n"
+            "#define GL_EXT_fragment_invocation_density 1\n"
 
             // GL_KHR_shader_subgroup
             "#define GL_KHR_shader_subgroup_basic 1\n"
diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h
index df10f0f..6b513b4 100644
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -167,6 +167,7 @@
 const char* const E_GL_EXT_nonuniform_qualifier             = "GL_EXT_nonuniform_qualifier";
 const char* const E_GL_EXT_samplerless_texture_functions    = "GL_EXT_samplerless_texture_functions";
 const char* const E_GL_EXT_scalar_block_layout              = "GL_EXT_scalar_block_layout";
+const char* const E_GL_EXT_fragment_invocation_density      = "GL_EXT_fragment_invocation_density";
 
 // Arrays of extensions for the above viewportEXTs duplications
 
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index f686afd..efb8967 100755
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -271,6 +271,10 @@
         "spv.flowControl.frag",
         "spv.forLoop.frag",
         "spv.forwardFun.frag",
+        "spv.fragmentDensity.frag",
+        "spv.fragmentDensity.vert",
+        "spv.fragmentDensity-es.frag",
+        "spv.fragmentDensity-neg.frag",
         "spv.fullyCovered.frag",
         "spv.functionCall.frag",
         "spv.functionNestedOpaque.vert",