• 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/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