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