1 // Copyright (c) 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Tests for OpExtension validator rules.
16
17 #include <string>
18 #include <vector>
19
20 #include "gmock/gmock.h"
21 #include "source/enum_string_mapping.h"
22 #include "source/extensions.h"
23 #include "source/spirv_target_env.h"
24 #include "test/test_fixture.h"
25 #include "test/unit_spirv.h"
26 #include "test/val/val_fixtures.h"
27
28 namespace spvtools {
29 namespace val {
30 namespace {
31
32 using ::testing::HasSubstr;
33 using ::testing::Values;
34 using ::testing::ValuesIn;
35
36 using ValidateSpvKHRTerminateInvocation = spvtest::ValidateBase<bool>;
37
TEST_F(ValidateSpvKHRTerminateInvocation,Valid)38 TEST_F(ValidateSpvKHRTerminateInvocation, Valid) {
39 const std::string str = R"(
40 OpCapability Shader
41 OpExtension "SPV_KHR_terminate_invocation"
42 OpMemoryModel Logical Simple
43 OpEntryPoint Fragment %main "main"
44 OpExecutionMode %main OriginUpperLeft
45
46 %void = OpTypeVoid
47 %void_fn = OpTypeFunction %void
48
49 %main = OpFunction %void None %void_fn
50 %entry = OpLabel
51 OpTerminateInvocation
52 OpFunctionEnd
53 )";
54 CompileSuccessfully(str.c_str());
55 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
56 }
57
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresExtensionPre1p6)58 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresExtensionPre1p6) {
59 const std::string str = R"(
60 OpCapability Shader
61 OpMemoryModel Logical Simple
62 OpEntryPoint Fragment %main "main"
63 OpExecutionMode %main OriginUpperLeft
64
65 %void = OpTypeVoid
66 %void_fn = OpTypeFunction %void
67
68 %main = OpFunction %void None %void_fn
69 %entry = OpLabel
70 OpTerminateInvocation
71 OpFunctionEnd
72 )";
73 CompileSuccessfully(str.c_str());
74 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
75 EXPECT_THAT(
76 getDiagnosticString(),
77 HasSubstr(
78 "TerminateInvocation requires SPIR-V version 1.6 at minimum or one "
79 "of the following extensions: SPV_KHR_terminate_invocation"));
80 }
81
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresNoExtensionPost1p6)82 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresNoExtensionPost1p6) {
83 const std::string str = R"(
84 OpCapability Shader
85 OpMemoryModel Logical Simple
86 OpEntryPoint Fragment %main "main"
87 OpExecutionMode %main OriginUpperLeft
88
89 %void = OpTypeVoid
90 %void_fn = OpTypeFunction %void
91
92 %main = OpFunction %void None %void_fn
93 %entry = OpLabel
94 OpTerminateInvocation
95 OpFunctionEnd
96 )";
97 CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_6);
98 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
99 }
100
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresShaderCapability)101 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresShaderCapability) {
102 const std::string str = R"(
103 OpCapability Kernel
104 OpCapability Addresses
105 OpExtension "SPV_KHR_terminate_invocation"
106 OpMemoryModel Physical32 OpenCL
107 OpEntryPoint Kernel %main "main"
108
109 %void = OpTypeVoid
110 %void_fn = OpTypeFunction %void
111
112 %main = OpFunction %void None %void_fn
113 %entry = OpLabel
114 OpTerminateInvocation
115 OpFunctionEnd
116 )";
117 CompileSuccessfully(str.c_str());
118 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
119 EXPECT_THAT(
120 getDiagnosticString(),
121 HasSubstr(
122 "TerminateInvocation requires one of these capabilities: Shader \n"));
123 }
124
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresFragmentShader)125 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresFragmentShader) {
126 const std::string str = R"(
127 OpCapability Shader
128 OpExtension "SPV_KHR_terminate_invocation"
129 OpMemoryModel Logical Simple
130 OpEntryPoint GLCompute %main "main"
131
132 %void = OpTypeVoid
133 %void_fn = OpTypeFunction %void
134
135 %main = OpFunction %void None %void_fn
136 %entry = OpLabel
137 OpTerminateInvocation
138 OpFunctionEnd
139 )";
140 CompileSuccessfully(str.c_str());
141 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
142 EXPECT_THAT(
143 getDiagnosticString(),
144 HasSubstr("OpTerminateInvocation requires Fragment execution model"));
145 }
146
TEST_F(ValidateSpvKHRTerminateInvocation,IsTerminatorInstruction)147 TEST_F(ValidateSpvKHRTerminateInvocation, IsTerminatorInstruction) {
148 const std::string str = R"(
149 OpCapability Shader
150 OpExtension "SPV_KHR_terminate_invocation"
151 OpMemoryModel Logical Simple
152 OpEntryPoint GLCompute %main "main"
153
154 %void = OpTypeVoid
155 %void_fn = OpTypeFunction %void
156
157 %main = OpFunction %void None %void_fn
158 %entry = OpLabel
159 OpTerminateInvocation
160 OpReturn
161 OpFunctionEnd
162 )";
163 CompileSuccessfully(str.c_str());
164 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
165 EXPECT_THAT(getDiagnosticString(),
166 HasSubstr("Return must appear in a block"));
167 }
168
169 } // namespace
170 } // namespace val
171 } // namespace spvtools
172