1 // Copyright (c) 2019 The Khronos Group Inc.
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 // Validation tests for OpenCL env specific checks
16
17 #include <string>
18
19 #include "gmock/gmock.h"
20 #include "test/val/val_fixtures.h"
21
22 namespace spvtools {
23 namespace val {
24 namespace {
25
26 using testing::Eq;
27 using testing::HasSubstr;
28
29 using ValidateOpenCL = spvtest::ValidateBase<bool>;
30
TEST_F(ValidateOpenCL,NonPhysicalAddressingModelBad)31 TEST_F(ValidateOpenCL, NonPhysicalAddressingModelBad) {
32 std::string spirv = R"(
33 OpCapability Kernel
34 OpMemoryModel Logical OpenCL
35 )";
36
37 CompileSuccessfully(spirv);
38
39 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
40 EXPECT_THAT(getDiagnosticString(),
41 HasSubstr("Addressing model must be Physical32 or Physical64 "
42 "in the OpenCL environment.\n OpMemoryModel Logical "
43 "OpenCL\n"));
44 }
45
TEST_F(ValidateOpenCL,NonOpenCLMemoryModelBad)46 TEST_F(ValidateOpenCL, NonOpenCLMemoryModelBad) {
47 std::string spirv = R"(
48 OpCapability Kernel
49 OpCapability Addresses
50 OpCapability VulkanMemoryModelKHR
51 OpExtension "SPV_KHR_vulkan_memory_model"
52 OpMemoryModel Physical32 VulkanKHR
53 )";
54
55 CompileSuccessfully(spirv);
56
57 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
58 EXPECT_THAT(
59 getDiagnosticString(),
60 HasSubstr("Memory model must be OpenCL in the OpenCL environment."));
61 }
62
TEST_F(ValidateOpenCL,NonVoidSampledTypeImageBad)63 TEST_F(ValidateOpenCL, NonVoidSampledTypeImageBad) {
64 std::string spirv = R"(
65 OpCapability Addresses
66 OpCapability Kernel
67 OpMemoryModel Physical32 OpenCL
68 %1 = OpTypeInt 32 0
69 %2 = OpTypeImage %1 2D 0 0 0 0 Unknown ReadOnly
70 )";
71
72 CompileSuccessfully(spirv);
73
74 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
75 EXPECT_THAT(
76 getDiagnosticString(),
77 HasSubstr("Sampled Type must be OpTypeVoid in the OpenCL environment."
78 "\n %2 = OpTypeImage %uint 2D 0 0 0 0 Unknown ReadOnly\n"));
79 }
80
TEST_F(ValidateOpenCL,NonZeroMSImageBad)81 TEST_F(ValidateOpenCL, NonZeroMSImageBad) {
82 std::string spirv = R"(
83 OpCapability Addresses
84 OpCapability Kernel
85 OpMemoryModel Physical32 OpenCL
86 %1 = OpTypeVoid
87 %2 = OpTypeImage %1 2D 0 0 1 0 Unknown ReadOnly
88 )";
89
90 CompileSuccessfully(spirv);
91
92 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
93 EXPECT_THAT(
94 getDiagnosticString(),
95 HasSubstr("MS must be 0 in the OpenCL environment."
96 "\n %2 = OpTypeImage %void 2D 0 0 1 0 Unknown ReadOnly\n"));
97 }
98
TEST_F(ValidateOpenCL,Non1D2DArrayedImageBad)99 TEST_F(ValidateOpenCL, Non1D2DArrayedImageBad) {
100 std::string spirv = R"(
101 OpCapability Addresses
102 OpCapability Kernel
103 OpMemoryModel Physical32 OpenCL
104 %1 = OpTypeVoid
105 %2 = OpTypeImage %1 3D 0 1 0 0 Unknown ReadOnly
106 )";
107
108 CompileSuccessfully(spirv);
109
110 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
111 EXPECT_THAT(
112 getDiagnosticString(),
113 HasSubstr("In the OpenCL environment, Arrayed may only be set to 1 "
114 "when Dim is either 1D or 2D."
115 "\n %2 = OpTypeImage %void 3D 0 1 0 0 Unknown ReadOnly\n"));
116 }
117
TEST_F(ValidateOpenCL,NonZeroSampledImageBad)118 TEST_F(ValidateOpenCL, NonZeroSampledImageBad) {
119 std::string spirv = R"(
120 OpCapability Addresses
121 OpCapability Kernel
122 OpMemoryModel Physical32 OpenCL
123 %1 = OpTypeVoid
124 %2 = OpTypeImage %1 3D 0 0 0 1 Unknown ReadOnly
125 )";
126
127 CompileSuccessfully(spirv);
128
129 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
130 EXPECT_THAT(
131 getDiagnosticString(),
132 HasSubstr("Sampled must be 0 in the OpenCL environment."
133 "\n %2 = OpTypeImage %void 3D 0 0 0 1 Unknown ReadOnly\n"));
134 }
135
TEST_F(ValidateOpenCL,NoAccessQualifierImageBad)136 TEST_F(ValidateOpenCL, NoAccessQualifierImageBad) {
137 std::string spirv = R"(
138 OpCapability Addresses
139 OpCapability Kernel
140 OpMemoryModel Physical32 OpenCL
141 %1 = OpTypeVoid
142 %2 = OpTypeImage %1 3D 0 0 0 0 Unknown
143 )";
144
145 CompileSuccessfully(spirv);
146
147 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
148 EXPECT_THAT(getDiagnosticString(),
149 HasSubstr("In the OpenCL environment, the optional "
150 "Access Qualifier must be present."
151 "\n %2 = OpTypeImage %void 3D 0 0 0 0 Unknown\n"));
152 }
153
TEST_F(ValidateOpenCL,ImageWriteWithOptionalImageOperandsBad)154 TEST_F(ValidateOpenCL, ImageWriteWithOptionalImageOperandsBad) {
155 std::string spirv = R"(
156 OpCapability Addresses
157 OpCapability Kernel
158 OpCapability ImageBasic
159 OpMemoryModel Physical64 OpenCL
160 OpEntryPoint Kernel %5 "test"
161 %uint = OpTypeInt 32 0
162 %uint_7 = OpConstant %uint 7
163 %uint_3 = OpConstant %uint 3
164 %uint_1 = OpConstant %uint 1
165 %uint_2 = OpConstant %uint 2
166 %uint_4 = OpConstant %uint 4
167 %void = OpTypeVoid
168 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown WriteOnly
169 %4 = OpTypeFunction %void %3
170 %v2uint = OpTypeVector %uint 2
171 %v4uint = OpTypeVector %uint 4
172 %12 = OpConstantComposite %v2uint %uint_7 %uint_3
173 %17 = OpConstantComposite %v4uint %uint_1 %uint_2 %uint_3 %uint_4
174 %5 = OpFunction %void None %4
175 %img = OpFunctionParameter %3
176 %entry = OpLabel
177 OpImageWrite %img %12 %17 ConstOffset %12
178 OpReturn
179 OpFunctionEnd
180 )";
181
182 CompileSuccessfully(spirv);
183
184 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
185 EXPECT_THAT(getDiagnosticString(),
186 HasSubstr("Optional Image Operands are not allowed in the "
187 "OpenCL environment."
188 "\n OpImageWrite %15 %13 %14 ConstOffset %13\n"));
189 }
190
TEST_F(ValidateOpenCL,ImageReadWithConstOffsetBad)191 TEST_F(ValidateOpenCL, ImageReadWithConstOffsetBad) {
192 std::string spirv = R"(
193 OpCapability Addresses
194 OpCapability Kernel
195 OpCapability ImageBasic
196 OpMemoryModel Physical64 OpenCL
197 OpEntryPoint Kernel %5 "image_kernel"
198 OpName %img "img"
199 OpName %coord "coord"
200 OpName %call "call"
201 %uint = OpTypeInt 32 0
202 %uint_7 = OpConstant %uint 7
203 %uint_3 = OpConstant %uint 3
204 %void = OpTypeVoid
205 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
206 %4 = OpTypeFunction %void %3
207 %v4uint = OpTypeVector %uint 4
208 %v2uint = OpTypeVector %uint 2
209 %coord = OpConstantComposite %v2uint %uint_7 %uint_3
210 %5 = OpFunction %void None %4
211 %img = OpFunctionParameter %3
212 %entry = OpLabel
213 %call = OpImageRead %v4uint %img %coord ConstOffset %coord
214 OpReturn
215 OpFunctionEnd
216 )";
217
218 CompileSuccessfully(spirv);
219
220 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
221 EXPECT_THAT(
222 getDiagnosticString(),
223 HasSubstr(
224 "ConstOffset image operand not allowed in the OpenCL environment."
225 "\n %call = OpImageRead %v4uint %img %coord ConstOffset %coord\n"));
226 }
227
TEST_F(ValidateOpenCL,ImageRead_NonDepthScalarFloatResult_Bad)228 TEST_F(ValidateOpenCL, ImageRead_NonDepthScalarFloatResult_Bad) {
229 std::string spirv = R"(
230 OpCapability Addresses
231 OpCapability Kernel
232 OpCapability ImageBasic
233 OpMemoryModel Physical64 OpenCL
234 OpEntryPoint Kernel %5 "image_kernel"
235 OpName %img "img"
236 OpName %coord "coord"
237 OpName %call "call"
238 %uint = OpTypeInt 32 0
239 %v2uint = OpTypeVector %uint 2
240 %coord = OpConstantNull %v2uint
241 %void = OpTypeVoid
242 %float = OpTypeFloat 32
243 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
244 %4 = OpTypeFunction %void %3
245 %5 = OpFunction %void None %4
246 %img = OpFunctionParameter %3
247 %entry = OpLabel
248 %call = OpImageRead %float %img %coord
249 OpReturn
250 OpFunctionEnd
251 )";
252
253 CompileSuccessfully(spirv);
254
255 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
256 EXPECT_THAT(getDiagnosticString(),
257 HasSubstr("Expected Result Type to have 4 components"));
258 }
259
TEST_F(ValidateOpenCL,ImageRead_NonDepthScalarIntResult_Bad)260 TEST_F(ValidateOpenCL, ImageRead_NonDepthScalarIntResult_Bad) {
261 std::string spirv = R"(
262 OpCapability Addresses
263 OpCapability Kernel
264 OpCapability ImageBasic
265 OpMemoryModel Physical64 OpenCL
266 OpEntryPoint Kernel %5 "image_kernel"
267 OpName %img "img"
268 OpName %coord "coord"
269 OpName %call "call"
270 %uint = OpTypeInt 32 0
271 %v2uint = OpTypeVector %uint 2
272 %coord = OpConstantNull %v2uint
273 %void = OpTypeVoid
274 %float = OpTypeFloat 32
275 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
276 %4 = OpTypeFunction %void %3
277 %5 = OpFunction %void None %4
278 %img = OpFunctionParameter %3
279 %entry = OpLabel
280 %call = OpImageRead %uint %img %coord
281 OpReturn
282 OpFunctionEnd
283 )";
284
285 CompileSuccessfully(spirv);
286
287 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
288 EXPECT_THAT(getDiagnosticString(),
289 HasSubstr("Expected Result Type to have 4 components"));
290 }
291
TEST_F(ValidateOpenCL,ImageRead_NonDepthVector3FloatResult_Bad)292 TEST_F(ValidateOpenCL, ImageRead_NonDepthVector3FloatResult_Bad) {
293 std::string spirv = R"(
294 OpCapability Addresses
295 OpCapability Kernel
296 OpCapability ImageBasic
297 OpMemoryModel Physical64 OpenCL
298 OpEntryPoint Kernel %5 "image_kernel"
299 OpName %img "img"
300 OpName %coord "coord"
301 OpName %call "call"
302 %uint = OpTypeInt 32 0
303 %v2uint = OpTypeVector %uint 2
304 %coord = OpConstantNull %v2uint
305 %void = OpTypeVoid
306 %float = OpTypeFloat 32
307 %v3float = OpTypeVector %float 3
308 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
309 %4 = OpTypeFunction %void %3
310 %5 = OpFunction %void None %4
311 %img = OpFunctionParameter %3
312 %entry = OpLabel
313 %call = OpImageRead %v3float %img %coord
314 OpReturn
315 OpFunctionEnd
316 )";
317
318 CompileSuccessfully(spirv);
319
320 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
321 EXPECT_THAT(getDiagnosticString(),
322 HasSubstr("Expected Result Type to have 4 components"));
323 }
324
TEST_F(ValidateOpenCL,ImageRead_NonDepthVector4FloatResult_Ok)325 TEST_F(ValidateOpenCL, ImageRead_NonDepthVector4FloatResult_Ok) {
326 std::string spirv = R"(
327 OpCapability Addresses
328 OpCapability Kernel
329 OpCapability ImageBasic
330 OpMemoryModel Physical64 OpenCL
331 OpEntryPoint Kernel %5 "image_kernel"
332 OpName %img "img"
333 OpName %coord "coord"
334 OpName %call "call"
335 %uint = OpTypeInt 32 0
336 %v2uint = OpTypeVector %uint 2
337 %coord = OpConstantNull %v2uint
338 %void = OpTypeVoid
339 %float = OpTypeFloat 32
340 %v4float = OpTypeVector %float 4
341 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
342 %4 = OpTypeFunction %void %3
343 %5 = OpFunction %void None %4
344 %img = OpFunctionParameter %3
345 %entry = OpLabel
346 %call = OpImageRead %v4float %img %coord
347 OpReturn
348 OpFunctionEnd
349 )";
350
351 CompileSuccessfully(spirv);
352
353 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
354 EXPECT_THAT(getDiagnosticString(), Eq(""));
355 }
356
TEST_F(ValidateOpenCL,ImageRead_NonDepthVector4IntResult_Ok)357 TEST_F(ValidateOpenCL, ImageRead_NonDepthVector4IntResult_Ok) {
358 std::string spirv = R"(
359 OpCapability Addresses
360 OpCapability Kernel
361 OpCapability ImageBasic
362 OpMemoryModel Physical64 OpenCL
363 OpEntryPoint Kernel %5 "image_kernel"
364 OpName %img "img"
365 OpName %coord "coord"
366 OpName %call "call"
367 %uint = OpTypeInt 32 0
368 %v2uint = OpTypeVector %uint 2
369 %coord = OpConstantNull %v2uint
370 %void = OpTypeVoid
371 %v4uint = OpTypeVector %uint 4
372 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
373 %4 = OpTypeFunction %void %3
374 %5 = OpFunction %void None %4
375 %img = OpFunctionParameter %3
376 %entry = OpLabel
377 %call = OpImageRead %v4uint %img %coord
378 OpReturn
379 OpFunctionEnd
380 )";
381
382 CompileSuccessfully(spirv);
383
384 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
385 EXPECT_THAT(getDiagnosticString(), Eq(""));
386 }
387
TEST_F(ValidateOpenCL,ImageRead_DepthScalarFloatResult_Ok)388 TEST_F(ValidateOpenCL, ImageRead_DepthScalarFloatResult_Ok) {
389 std::string spirv = R"(
390 OpCapability Addresses
391 OpCapability Kernel
392 OpCapability ImageBasic
393 OpMemoryModel Physical64 OpenCL
394 OpEntryPoint Kernel %5 "image_kernel"
395 OpName %img "img"
396 OpName %coord "coord"
397 OpName %call "call"
398 %uint = OpTypeInt 32 0
399 %v2uint = OpTypeVector %uint 2
400 %coord = OpConstantNull %v2uint
401 %void = OpTypeVoid
402 %float = OpTypeFloat 32
403 %3 = OpTypeImage %void 2D 1 0 0 0 Unknown ReadOnly
404 %4 = OpTypeFunction %void %3
405 %5 = OpFunction %void None %4
406 %img = OpFunctionParameter %3
407 %entry = OpLabel
408 %call = OpImageRead %float %img %coord
409 OpReturn
410 OpFunctionEnd
411 )";
412
413 CompileSuccessfully(spirv);
414
415 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
416 EXPECT_THAT(getDiagnosticString(), Eq(""));
417 }
418
TEST_F(ValidateOpenCL,ImageRead_DepthScalarIntResult_Bad)419 TEST_F(ValidateOpenCL, ImageRead_DepthScalarIntResult_Bad) {
420 std::string spirv = R"(
421 OpCapability Addresses
422 OpCapability Kernel
423 OpCapability ImageBasic
424 OpMemoryModel Physical64 OpenCL
425 OpEntryPoint Kernel %5 "image_kernel"
426 OpName %img "img"
427 OpName %coord "coord"
428 OpName %call "call"
429 %uint = OpTypeInt 32 0
430 %v2uint = OpTypeVector %uint 2
431 %coord = OpConstantNull %v2uint
432 %void = OpTypeVoid
433 %float = OpTypeFloat 32
434 %3 = OpTypeImage %void 2D 1 0 0 0 Unknown ReadOnly
435 %4 = OpTypeFunction %void %3
436 %5 = OpFunction %void None %4
437 %img = OpFunctionParameter %3
438 %entry = OpLabel
439 %call = OpImageRead %uint %img %coord
440 OpReturn
441 OpFunctionEnd
442 )";
443
444 CompileSuccessfully(spirv);
445
446 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
447 EXPECT_THAT(getDiagnosticString(),
448 HasSubstr("Expected Result Type from a depth image "
449 "read to result in a scalar float value"));
450 }
451
TEST_F(ValidateOpenCL,ImageRead_DepthVectorFloatResult_Bad)452 TEST_F(ValidateOpenCL, ImageRead_DepthVectorFloatResult_Bad) {
453 std::string spirv = R"(
454 OpCapability Addresses
455 OpCapability Kernel
456 OpCapability ImageBasic
457 OpMemoryModel Physical64 OpenCL
458 OpEntryPoint Kernel %5 "image_kernel"
459 OpName %img "img"
460 OpName %coord "coord"
461 OpName %call "call"
462 %uint = OpTypeInt 32 0
463 %v2uint = OpTypeVector %uint 2
464 %coord = OpConstantNull %v2uint
465 %void = OpTypeVoid
466 %float = OpTypeFloat 32
467 %v4float = OpTypeVector %float 4
468 %3 = OpTypeImage %void 2D 1 0 0 0 Unknown ReadOnly
469 %4 = OpTypeFunction %void %3
470 %5 = OpFunction %void None %4
471 %img = OpFunctionParameter %3
472 %entry = OpLabel
473 %call = OpImageRead %v4float %img %coord
474 OpReturn
475 OpFunctionEnd
476 )";
477
478 CompileSuccessfully(spirv);
479
480 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
481 EXPECT_THAT(getDiagnosticString(),
482 HasSubstr("Expected Result Type from a depth image "
483 "read to result in a scalar float value"));
484 }
485
TEST_F(ValidateOpenCL,ImageSampleExplicitLodWithConstOffsetBad)486 TEST_F(ValidateOpenCL, ImageSampleExplicitLodWithConstOffsetBad) {
487 std::string spirv = R"(
488 OpCapability Addresses
489 OpCapability Kernel
490 OpCapability ImageBasic
491 OpCapability LiteralSampler
492 OpMemoryModel Physical64 OpenCL
493 OpEntryPoint Kernel %5 "image_kernel"
494 OpName %img "img"
495 OpName %coord "coord"
496 OpName %call "call"
497 %uint = OpTypeInt 32 0
498 %v2uint = OpTypeVector %uint 2
499 %coord = OpConstantNull %v2uint
500 %void = OpTypeVoid
501 %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
502 %4 = OpTypeFunction %void %3
503 %8 = OpTypeSampler
504 %10 = OpTypeSampledImage %3
505 %v4uint = OpTypeVector %uint 4
506 %float = OpTypeFloat 32
507 %9 = OpConstantSampler %8 None 0 Nearest
508 %float_0 = OpConstant %float 0
509 %5 = OpFunction %void None %4
510 %6 = OpFunctionParameter %3
511 %entry = OpLabel
512 %img = OpSampledImage %10 %6 %9
513 %call = OpImageSampleExplicitLod %v4uint %img %coord
514 Lod|ConstOffset %float_0 %coord
515 OpReturn
516 OpFunctionEnd
517 )";
518
519 CompileSuccessfully(spirv);
520
521 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
522 EXPECT_THAT(
523 getDiagnosticString(),
524 HasSubstr(
525 "ConstOffset image operand not allowed in the OpenCL environment."
526 "\n %call = OpImageSampleExplicitLod %v4uint %img "
527 "%coord Lod|ConstOffset %float_0 %coord\n"));
528 }
529
530 } // namespace
531 } // namespace val
532 } // namespace spvtools
533