Allow GL_NV_mesh_shader in fragment shaders for perprimitiveNV

- Emit relevant capability/extension for use of perprimitiveNV in fragment shader
- Remove redundant checks for mesh shader qualifiers in glslang.y
- Add profile version check for use of extension GL_NV_mesh_shader
- Add a new gtest for use of perprimitiveNV in fragment shader
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index c222ccb..e1ae7b4 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -7202,15 +7202,29 @@
 void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier)
 {
     if (member >= 0) {
-        if (qualifier.perPrimitiveNV)
+        if (qualifier.perPrimitiveNV) {
+            // Need to add capability/extension for fragment shader.
+            // Mesh shader already adds this by default.
+            if (glslangIntermediate->getStage() == EShLangFragment) {
+                builder.addCapability(spv::CapabilityMeshShadingNV);
+                builder.addExtension(spv::E_SPV_NV_mesh_shader);
+            }
             builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerPrimitiveNV);
+        }
         if (qualifier.perViewNV)
             builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerViewNV);
         if (qualifier.perTaskNV)
             builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerTaskNV);
     } else {
-        if (qualifier.perPrimitiveNV)
+        if (qualifier.perPrimitiveNV) {
+            // Need to add capability/extension for fragment shader.
+            // Mesh shader already adds this by default.
+            if (glslangIntermediate->getStage() == EShLangFragment) {
+                builder.addCapability(spv::CapabilityMeshShadingNV);
+                builder.addExtension(spv::E_SPV_NV_mesh_shader);
+            }
             builder.addDecoration(id, spv::DecorationPerPrimitiveNV);
+        }
         if (qualifier.perViewNV)
             builder.addDecoration(id, spv::DecorationPerViewNV);
         if (qualifier.perTaskNV)
diff --git a/Test/baseResults/spv.perprimitiveNV.frag.out b/Test/baseResults/spv.perprimitiveNV.frag.out
new file mode 100644
index 0000000..eaff400
--- /dev/null
+++ b/Test/baseResults/spv.perprimitiveNV.frag.out
@@ -0,0 +1,54 @@
+spv.perprimitiveNV.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 23
+
+                              Capability Shader
+                              Capability MeshShadingNV
+                              Extension  "SPV_NV_mesh_shader"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 8 11 19
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 460
+                              SourceExtension  "GL_NV_mesh_shader"
+                              Name 4  "main"
+                              Name 8  "g"
+                              Name 9  "B"
+                              MemberName 9(B) 0  "f"
+                              Name 11  ""
+                              Name 17  "C"
+                              MemberName 17(C) 0  "h"
+                              Name 19  ""
+                              Decorate 8(g) Location 8
+                              MemberDecorate 9(B) 0 PerPrimitiveNV
+                              Decorate 9(B) Block
+                              Decorate 11 Location 0
+                              MemberDecorate 17(C) 0 Flat
+                              MemberDecorate 17(C) 0 Centroid
+                              Decorate 17(C) Block
+                              Decorate 19 Location 4
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypePointer Output 6(float)
+            8(g):      7(ptr) Variable Output
+            9(B):             TypeStruct 6(float)
+              10:             TypePointer Input 9(B)
+              11:     10(ptr) Variable Input
+              12:             TypeInt 32 1
+              13:     12(int) Constant 0
+              14:             TypePointer Input 6(float)
+           17(C):             TypeStruct 6(float)
+              18:             TypePointer Input 17(C)
+              19:     18(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+              15:     14(ptr) AccessChain 11 13
+              16:    6(float) Load 15
+              20:     14(ptr) AccessChain 19 13
+              21:    6(float) Load 20
+              22:    6(float) FAdd 16 21
+                              Store 8(g) 22
+                              Return
+                              FunctionEnd
diff --git a/Test/spv.perprimitiveNV.frag b/Test/spv.perprimitiveNV.frag
new file mode 100644
index 0000000..56e00f5
--- /dev/null
+++ b/Test/spv.perprimitiveNV.frag
@@ -0,0 +1,21 @@
+#version 460

+

+#extension GL_NV_mesh_shader: require

+

+layout(location=0) 

+in B {

+    perprimitiveNV float f;

+};

+

+layout(location=4) 

+in C {

+    flat centroid float h;

+};

+

+layout(location=8) 

+out float g;

+

+void main()

+{

+    g = f + h;

+}

diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 4c2d69f..bb0fe93 100755
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -4514,6 +4514,8 @@
         break;
 #ifdef NV_EXTENSIONS
     case EShLangTaskNV:
+        requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "task shaders");
+        break;
     case EShLangMeshNV:
         requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "mesh shaders");
         break;
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 9ca20a5..b26bc3e 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -842,9 +842,12 @@
 {
 #ifdef NV_EXTENSIONS
     // GL_NV_mesh_shader extension is only allowed in task/mesh shaders
-    if (strcmp(extension, "GL_NV_mesh_shader") == 0)
-        requireStage(loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask),
+    if (strcmp(extension, "GL_NV_mesh_shader") == 0) {
+        requireStage(loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask | EShLangFragmentMask),
                      "#extension GL_NV_mesh_shader");
+        profileRequires(loc, ECoreProfile, 450, 0, "#extension GL_NV_mesh_shader");
+        profileRequires(loc, EEsProfile, 320, 0, "#extension GL_NV_mesh_shader");
+    }
 #endif
 }
 
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index cd4256d..f6e33c6 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -1157,30 +1157,30 @@
     }
     | PERPRIMITIVENV {
 #ifdef NV_EXTENSIONS
+        // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck($1.loc, "perprimitiveNV");
         parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshNVMask), "perprimitiveNV");
-        parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_NV_mesh_shader, "perprimitiveNV");
-        parseContext.profileRequires($1.loc, EEsProfile, 320, E_GL_NV_mesh_shader, "perprimitiveNV");
+        // Fragment shader stage doesn't check for extension. So we explicitly add below extension check.
+        if (parseContext.language == EShLangFragment)
+            parseContext.requireExtensions($1.loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV");
         $$.init($1.loc);
         $$.qualifier.perPrimitiveNV = true;
 #endif
     }
     | PERVIEWNV {
 #ifdef NV_EXTENSIONS
+        // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck($1.loc, "perviewNV");
         parseContext.requireStage($1.loc, EShLangMeshNV, "perviewNV");
-        parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_NV_mesh_shader, "perviewNV");
-        parseContext.profileRequires($1.loc, EEsProfile, 320, E_GL_NV_mesh_shader, "perviewNV");
         $$.init($1.loc);
         $$.qualifier.perViewNV = true;
 #endif
     }
     | PERTASKNV {
 #ifdef NV_EXTENSIONS
+        // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck($1.loc, "taskNV");
         parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask), "taskNV");
-        parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_NV_mesh_shader, "taskNV");
-        parseContext.profileRequires($1.loc, EEsProfile, 320, E_GL_NV_mesh_shader, "taskNV");
         $$.init($1.loc);
         $$.qualifier.perTaskNV = true;
 #endif
diff --git a/glslang/MachineIndependent/glslang_tab.cpp b/glslang/MachineIndependent/glslang_tab.cpp
index 9b9df51..4b70ee3 100644
--- a/glslang/MachineIndependent/glslang_tab.cpp
+++ b/glslang/MachineIndependent/glslang_tab.cpp
@@ -948,7 +948,7 @@
      820,   825,   834,   834,   845,   849,   856,   863,   866,   873,
      881,   901,   924,   939,   964,   975,   985,   995,  1005,  1014,
     1017,  1021,  1025,  1030,  1038,  1043,  1048,  1053,  1058,  1067,
-    1078,  1105,  1114,  1121,  1128,  1139,  1148,  1158,  1168,  1178,
+    1078,  1105,  1114,  1121,  1128,  1139,  1148,  1158,  1170,  1179,
     1191,  1197,  1200,  1207,  1211,  1215,  1223,  1232,  1235,  1246,
     1249,  1252,  1256,  1260,  1264,  1268,  1274,  1278,  1290,  1304,
     1309,  1315,  1321,  1328,  1334,  1339,  1344,  1349,  1359,  1369,
@@ -5515,40 +5515,40 @@
 #line 1158 "MachineIndependent/glslang.y" /* yacc.c:1646  */
     {
 #ifdef NV_EXTENSIONS
+        // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV");
         parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshNVMask), "perprimitiveNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_NV_mesh_shader, "perprimitiveNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, E_GL_NV_mesh_shader, "perprimitiveNV");
+        // Fragment shader stage doesn't check for extension. So we explicitly add below extension check.
+        if (parseContext.language == EShLangFragment)
+            parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.perPrimitiveNV = true;
 #endif
     }
-#line 5527 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 138:
-#line 1168 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1170 "MachineIndependent/glslang.y" /* yacc.c:1646  */
     {
 #ifdef NV_EXTENSIONS
+        // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV");
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangMeshNV, "perviewNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_NV_mesh_shader, "perviewNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, E_GL_NV_mesh_shader, "perviewNV");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.perViewNV = true;
 #endif
     }
-#line 5542 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5543 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 139:
-#line 1178 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1179 "MachineIndependent/glslang.y" /* yacc.c:1646  */
     {
 #ifdef NV_EXTENSIONS
+        // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV");
         parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask), "taskNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_NV_mesh_shader, "taskNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, E_GL_NV_mesh_shader, "taskNV");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.perTaskNV = true;
 #endif
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index 8158391..ece5e69 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -528,6 +528,7 @@
     "spv.meshShaderRedeclBuiltins.mesh",
     "spv.meshShaderRedeclPerViewBuiltins.mesh",
     "spv.meshTaskShader.task",
+    "spv.perprimitiveNV.frag",
 })),
 FileNameAsCustomTestSuffix
 );