Merge pull request #1549 from sparmarNV/fix-SPV_NV_mesh_shader
Allow GL_NV_mesh_shader in fragment shaders for perprimitiveNV
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
);