diff options
author | Spencer Fricke <spencerfricke@gmail.com> | 2022-09-08 04:12:07 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-07 15:12:07 -0400 |
commit | 59cf5b1346d8b029add67a919f801c29ea13cc49 (patch) | |
tree | 03807ae8681cea25f56a84f98763962bb24a4bd8 | |
parent | 934a0597874e93b2440e196cf5b45a830513c2db (diff) | |
download | SPIRV-Tools-59cf5b1346d8b029add67a919f801c29ea13cc49.tar.gz |
spirv-val: consider OpEmitMeshTasksEXT a terminator instruction (#4923)
-rw-r--r-- | source/opcode.cpp | 12 | ||||
-rw-r--r-- | source/val/validate_cfg.cpp | 6 | ||||
-rw-r--r-- | test/val/CMakeLists.txt | 1 | ||||
-rw-r--r-- | test/val/val_mesh_shading_test.cpp | 95 |
4 files changed, 112 insertions, 2 deletions
diff --git a/source/opcode.cpp b/source/opcode.cpp index 2584d51e..e3797b70 100644 --- a/source/opcode.cpp +++ b/source/opcode.cpp @@ -468,8 +468,16 @@ bool spvOpcodeIsBlockTerminator(SpvOp opcode) { } bool spvOpcodeTerminatesExecution(SpvOp opcode) { - return opcode == SpvOpKill || opcode == SpvOpTerminateInvocation || - opcode == SpvOpTerminateRayKHR || opcode == SpvOpIgnoreIntersectionKHR; + switch (opcode) { + case SpvOpKill: + case SpvOpTerminateInvocation: + case SpvOpTerminateRayKHR: + case SpvOpIgnoreIntersectionKHR: + case SpvOpEmitMeshTasksEXT: + return true; + default: + return false; + } } bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) { diff --git a/source/val/validate_cfg.cpp b/source/val/validate_cfg.cpp index 87975e1e..c684a991 100644 --- a/source/val/validate_cfg.cpp +++ b/source/val/validate_cfg.cpp @@ -1066,6 +1066,7 @@ spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) { case SpvOpTerminateInvocation: case SpvOpIgnoreIntersectionKHR: case SpvOpTerminateRayKHR: + case SpvOpEmitMeshTasksEXT: _.current_function().RegisterBlockEnd(std::vector<uint32_t>()); if (opcode == SpvOpKill) { _.current_function().RegisterExecutionModelLimitation( @@ -1087,6 +1088,11 @@ spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) { SpvExecutionModelAnyHitKHR, "OpTerminateRayKHR requires AnyHitKHR execution model"); } + if (opcode == SpvOpEmitMeshTasksEXT) { + _.current_function().RegisterExecutionModelLimitation( + SpvExecutionModelTaskEXT, + "OpEmitMeshTasksEXT requires TaskEXT execution model"); + } break; default: diff --git a/test/val/CMakeLists.txt b/test/val/CMakeLists.txt index e73e0f4a..8d00560b 100644 --- a/test/val/CMakeLists.txt +++ b/test/val/CMakeLists.txt @@ -77,6 +77,7 @@ add_spvtools_unittest(TARGET val_fghijklmnop val_literals_test.cpp val_logicals_test.cpp val_memory_test.cpp + val_mesh_shading_test.cpp val_misc_test.cpp val_modes_test.cpp val_non_semantic_test.cpp diff --git a/test/val/val_mesh_shading_test.cpp b/test/val/val_mesh_shading_test.cpp new file mode 100644 index 00000000..d10f40d8 --- /dev/null +++ b/test/val/val_mesh_shading_test.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2022 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Tests instructions from SPV_EXT_mesh_shader + +#include <sstream> +#include <string> + +#include "gmock/gmock.h" +#include "test/val/val_fixtures.h" + +namespace spvtools { +namespace val { +namespace { + +using ::testing::HasSubstr; +using ::testing::Values; + +using ValidateMeshShading = spvtest::ValidateBase<bool>; + +TEST_F(ValidateMeshShading, EmitMeshTasksEXTNotLastInstructionUniversal) { + const std::string body = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpMemoryModel Logical GLSL450 + OpEntryPoint TaskEXT %main "main" %p + OpExecutionModeId %main LocalSizeId %uint_1 %uint_1 %uint_1 + %void = OpTypeVoid + %func = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 + %float = OpTypeFloat 32 + %arr_float = OpTypeArray %float %uint_1 + %Payload = OpTypeStruct %arr_float +%ptr_Payload = OpTypePointer TaskPayloadWorkgroupEXT %Payload + %p = OpVariable %ptr_Payload TaskPayloadWorkgroupEXT + %main = OpFunction %void None %func + %label1 = OpLabel + OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %p + OpBranch %label2 + %label2 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_4); + EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, + ValidateInstructions(SPV_ENV_UNIVERSAL_1_4)); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Branch must appear in a block")); +} + +TEST_F(ValidateMeshShading, EmitMeshTasksEXTNotLastInstructionVulkan) { + const std::string body = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpMemoryModel Logical GLSL450 + OpEntryPoint TaskEXT %main "main" %p + OpExecutionModeId %main LocalSizeId %uint_1 %uint_1 %uint_1 + %void = OpTypeVoid + %func = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 + %float = OpTypeFloat 32 + %arr_float = OpTypeArray %float %uint_1 + %Payload = OpTypeStruct %arr_float +%ptr_Payload = OpTypePointer TaskPayloadWorkgroupEXT %Payload + %p = OpVariable %ptr_Payload TaskPayloadWorkgroupEXT + %main = OpFunction %void None %func + %label1 = OpLabel + OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %p + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(body, SPV_ENV_VULKAN_1_2); + EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Return must appear in a block")); +} + +} // namespace +} // namespace val +} // namespace spvtools |