• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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