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,RequiresExtension)58 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresExtension) {
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(getDiagnosticString(),
76 HasSubstr("TerminateInvocation requires one of the following "
77 "extensions: SPV_KHR_terminate_invocation"));
78 }
79
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresShaderCapability)80 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresShaderCapability) {
81 const std::string str = R"(
82 OpCapability Kernel
83 OpCapability Addresses
84 OpExtension "SPV_KHR_terminate_invocation"
85 OpMemoryModel Physical32 OpenCL
86 OpEntryPoint Kernel %main "main"
87
88 %void = OpTypeVoid
89 %void_fn = OpTypeFunction %void
90
91 %main = OpFunction %void None %void_fn
92 %entry = OpLabel
93 OpTerminateInvocation
94 OpFunctionEnd
95 )";
96 CompileSuccessfully(str.c_str());
97 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
98 EXPECT_THAT(
99 getDiagnosticString(),
100 HasSubstr(
101 "TerminateInvocation requires one of these capabilities: Shader \n"));
102 }
103
TEST_F(ValidateSpvKHRTerminateInvocation,RequiresFragmentShader)104 TEST_F(ValidateSpvKHRTerminateInvocation, RequiresFragmentShader) {
105 const std::string str = R"(
106 OpCapability Shader
107 OpExtension "SPV_KHR_terminate_invocation"
108 OpMemoryModel Logical Simple
109 OpEntryPoint GLCompute %main "main"
110
111 %void = OpTypeVoid
112 %void_fn = OpTypeFunction %void
113
114 %main = OpFunction %void None %void_fn
115 %entry = OpLabel
116 OpTerminateInvocation
117 OpFunctionEnd
118 )";
119 CompileSuccessfully(str.c_str());
120 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
121 EXPECT_THAT(
122 getDiagnosticString(),
123 HasSubstr("OpTerminateInvocation requires Fragment execution model"));
124 }
125
TEST_F(ValidateSpvKHRTerminateInvocation,IsTerminatorInstruction)126 TEST_F(ValidateSpvKHRTerminateInvocation, IsTerminatorInstruction) {
127 const std::string str = R"(
128 OpCapability Shader
129 OpExtension "SPV_KHR_terminate_invocation"
130 OpMemoryModel Logical Simple
131 OpEntryPoint GLCompute %main "main"
132
133 %void = OpTypeVoid
134 %void_fn = OpTypeFunction %void
135
136 %main = OpFunction %void None %void_fn
137 %entry = OpLabel
138 OpTerminateInvocation
139 OpReturn
140 OpFunctionEnd
141 )";
142 CompileSuccessfully(str.c_str());
143 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
144 EXPECT_THAT(getDiagnosticString(),
145 HasSubstr("Return must appear in a block"));
146 }
147
148 } // namespace
149 } // namespace val
150 } // namespace spvtools
151