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/spirv_target_env.h"
22 #include "test/unit_spirv.h"
23 #include "test/val/val_fixtures.h"
24
25 namespace spvtools {
26 namespace val {
27 namespace {
28
29 using ::testing::HasSubstr;
30 using ::testing::Values;
31 using ::testing::ValuesIn;
32
33 using ValidateSpvKHRTerminateInvocation = spvtest::ValidateBase<bool>;
34
TEST_F(ValidateSpvKHRTerminateInvocation,Valid)35 TEST_F(ValidateSpvKHRTerminateInvocation, Valid) {
36 const std::string str = R"(
37 OpCapability Shader
38 OpExtension "SPV_KHR_terminate_invocation"
39 OpMemoryModel Logical Simple
40 OpEntryPoint Fragment %main "main"
41 OpExecutionMode %main OriginUpperLeft
42
43 %void = OpTypeVoid
44 %void_fn = OpTypeFunction %void
45
46 %main = OpFunction %void None %void_fn
47 %entry = OpLabel
48 OpTerminateInvocation
49 OpFunctionEnd
50 )";
51 CompileSuccessfully(str.c_str());
52 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
53 }
54
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresExtensionPre1p6)55 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresExtensionPre1p6) {
56 const std::string str = R"(
57 OpCapability Shader
58 OpMemoryModel Logical Simple
59 OpEntryPoint Fragment %main "main"
60 OpExecutionMode %main OriginUpperLeft
61
62 %void = OpTypeVoid
63 %void_fn = OpTypeFunction %void
64
65 %main = OpFunction %void None %void_fn
66 %entry = OpLabel
67 OpTerminateInvocation
68 OpFunctionEnd
69 )";
70 CompileSuccessfully(str.c_str());
71 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
72 EXPECT_THAT(
73 getDiagnosticString(),
74 HasSubstr(
75 "TerminateInvocation requires SPIR-V version 1.6 at minimum or one "
76 "of the following extensions: SPV_KHR_terminate_invocation"));
77 }
78
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresNoExtensionPost1p6)79 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresNoExtensionPost1p6) {
80 const std::string str = R"(
81 OpCapability Shader
82 OpMemoryModel Logical Simple
83 OpEntryPoint Fragment %main "main"
84 OpExecutionMode %main OriginUpperLeft
85
86 %void = OpTypeVoid
87 %void_fn = OpTypeFunction %void
88
89 %main = OpFunction %void None %void_fn
90 %entry = OpLabel
91 OpTerminateInvocation
92 OpFunctionEnd
93 )";
94 CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_6);
95 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
96 }
97
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresShaderCapability)98 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresShaderCapability) {
99 const std::string str = R"(
100 OpCapability Kernel
101 OpCapability Addresses
102 OpExtension "SPV_KHR_terminate_invocation"
103 OpMemoryModel Physical32 OpenCL
104 OpEntryPoint Kernel %main "main"
105
106 %void = OpTypeVoid
107 %void_fn = OpTypeFunction %void
108
109 %main = OpFunction %void None %void_fn
110 %entry = OpLabel
111 OpTerminateInvocation
112 OpFunctionEnd
113 )";
114 CompileSuccessfully(str.c_str());
115 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
116 EXPECT_THAT(
117 getDiagnosticString(),
118 HasSubstr(
119 "TerminateInvocation requires one of these capabilities: Shader \n"));
120 }
121
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresFragmentShader)122 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresFragmentShader) {
123 const std::string str = R"(
124 OpCapability Shader
125 OpExtension "SPV_KHR_terminate_invocation"
126 OpMemoryModel Logical Simple
127 OpEntryPoint GLCompute %main "main"
128
129 %void = OpTypeVoid
130 %void_fn = OpTypeFunction %void
131
132 %main = OpFunction %void None %void_fn
133 %entry = OpLabel
134 OpTerminateInvocation
135 OpFunctionEnd
136 )";
137 CompileSuccessfully(str.c_str());
138 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
139 EXPECT_THAT(
140 getDiagnosticString(),
141 HasSubstr("OpTerminateInvocation requires Fragment execution model"));
142 }
143
TEST_F(ValidateSpvKHRTerminateInvocation,IsTerminatorInstruction)144 TEST_F(ValidateSpvKHRTerminateInvocation, IsTerminatorInstruction) {
145 const std::string str = R"(
146 OpCapability Shader
147 OpExtension "SPV_KHR_terminate_invocation"
148 OpMemoryModel Logical Simple
149 OpEntryPoint GLCompute %main "main"
150
151 %void = OpTypeVoid
152 %void_fn = OpTypeFunction %void
153
154 %main = OpFunction %void None %void_fn
155 %entry = OpLabel
156 OpTerminateInvocation
157 OpReturn
158 OpFunctionEnd
159 )";
160 CompileSuccessfully(str.c_str());
161 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
162 EXPECT_THAT(getDiagnosticString(),
163 HasSubstr("Return must appear in a block"));
164 }
165
166 } // namespace
167 } // namespace val
168 } // namespace spvtools
169