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_code_generator.h"
26 #include "test/val/val_fixtures.h"
27
28 namespace spvtools {
29 namespace val {
30 namespace {
31
32 using ::testing::Combine;
33 using ::testing::Eq;
34 using ::testing::HasSubstr;
35 using ::testing::Values;
36 using ::testing::ValuesIn;
37
38 using ValidateConstant = spvtest::ValidateBase<bool>;
39
40 #define kBasicTypes \
41 "%bool = OpTypeBool " \
42 "%uint = OpTypeInt 32 0 " \
43 "%uint2 = OpTypeVector %uint 2 " \
44 "%float = OpTypeFloat 32 " \
45 "%_ptr_uint = OpTypePointer Workgroup %uint " \
46 "%uint_0 = OpConstantNull %uint " \
47 "%uint2_0 = OpConstantNull %uint " \
48 "%float_0 = OpConstantNull %float " \
49 "%false = OpConstantFalse %bool " \
50 "%true = OpConstantTrue %bool " \
51 "%null = OpConstantNull %_ptr_uint "
52
53 #define kShaderPreamble \
54 "OpCapability Shader\n" \
55 "OpCapability Linkage\n" \
56 "OpMemoryModel Logical Simple\n"
57
58 #define kKernelPreamble \
59 "OpCapability Kernel\n" \
60 "OpCapability Linkage\n" \
61 "OpCapability Addresses\n" \
62 "OpMemoryModel Physical32 OpenCL\n"
63
64 struct ConstantOpCase {
65 spv_target_env env;
66 std::string assembly;
67 bool expect_success;
68 std::string expect_err;
69 };
70
71 using ValidateConstantOp = spvtest::ValidateBase<ConstantOpCase>;
72
TEST_P(ValidateConstantOp,Samples)73 TEST_P(ValidateConstantOp, Samples) {
74 const auto env = GetParam().env;
75 CompileSuccessfully(GetParam().assembly, env);
76 const auto result = ValidateInstructions(env);
77 if (GetParam().expect_success) {
78 EXPECT_EQ(SPV_SUCCESS, result);
79 EXPECT_THAT(getDiagnosticString(), Eq(""));
80 } else {
81 EXPECT_EQ(SPV_ERROR_INVALID_ID, result);
82 EXPECT_THAT(getDiagnosticString(), HasSubstr(GetParam().expect_err));
83 }
84 }
85
86 #define GOOD_SHADER_10(STR) \
87 { SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, true, "" }
88 #define GOOD_KERNEL_10(STR) \
89 { SPV_ENV_UNIVERSAL_1_0, kKernelPreamble kBasicTypes STR, true, "" }
90 INSTANTIATE_TEST_SUITE_P(
91 UniversalInShader, ValidateConstantOp,
92 ValuesIn(std::vector<ConstantOpCase>{
93 // TODO(dneto): Conversions must change width.
94 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
95 GOOD_SHADER_10("%v = OpSpecConstantOp %float FConvert %float_0"),
96 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
97 GOOD_SHADER_10("%v = OpSpecConstantOp %uint Not %uint_0"),
98 GOOD_SHADER_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
99 GOOD_SHADER_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
100 GOOD_SHADER_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
101 GOOD_SHADER_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
102 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
103 GOOD_SHADER_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
104 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
105 GOOD_SHADER_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
106 GOOD_SHADER_10(
107 "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
108 GOOD_SHADER_10(
109 "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
110 GOOD_SHADER_10(
111 "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
112 GOOD_SHADER_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
113 GOOD_SHADER_10(
114 "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
115 GOOD_SHADER_10(
116 "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
117 GOOD_SHADER_10(
118 "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
119 GOOD_SHADER_10(
120 "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
121 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
122 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
123 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
124 GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
125 GOOD_SHADER_10(
126 "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
127 GOOD_SHADER_10(
128 "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
129 GOOD_SHADER_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
130 GOOD_SHADER_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
131 GOOD_SHADER_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
132 GOOD_SHADER_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
133 GOOD_SHADER_10(
134 "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
135 GOOD_SHADER_10(
136 "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
137 GOOD_SHADER_10(
138 "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
139 GOOD_SHADER_10(
140 "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
141 GOOD_SHADER_10(
142 "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
143 GOOD_SHADER_10(
144 "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
145 }));
146
147 INSTANTIATE_TEST_SUITE_P(
148 UniversalInKernel, ValidateConstantOp,
149 ValuesIn(std::vector<ConstantOpCase>{
150 // TODO(dneto): Conversions must change width.
151 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
152 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FConvert %float_0"),
153 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
154 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Not %uint_0"),
155 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
156 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
157 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
158 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
159 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
160 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
161 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
162 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
163 GOOD_KERNEL_10(
164 "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
165 GOOD_KERNEL_10(
166 "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
167 GOOD_KERNEL_10(
168 "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
169 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
170 GOOD_KERNEL_10(
171 "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
172 GOOD_KERNEL_10(
173 "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
174 GOOD_KERNEL_10(
175 "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
176 GOOD_KERNEL_10(
177 "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
178 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
179 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
180 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
181 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
182 GOOD_KERNEL_10(
183 "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
184 GOOD_KERNEL_10(
185 "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
186 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
187 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
188 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
189 GOOD_KERNEL_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
190 GOOD_KERNEL_10(
191 "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
192 GOOD_KERNEL_10(
193 "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
194 GOOD_KERNEL_10(
195 "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
196 GOOD_KERNEL_10(
197 "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
198 GOOD_KERNEL_10(
199 "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
200 GOOD_KERNEL_10(
201 "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
202 }));
203
204 INSTANTIATE_TEST_SUITE_P(
205 UConvert, ValidateConstantOp,
206 ValuesIn(std::vector<ConstantOpCase>{
207 // TODO(dneto): Conversions must change width.
208 {SPV_ENV_UNIVERSAL_1_0,
209 kKernelPreamble kBasicTypes
210 "%v = OpSpecConstantOp %uint UConvert %uint_0",
211 true, ""},
212 {SPV_ENV_UNIVERSAL_1_1,
213 kKernelPreamble kBasicTypes
214 "%v = OpSpecConstantOp %uint UConvert %uint_0",
215 true, ""},
216 {SPV_ENV_UNIVERSAL_1_3,
217 kKernelPreamble kBasicTypes
218 "%v = OpSpecConstantOp %uint UConvert %uint_0",
219 true, ""},
220 {SPV_ENV_UNIVERSAL_1_3,
221 kKernelPreamble kBasicTypes
222 "%v = OpSpecConstantOp %uint UConvert %uint_0",
223 true, ""},
224 {SPV_ENV_UNIVERSAL_1_4,
225 kKernelPreamble kBasicTypes
226 "%v = OpSpecConstantOp %uint UConvert %uint_0",
227 true, ""},
228 {SPV_ENV_UNIVERSAL_1_0,
229 kShaderPreamble kBasicTypes
230 "%v = OpSpecConstantOp %uint UConvert %uint_0",
231 false,
232 "Prior to SPIR-V 1.4, specialization constant operation "
233 "UConvert requires Kernel capability"},
234 {SPV_ENV_UNIVERSAL_1_1,
235 kShaderPreamble kBasicTypes
236 "%v = OpSpecConstantOp %uint UConvert %uint_0",
237 false,
238 "Prior to SPIR-V 1.4, specialization constant operation "
239 "UConvert requires Kernel capability"},
240 {SPV_ENV_UNIVERSAL_1_3,
241 kShaderPreamble kBasicTypes
242 "%v = OpSpecConstantOp %uint UConvert %uint_0",
243 false,
244 "Prior to SPIR-V 1.4, specialization constant operation "
245 "UConvert requires Kernel capability"},
246 {SPV_ENV_UNIVERSAL_1_3,
247 kShaderPreamble kBasicTypes
248 "%v = OpSpecConstantOp %uint UConvert %uint_0",
249 false,
250 "Prior to SPIR-V 1.4, specialization constant operation "
251 "UConvert requires Kernel capability"},
252 {SPV_ENV_UNIVERSAL_1_4,
253 kShaderPreamble kBasicTypes
254 "%v = OpSpecConstantOp %uint UConvert %uint_0",
255 true, ""},
256 }));
257
258 INSTANTIATE_TEST_SUITE_P(
259 KernelInKernel, ValidateConstantOp,
260 ValuesIn(std::vector<ConstantOpCase>{
261 // TODO(dneto): Conversions must change width.
262 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0"),
263 GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0"),
264 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0"),
265 GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0"),
266 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UConvert %uint_0"),
267 GOOD_KERNEL_10(
268 "%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null"),
269 GOOD_KERNEL_10(
270 "%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null"),
271 GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Bitcast %uint_0"),
272 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FNegate %float_0"),
273 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0"),
274 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0"),
275 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0"),
276 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0"),
277 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0"),
278 GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0"),
279 GOOD_KERNEL_10(
280 "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0"),
281 GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
282 "%null %uint_0"),
283 GOOD_KERNEL_10(
284 "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0"),
285 GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint "
286 "InBoundsPtrAccessChain %null %uint_0"),
287 }));
288
289 #define BAD_SHADER_10(STR, NAME) \
290 { \
291 SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, false, \
292 "Specialization constant operation " NAME \
293 " requires Kernel capability" \
294 }
295 INSTANTIATE_TEST_SUITE_P(
296 KernelInShader, ValidateConstantOp,
297 ValuesIn(std::vector<ConstantOpCase>{
298 // TODO(dneto): Conversions must change width.
299 BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0",
300 "ConvertFToS"),
301 BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0",
302 "ConvertSToF"),
303 BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0",
304 "ConvertFToU"),
305 BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0",
306 "ConvertUToF"),
307 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null",
308 "GenericCastToPtr"),
309 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null",
310 "PtrCastToGeneric"),
311 BAD_SHADER_10("%v = OpSpecConstantOp %uint Bitcast %uint_0", "Bitcast"),
312 BAD_SHADER_10("%v = OpSpecConstantOp %float FNegate %float_0",
313 "FNegate"),
314 BAD_SHADER_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0",
315 "FAdd"),
316 BAD_SHADER_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0",
317 "FSub"),
318 BAD_SHADER_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0",
319 "FMul"),
320 BAD_SHADER_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0",
321 "FDiv"),
322 BAD_SHADER_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0",
323 "FRem"),
324 BAD_SHADER_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0",
325 "FMod"),
326 BAD_SHADER_10(
327 "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0",
328 "AccessChain"),
329 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
330 "%null %uint_0",
331 "InBoundsAccessChain"),
332 BAD_SHADER_10(
333 "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0",
334 "PtrAccessChain"),
335 BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint "
336 "InBoundsPtrAccessChain %null %uint_0",
337 "InBoundsPtrAccessChain"),
338 }));
339
340 INSTANTIATE_TEST_SUITE_P(
341 UConvertInAMD_gpu_shader_int16, ValidateConstantOp,
342 ValuesIn(std::vector<ConstantOpCase>{
343 // SPV_AMD_gpu_shader_int16 should enable UConvert for OpSpecConstantOp
344 // https://github.com/KhronosGroup/glslang/issues/848
345 {SPV_ENV_UNIVERSAL_1_0,
346 "OpCapability Shader "
347 "OpCapability Linkage ; So we don't need to define a function\n"
348 "OpExtension \"SPV_AMD_gpu_shader_int16\" "
349 "OpMemoryModel Logical Simple " kBasicTypes
350 "%v = OpSpecConstantOp %uint UConvert %uint_0",
351 true, ""},
352 }));
353
TEST_F(ValidateConstant,SpecConstantUConvert1p3Binary1p4EnvBad)354 TEST_F(ValidateConstant, SpecConstantUConvert1p3Binary1p4EnvBad) {
355 const std::string spirv = R"(
356 OpCapability Shader
357 OpCapability Linkage
358 OpMemoryModel Logical GLSL450
359 %int = OpTypeInt 32 0
360 %int0 = OpConstant %int 0
361 %const = OpSpecConstantOp %int UConvert %int0
362 )";
363
364 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
365 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
366 EXPECT_THAT(
367 getDiagnosticString(),
368 HasSubstr(
369 "Prior to SPIR-V 1.4, specialization constant operation UConvert "
370 "requires Kernel capability or extension SPV_AMD_gpu_shader_int16"));
371 }
372
373 using SmallStorageConstants = spvtest::ValidateBase<std::string>;
374
GetSmallStorageCodeGenerator()375 CodeGenerator GetSmallStorageCodeGenerator() {
376 CodeGenerator generator;
377 generator.capabilities_ = R"(
378 OpCapability Shader
379 OpCapability Linkage
380 OpCapability UniformAndStorageBuffer16BitAccess
381 OpCapability StoragePushConstant16
382 OpCapability StorageInputOutput16
383 OpCapability UniformAndStorageBuffer8BitAccess
384 OpCapability StoragePushConstant8
385 )";
386 generator.extensions_ = R"(
387 OpExtension "SPV_KHR_16bit_storage"
388 OpExtension "SPV_KHR_8bit_storage"
389 )";
390 generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
391 generator.types_ = R"(
392 %short = OpTypeInt 16 0
393 %short2 = OpTypeVector %short 2
394 %char = OpTypeInt 8 0
395 %char2 = OpTypeVector %char 2
396 %half = OpTypeFloat 16
397 %half2 = OpTypeVector %half 2
398 %int = OpTypeInt 32 0
399 %int_0 = OpConstant %int 0
400 %float = OpTypeFloat 32
401 %float_0 = OpConstant %float 0
402 )";
403 return generator;
404 }
405
TEST_P(SmallStorageConstants,SmallConstant)406 TEST_P(SmallStorageConstants, SmallConstant) {
407 std::string constant = GetParam();
408 CodeGenerator generator = GetSmallStorageCodeGenerator();
409 generator.after_types_ += constant + "\n";
410 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
411 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
412 EXPECT_THAT(getDiagnosticString(),
413 HasSubstr("Cannot form constants of 8- or 16-bit types"));
414 }
415
416 // Constant composites would be caught through scalar constants.
417 INSTANTIATE_TEST_SUITE_P(
418 SmallConstants, SmallStorageConstants,
419 Values("%c = OpConstant %char 0", "%c = OpConstantNull %char2",
420 "%c = OpConstant %short 0", "%c = OpConstantNull %short",
421 "%c = OpConstant %half 0", "%c = OpConstantNull %half",
422 "%c = OpSpecConstant %char 0", "%c = OpSpecConstant %short 0",
423 "%c = OpSpecConstant %half 0",
424 "%c = OpSpecConstantOp %char SConvert %int_0",
425 "%c = OpSpecConstantOp %short SConvert %int_0",
426 "%c = OpSpecConstantOp %half FConvert %float_0"));
427
TEST_F(ValidateConstant,NullPointerTo16BitStorageOk)428 TEST_F(ValidateConstant, NullPointerTo16BitStorageOk) {
429 std::string spirv = R"(
430 OpCapability Shader
431 OpCapability VariablePointersStorageBuffer
432 OpCapability UniformAndStorageBuffer16BitAccess
433 OpCapability Linkage
434 OpExtension "SPV_KHR_16bit_storage"
435 OpMemoryModel Logical GLSL450
436 %half = OpTypeFloat 16
437 %ptr_ssbo_half = OpTypePointer StorageBuffer %half
438 %null_ptr = OpConstantNull %ptr_ssbo_half
439 )";
440
441 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
442 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
443 }
444
TEST_F(ValidateConstant,NullMatrix)445 TEST_F(ValidateConstant, NullMatrix) {
446 std::string spirv = R"(
447 OpCapability Shader
448 OpCapability Linkage
449 OpMemoryModel Logical GLSL450
450 %float = OpTypeFloat 32
451 %v2float = OpTypeVector %float 2
452 %mat2x2 = OpTypeMatrix %v2float 2
453 %null_vector = OpConstantNull %v2float
454 %null_matrix = OpConstantComposite %mat2x2 %null_vector %null_vector
455 )";
456
457 CompileSuccessfully(spirv);
458 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
459 }
460
TEST_F(ValidateConstant,NullPhysicalStorageBuffer)461 TEST_F(ValidateConstant, NullPhysicalStorageBuffer) {
462 std::string spirv = R"(
463 OpCapability Shader
464 OpCapability PhysicalStorageBufferAddresses
465 OpCapability Linkage
466 OpExtension "SPV_KHR_physical_storage_buffer"
467 OpMemoryModel PhysicalStorageBuffer64 GLSL450
468 OpName %ptr "ptr"
469 %int = OpTypeInt 32 0
470 %ptr = OpTypePointer PhysicalStorageBuffer %int
471 %null = OpConstantNull %ptr
472 )";
473
474 CompileSuccessfully(spirv);
475 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
476 EXPECT_THAT(getDiagnosticString(),
477 HasSubstr("OpConstantNull Result Type <id> '1[%ptr]' cannot have "
478 "a null value"));
479 }
480
481 } // namespace
482 } // namespace val
483 } // namespace spvtools
484