- 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
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)
--- /dev/null
+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
--- /dev/null
+#version 460\r
+\r
+#extension GL_NV_mesh_shader: require\r
+\r
+layout(location=0) \r
+in B {\r
+ perprimitiveNV float f;\r
+};\r
+\r
+layout(location=4) \r
+in C {\r
+ flat centroid float h;\r
+};\r
+\r
+layout(location=8) \r
+out float g;\r
+\r
+void main()\r
+{\r
+ g = f + h;\r
+}\r
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;
{
#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
}
}
| 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
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,
#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
"spv.meshShaderRedeclBuiltins.mesh",
"spv.meshShaderRedeclPerViewBuiltins.mesh",
"spv.meshTaskShader.task",
+ "spv.perprimitiveNV.frag",
})),
FileNameAsCustomTestSuffix
);