Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSpencer Fricke <spencerfricke@gmail.com>2022-09-23 18:06:46 +0300
committerGitHub <noreply@github.com>2022-09-23 18:06:46 +0300
commitb53d7a8affabb230a47fb4123b040573a3062d4a (patch)
tree17ad86d1bfe312ac8a0d4b8fc4b6f4185287b3ae /test
parent265b455c996f7314ff995ecc3f5e3548365dbe87 (diff)
spirv-val: Add initial SPV_EXT_mesh_shader validation (#4924)
* Move TaskEXT check to OpEmitMeshTasksEXT * Add MeshNV for Execution Model alias
Diffstat (limited to 'test')
-rw-r--r--test/val/val_id_test.cpp4
-rw-r--r--test/val/val_memory_test.cpp49
-rw-r--r--test/val/val_mesh_shading_test.cpp509
3 files changed, 560 insertions, 2 deletions
diff --git a/test/val/val_id_test.cpp b/test/val/val_id_test.cpp
index 3cf7575a1..deda95b49 100644
--- a/test/val/val_id_test.cpp
+++ b/test/val/val_id_test.cpp
@@ -2091,9 +2091,9 @@ TEST_F(ValidateIdWithMessage, OpVariableGood) {
TEST_F(ValidateIdWithMessage, OpVariableInitializerConstantGood) {
std::string spirv = kGLSL450MemoryModel + R"(
%1 = OpTypeInt 32 0
-%2 = OpTypePointer Input %1
+%2 = OpTypePointer Output %1
%3 = OpConstant %1 42
-%4 = OpVariable %2 Input %3)";
+%4 = OpVariable %2 Output %3)";
CompileSuccessfully(spirv.c_str());
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
}
diff --git a/test/val/val_memory_test.cpp b/test/val/val_memory_test.cpp
index ec1a00077..35e8af756 100644
--- a/test/val/val_memory_test.cpp
+++ b/test/val/val_memory_test.cpp
@@ -472,6 +472,55 @@ OpFunctionEnd
"= OpVariable %_ptr_Input_float Input %float_1\n"));
}
+TEST_F(ValidateMemory, UniversalInitializerWithDisallowedStorageClassesBad) {
+ std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+OpExecutionMode %func OriginUpperLeft
+%float = OpTypeFloat 32
+%float_ptr = OpTypePointer Input %float
+%init_val = OpConstant %float 1.0
+%1 = OpVariable %float_ptr Input %init_val
+%void = OpTypeVoid
+%functy = OpTypeFunction %void
+%func = OpFunction %void None %functy
+%2 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_3);
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpVariable, <id> '5[%5]', initializer are not allowed for Input"));
+}
+
+TEST_F(ValidateMemory, InitializerWithTaskPayloadWorkgroupEXT) {
+ std::string spirv = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TaskEXT %main "main" %payload
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
+ %uint_1 = OpConstant %uint 1
+ %payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT %uint_1
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpVariable, <id> '2[%2]', initializer are not allowed "
+ "for TaskPayloadWorkgroupEXT"));
+}
+
TEST_F(ValidateMemory, ArrayLenCorrectResultType) {
std::string spirv = R"(
OpCapability Shader
diff --git a/test/val/val_mesh_shading_test.cpp b/test/val/val_mesh_shading_test.cpp
index d10f40d87..ce6999dcb 100644
--- a/test/val/val_mesh_shading_test.cpp
+++ b/test/val/val_mesh_shading_test.cpp
@@ -90,6 +90,515 @@ TEST_F(ValidateMeshShading, EmitMeshTasksEXTNotLastInstructionVulkan) {
HasSubstr("Return must appear in a block"));
}
+TEST_F(ValidateMeshShading, BasicTaskSuccess) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TaskEXT %main "main"
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateMeshShading, BasicMeshSuccess) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputVertices 1
+ OpExecutionMode %main OutputPrimitivesEXT 1
+ OpExecutionMode %main OutputTrianglesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateMeshShading, VulkanBasicMeshAndTaskSuccess) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpExtension "SPV_NV_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %mainMesh "mainMesh"
+ OpEntryPoint TaskEXT %mainTask "mainTask"
+ OpExecutionMode %mainMesh OutputVertices 1
+ OpExecutionMode %mainMesh OutputPrimitivesEXT 1
+ OpExecutionMode %mainMesh OutputTrianglesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %mainMesh = OpFunction %void None %func
+ %labelMesh = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %mainTask = OpFunction %void None %func
+ %labelTask = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+}
+
+TEST_F(ValidateMeshShading, VulkanBasicMeshAndTaskBad) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpCapability MeshShadingNV
+ OpExtension "SPV_EXT_mesh_shader"
+ OpExtension "SPV_NV_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %mainMesh "mainMesh"
+ OpEntryPoint TaskNV %mainTask "mainTask"
+ OpExecutionMode %mainMesh OutputVertices 1
+ OpExecutionMode %mainMesh OutputPrimitivesEXT 1
+ OpExecutionMode %mainMesh OutputTrianglesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %mainMesh = OpFunction %void None %func
+ %labelMesh = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %mainTask = OpFunction %void None %func
+ %labelTask = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-MeshEXT-07102"));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Module can't mix MeshEXT/TaskEXT with MeshNV/TaskNV "
+ "Execution Model."));
+}
+
+TEST_F(ValidateMeshShading, MeshMissingOutputVertices) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputPrimitivesEXT 1
+ OpExecutionMode %main OutputTrianglesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("MeshEXT execution model entry points must specify both "
+ "OutputPrimitivesEXT and OutputVertices Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, MeshMissingOutputPrimitivesEXT) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputVertices 1
+ OpExecutionMode %main OutputTrianglesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("MeshEXT execution model entry points must specify both "
+ "OutputPrimitivesEXT and OutputVertices Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, MeshMissingOutputType) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputVertices 1
+ OpExecutionMode %main OutputPrimitivesEXT 1
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("MeshEXT execution model entry points must specify "
+ "exactly one of OutputPoints, OutputLinesEXT, or "
+ "OutputTrianglesEXT Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, MeshMultipleOutputType) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputVertices 1
+ OpExecutionMode %main OutputPrimitivesEXT 1
+ OpExecutionMode %main OutputLinesEXT
+ OpExecutionMode %main OutputTrianglesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("MeshEXT execution model entry points must specify "
+ "exactly one of OutputPoints, OutputLinesEXT, or "
+ "OutputTrianglesEXT Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, BadExecutionModelOutputLinesEXT) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main OutputLinesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Execution mode can only be used with the MeshEXT or "
+ "MeshNV execution model."));
+}
+
+TEST_F(ValidateMeshShading, BadExecutionModelOutputTrianglesEXT) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main OutputTrianglesEXT
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Execution mode can only be used with the MeshEXT or "
+ "MeshNV execution model."));
+}
+
+TEST_F(ValidateMeshShading, BadExecutionModelOutputPrimitivesEXT) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main OutputPrimitivesEXT 1
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Execution mode can only be used with the MeshEXT or "
+ "MeshNV execution model."));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksBadGroupCountSignedInt) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TaskEXT %main "main"
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %uint = OpTypeInt 32 0
+ %int_1 = OpConstant %int 1
+ %uint_1 = OpConstant %uint 1
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpEmitMeshTasksEXT %int_1 %uint_1 %uint_1
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Group Count X must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksBadGroupCountVector) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TaskEXT %main "main"
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %v2uint = OpTypeVector %uint 2
+%_ptr_v2uint = OpTypePointer Function %v2uint
+ %uint_1 = OpConstant %uint 1
+ %composite = OpConstantComposite %v2uint %uint_1 %uint_1
+ %_ptr_uint = OpTypePointer Function %uint
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ %x = OpVariable %_ptr_v2uint Function
+ OpStore %x %composite
+ %13 = OpAccessChain %_ptr_uint %x %uint_1
+ %14 = OpLoad %uint %13
+ OpEmitMeshTasksEXT %14 %composite %uint_1
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Group Count Y must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksBadPayload) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TaskEXT %main "main" %payload
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %task = OpTypeStruct %uint
+%_ptr_Uniform = OpTypePointer Uniform %task
+ %payload = OpVariable %_ptr_Uniform Uniform
+ %uint_1 = OpConstant %uint 1
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %payload
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Payload OpVariable must have a storage class of "
+ "TaskPayloadWorkgroupEXT"));
+}
+
+TEST_F(ValidateMeshShading, TaskPayloadWorkgroupBadExecutionModel) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %payload
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
+ %payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ %load = OpLoad %uint %payload
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("TaskPayloadWorkgroupEXT Storage Class is limited to "
+ "TaskEXT and MeshKHR execution model"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsBadVertexCount) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputVertices 1
+ OpExecutionMode %main OutputPrimitivesNV 1
+ OpExecutionMode %main OutputTrianglesNV
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %uint = OpTypeInt 32 0
+ %_ptr_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_1 = OpConstant %uint 1
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %x = OpVariable %_ptr_int Function
+ OpStore %x %int_1
+ %load = OpLoad %int %x
+ OpSetMeshOutputsEXT %load %uint_1
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Vertex Count must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsBadPrimitiveCount) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputVertices 1
+ OpExecutionMode %main OutputPrimitivesNV 1
+ OpExecutionMode %main OutputTrianglesNV
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %uint = OpTypeInt 32 0
+ %int_1 = OpConstant %int 1
+ %uint_1 = OpConstant %uint 1
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ OpSetMeshOutputsEXT %uint_1 %int_1
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Primitive Count must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsBadExecutionModel) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TaskEXT %main "main"
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ OpSetMeshOutputsEXT %uint_1 %uint_1
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("OpSetMeshOutputsEXT requires MeshEXT execution model"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsZeroSuccess) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint MeshEXT %main "main"
+ OpExecutionMode %main OutputVertices 1
+ OpExecutionMode %main OutputPrimitivesNV 1
+ OpExecutionMode %main OutputTrianglesNV
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ OpSetMeshOutputsEXT %uint_0 %uint_0
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksZeroSuccess) {
+ const std::string body = R"(
+ OpCapability MeshShadingEXT
+ OpExtension "SPV_EXT_mesh_shader"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TaskEXT %main "main"
+ %void = OpTypeVoid
+ %func = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 1
+ %main = OpFunction %void None %func
+ %label = OpLabel
+ OpEmitMeshTasksEXT %uint_0 %uint_0 %uint_0
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
} // namespace
} // namespace val
} // namespace spvtools