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 22namespace spvtools { 23namespace val { 24namespace { 25 26using testing::Eq; 27using testing::HasSubstr; 28 29using ValidateOpenCL = spvtest::ValidateBase<bool>; 30 31TEST_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 46TEST_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 63TEST_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 81TEST_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 99TEST_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 118TEST_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 136TEST_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 154TEST_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 191TEST_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 228TEST_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 260TEST_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 292TEST_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 325TEST_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 357TEST_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 388TEST_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 419TEST_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 452TEST_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 486TEST_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