1 // Copyright (c) 2019 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 // Test validation of constants.
16 //
17 // This file contains newer tests. Older tests may be in other files such as
18 // val_id_test.cpp.
19
20 #include <string>
21 #include <vector>
22
23 #include "gmock/gmock.h"
24 #include "test/unit_spirv.h"
25 #include "test/val/val_fixtures.h"
26
27 namespace spvtools {
28 namespace val {
29 namespace {
30
31 using ::testing::Eq;
32 using ::testing::HasSubstr;
33 using ::testing::ValuesIn;
34
35 using ValidateConstant = spvtest::ValidateBase<bool>;
36
37 #define kBasicTypes \
38 "%bool = OpTypeBool " \
39 "%uint = OpTypeInt 32 0 " \
40 "%uint2 = OpTypeVector %uint 2 " \
41 "%float = OpTypeFloat 32 " \
42 "%_ptr_uint = OpTypePointer Workgroup %uint " \
43 "%uint_0 = OpConstantNull %uint " \
44 "%uint2_0 = OpConstantNull %uint " \
45 "%float_0 = OpConstantNull %float " \
46 "%false = OpConstantFalse %bool " \
47 "%true = OpConstantTrue %bool " \
48 "%null = OpConstantNull %_ptr_uint "
49
50 #define kShaderPreamble \
51 "OpCapability Shader\n" \
52 "OpCapability Linkage\n" \
53 "OpMemoryModel Logical Simple\n"
54
55 #define kKernelPreamble \
56 "OpCapability Kernel\n" \
57 "OpCapability Linkage\n" \
58 "OpCapability Addresses\n" \
59 "OpMemoryModel Physical32 OpenCL\n"
60
61 struct ConstantOpCase {
62 spv_target_env env;
63 std::string assembly;
64 bool expect_success;
65 std::string expect_err;
66 };
67
68 using ValidateConstantOp = spvtest::ValidateBase<ConstantOpCase>;
69
TEST_P(ValidateConstantOp,Samples)70 TEST_P(ValidateConstantOp, Samples) {
71 const auto env = GetParam().env;
72 CompileSuccessfully(GetParam().assembly, env);
73 const auto result = ValidateInstructions(env);
74 if (GetParam().expect_success) {
75 EXPECT_EQ(SPV_SUCCESS, result);
76 EXPECT_THAT(getDiagnosticString(), Eq(""));
77 } else {
78 EXPECT_EQ(SPV_ERROR_INVALID_ID, result);
79 EXPECT_THAT(getDiagnosticString(), HasSubstr(GetParam().expect_err));
80 }
81 }
82
83 #define GOOD_SHADER_10(STR) \
84 { SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, true, "" }
85 #define GOOD_KERNEL_10(STR) \
86 { SPV_ENV_UNIVERSAL_1_0, kKernelPreamble kBasicTypes STR, true, "" }
87 INSTANTIATE_TEST_CASE_P(
88 UniversalInShader, ValidateConstantOp,
89 ValuesIn(std::vector<ConstantOpCase>{
90 // TODO(dneto): Conversions must change width.
91 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
92 GOOD_SHADER_10("%v = OpSpecConstantOp %float FConvert %float_0"),
93 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
94 GOOD_SHADER_10("%v = OpSpecConstantOp %uint Not %uint_0"),
95 GOOD_SHADER_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
96 GOOD_SHADER_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
97 GOOD_SHADER_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
98 GOOD_SHADER_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
99 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
100 GOOD_SHADER_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
101 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
102 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
103 GOOD_SHADER_10(
104 "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
105 GOOD_SHADER_10(
106 "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
107 GOOD_SHADER_10(
108 "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
109 GOOD_SHADER_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
110 GOOD_SHADER_10(
111 "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
112 GOOD_SHADER_10(
113 "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
114 GOOD_SHADER_10(
115 "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
116 GOOD_SHADER_10(
117 "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
118 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
119 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
120 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
121 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
122 GOOD_SHADER_10(
123 "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
124 GOOD_SHADER_10(
125 "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
126 GOOD_SHADER_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
127 GOOD_SHADER_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
128 GOOD_SHADER_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
129 GOOD_SHADER_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
130 GOOD_SHADER_10(
131 "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
132 GOOD_SHADER_10(
133 "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
134 GOOD_SHADER_10(
135 "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
136 GOOD_SHADER_10(
137 "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
138 GOOD_SHADER_10(
139 "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
140 GOOD_SHADER_10(
141 "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
142 }));
143
144 INSTANTIATE_TEST_CASE_P(
145 UniversalInKernel, ValidateConstantOp,
146 ValuesIn(std::vector<ConstantOpCase>{
147 // TODO(dneto): Conversions must change width.
148 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
149 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FConvert %float_0"),
150 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
151 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Not %uint_0"),
152 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
153 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
154 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
155 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
156 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
157 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
158 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
159 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
160 GOOD_KERNEL_10(
161 "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
162 GOOD_KERNEL_10(
163 "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
164 GOOD_KERNEL_10(
165 "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
166 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
167 GOOD_KERNEL_10(
168 "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
169 GOOD_KERNEL_10(
170 "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
171 GOOD_KERNEL_10(
172 "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
173 GOOD_KERNEL_10(
174 "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
175 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
176 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
177 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
178 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
179 GOOD_KERNEL_10(
180 "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
181 GOOD_KERNEL_10(
182 "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
183 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
184 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
185 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
186 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
187 GOOD_KERNEL_10(
188 "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
189 GOOD_KERNEL_10(
190 "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
191 GOOD_KERNEL_10(
192 "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
193 GOOD_KERNEL_10(
194 "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
195 GOOD_KERNEL_10(
196 "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
197 GOOD_KERNEL_10(
198 "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
199 }));
200
201 INSTANTIATE_TEST_CASE_P(
202 KernelInKernel, ValidateConstantOp,
203 ValuesIn(std::vector<ConstantOpCase>{
204 // TODO(dneto): Conversions must change width.
205 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0"),
206 GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0"),
207 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0"),
208 GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0"),
209 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UConvert %uint_0"),
210 GOOD_KERNEL_10(
211 "%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null"),
212 GOOD_KERNEL_10(
213 "%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null"),
214 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Bitcast %uint_0"),
215 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FNegate %float_0"),
216 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0"),
217 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0"),
218 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0"),
219 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0"),
220 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0"),
221 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0"),
222 GOOD_KERNEL_10(
223 "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0"),
224 GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
225 "%null %uint_0"),
226 GOOD_KERNEL_10(
227 "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0"),
228 GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint "
229 "InBoundsPtrAccessChain %null %uint_0"),
230 }));
231
232 #define BAD_SHADER_10(STR, NAME) \
233 { \
234 SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, false, \
235 "Specialization constant operation " NAME \
236 " requires Kernel capability" \
237 }
238 INSTANTIATE_TEST_CASE_P(
239 KernelInShader, ValidateConstantOp,
240 ValuesIn(std::vector<ConstantOpCase>{
241 // TODO(dneto): Conversions must change width.
242 BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0",
243 "ConvertFToS"),
244 BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0",
245 "ConvertSToF"),
246 BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0",
247 "ConvertFToU"),
248 BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0",
249 "ConvertUToF"),
250 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null",
251 "GenericCastToPtr"),
252 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null",
253 "PtrCastToGeneric"),
254 BAD_SHADER_10("%v = OpSpecConstantOp %uint Bitcast %uint_0", "Bitcast"),
255 BAD_SHADER_10("%v = OpSpecConstantOp %float FNegate %float_0",
256 "FNegate"),
257 BAD_SHADER_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0",
258 "FAdd"),
259 BAD_SHADER_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0",
260 "FSub"),
261 BAD_SHADER_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0",
262 "FMul"),
263 BAD_SHADER_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0",
264 "FDiv"),
265 BAD_SHADER_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0",
266 "FRem"),
267 BAD_SHADER_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0",
268 "FMod"),
269 BAD_SHADER_10(
270 "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0",
271 "AccessChain"),
272 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
273 "%null %uint_0",
274 "InBoundsAccessChain"),
275 BAD_SHADER_10(
276 "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0",
277 "PtrAccessChain"),
278 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint "
279 "InBoundsPtrAccessChain %null %uint_0",
280 "InBoundsPtrAccessChain"),
281 }));
282
283 INSTANTIATE_TEST_CASE_P(
284 UConvertInAMD_gpu_shader_int16, ValidateConstantOp,
285 ValuesIn(std::vector<ConstantOpCase>{
286 // SPV_AMD_gpu_shader_int16 should enable UConvert for OpSpecConstantOp
287 // https://github.com/KhronosGroup/glslang/issues/848
288 {SPV_ENV_UNIVERSAL_1_0,
289 "OpCapability Shader "
290 "OpCapability Linkage ; So we don't need to define a function\n"
291 "OpExtension \"SPV_AMD_gpu_shader_int16\" "
292 "OpMemoryModel Logical Simple " kBasicTypes
293 "%v = OpSpecConstantOp %uint UConvert %uint_0",
294 true, ""},
295 }));
296
297 } // namespace
298 } // namespace val
299 } // namespace spvtools
300