1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // validationCL.cpp: Validation functions for generic CL entry point parameters
7 // based on the OpenCL Specification V3.0.7, see https://www.khronos.org/registry/OpenCL/
8 // Each used CL error code is preceeded by a citation of the relevant rule in the spec.
9
10 #include "libANGLE/validationCL_autogen.h"
11
12 #include "common/string_utils.h"
13
14 #include "libANGLE/cl_utils.h"
15
16 #define ANGLE_VALIDATE_VERSION(version, major, minor) \
17 do \
18 { \
19 if (version < CL_MAKE_VERSION(major##u, minor##u, 0u)) \
20 { \
21 return CL_INVALID_VALUE; \
22 } \
23 } while (0)
24
25 #define ANGLE_VALIDATE_EXTENSION(extension) \
26 do \
27 { \
28 if (!extension) \
29 { \
30 return CL_INVALID_VALUE; \
31 } \
32 } while (0)
33
34 #define ANGLE_VALIDATE(expression) \
35 do \
36 { \
37 const cl_int _errorCode = expression; \
38 if (_errorCode != CL_SUCCESS) \
39 { \
40 return _errorCode; \
41 } \
42 } while (0)
43
44 #define ANGLE_VALIDATE_VERSION_OR_EXTENSION(version, major, minor, extension) \
45 do \
46 { \
47 if (version < CL_MAKE_VERSION(major##u, minor##u, 0u)) \
48 { \
49 ANGLE_VALIDATE_EXTENSION(extension); \
50 } \
51 } while (0)
52
53 namespace cl
54 {
55
56 namespace
57 {
58
ValidateContextProperties(const cl_context_properties * properties,const Platform * & platform)59 cl_int ValidateContextProperties(const cl_context_properties *properties, const Platform *&platform)
60 {
61 platform = nullptr;
62 bool hasUserSync = false;
63 if (properties != nullptr)
64 {
65 while (*properties != 0)
66 {
67 switch (*properties++)
68 {
69 case CL_CONTEXT_PLATFORM:
70 {
71 // CL_INVALID_PROPERTY if the same property name is specified more than once.
72 if (platform != nullptr)
73 {
74 return CL_INVALID_PROPERTY;
75 }
76 cl_platform_id nativePlatform = reinterpret_cast<cl_platform_id>(*properties++);
77 // CL_INVALID_PLATFORM if platform value specified in properties
78 // is not a valid platform.
79 if (!Platform::IsValid(nativePlatform))
80 {
81 return CL_INVALID_PLATFORM;
82 }
83 platform = &nativePlatform->cast<Platform>();
84 break;
85 }
86 case CL_CONTEXT_INTEROP_USER_SYNC:
87 {
88 // CL_INVALID_PROPERTY if the value specified for a supported property name
89 // is not valid, or if the same property name is specified more than once.
90 if ((*properties != CL_FALSE && *properties != CL_TRUE) || hasUserSync)
91 {
92 return CL_INVALID_PROPERTY;
93 }
94 ++properties;
95 hasUserSync = true;
96 break;
97 }
98 default:
99 {
100 // CL_INVALID_PROPERTY if context property name in properties
101 // is not a supported property name.
102 return CL_INVALID_PROPERTY;
103 }
104 }
105 }
106 }
107 if (platform == nullptr)
108 {
109 platform = Platform::GetDefault();
110 // CL_INVALID_PLATFORM if properties is NULL and no platform could be selected.
111 if (platform == nullptr)
112 {
113 return CL_INVALID_PLATFORM;
114 }
115 }
116 return CL_SUCCESS;
117 }
118
ValidateMemoryFlags(MemFlags flags,const Platform & platform)119 bool ValidateMemoryFlags(MemFlags flags, const Platform &platform)
120 {
121 // CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, and CL_MEM_READ_ONLY are mutually exclusive.
122 MemFlags allowedFlags(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY);
123 if (!flags.areMutuallyExclusive(CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY))
124 {
125 return false;
126 }
127 // CL_MEM_USE_HOST_PTR is mutually exclusive with either of the other two flags.
128 allowedFlags.set(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR);
129 if (!flags.areMutuallyExclusive(CL_MEM_USE_HOST_PTR,
130 CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR))
131 {
132 return false;
133 }
134 if (platform.isVersionOrNewer(1u, 2u))
135 {
136 // CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY,
137 // and CL_MEM_HOST_NO_ACCESS are mutually exclusive.
138 allowedFlags.set(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS);
139 if (!flags.areMutuallyExclusive(CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY,
140 CL_MEM_HOST_NO_ACCESS))
141 {
142 return false;
143 }
144 }
145 if (platform.isVersionOrNewer(2u, 0u))
146 {
147 allowedFlags.set(CL_MEM_KERNEL_READ_AND_WRITE);
148 }
149 if (flags.hasOtherBitsThan(allowedFlags))
150 {
151 return false;
152 }
153 return true;
154 }
155
ValidateMapFlags(MapFlags flags,const Platform & platform)156 bool ValidateMapFlags(MapFlags flags, const Platform &platform)
157 {
158 MemFlags allowedFlags(CL_MAP_READ | CL_MAP_WRITE);
159 if (platform.isVersionOrNewer(1u, 2u))
160 {
161 // CL_MAP_READ or CL_MAP_WRITE and CL_MAP_WRITE_INVALIDATE_REGION are mutually exclusive.
162 allowedFlags.set(CL_MAP_WRITE_INVALIDATE_REGION);
163 if (!flags.areMutuallyExclusive(CL_MAP_WRITE_INVALIDATE_REGION, CL_MAP_READ | CL_MAP_WRITE))
164 {
165 return false;
166 }
167 }
168 if (flags.hasOtherBitsThan(allowedFlags))
169 {
170 return false;
171 }
172 return true;
173 }
174
ValidateMemoryProperties(const cl_mem_properties * properties)175 bool ValidateMemoryProperties(const cl_mem_properties *properties)
176 {
177 if (properties != nullptr)
178 {
179 // OpenCL 3.0 does not define any optional properties.
180 // This function is reserved for extensions and future use.
181 if (*properties != 0)
182 {
183 return false;
184 }
185 }
186 return true;
187 }
188
ValidateCommandQueueAndEventWaitList(cl_command_queue commandQueue,bool validateImageSupport,cl_uint numEvents,const cl_event * events)189 cl_int ValidateCommandQueueAndEventWaitList(cl_command_queue commandQueue,
190 bool validateImageSupport,
191 cl_uint numEvents,
192 const cl_event *events)
193 {
194 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
195 if (!CommandQueue::IsValid(commandQueue))
196 {
197 return CL_INVALID_COMMAND_QUEUE;
198 }
199 const CommandQueue &queue = commandQueue->cast<CommandQueue>();
200 if (!queue.isOnHost())
201 {
202 return CL_INVALID_COMMAND_QUEUE;
203 }
204
205 if (validateImageSupport)
206 {
207 // CL_INVALID_OPERATION if the device associated with command_queue does not support images.
208 if (queue.getDevice().getInfo().imageSupport == CL_FALSE)
209 {
210 return CL_INVALID_OPERATION;
211 }
212 }
213
214 // CL_INVALID_EVENT_WAIT_LIST if event_wait_list is NULL and num_events_in_wait_list > 0,
215 // or event_wait_list is not NULL and num_events_in_wait_list is 0, ...
216 if ((events == nullptr) != (numEvents == 0u))
217 {
218 return CL_INVALID_EVENT_WAIT_LIST;
219 }
220 while (numEvents-- != 0u)
221 {
222 // or if event objects in event_wait_list are not valid events.
223 if (!Event::IsValid(*events))
224 {
225 return CL_INVALID_EVENT_WAIT_LIST;
226 }
227
228 // CL_INVALID_CONTEXT if the context associated with command_queue
229 // and events in event_wait_list are not the same.
230 if (&queue.getContext() != &(*events++)->cast<Event>().getContext())
231 {
232 return CL_INVALID_CONTEXT;
233 }
234 }
235
236 return CL_SUCCESS;
237 }
238
ValidateEnqueueBuffer(const CommandQueue & queue,cl_mem buffer,bool hostRead,bool hostWrite)239 cl_int ValidateEnqueueBuffer(const CommandQueue &queue,
240 cl_mem buffer,
241 bool hostRead,
242 bool hostWrite)
243 {
244 // CL_INVALID_MEM_OBJECT if buffer is not a valid buffer object.
245 if (!Buffer::IsValid(buffer))
246 {
247 return CL_INVALID_MEM_OBJECT;
248 }
249 const Buffer &buf = buffer->cast<Buffer>();
250
251 // CL_INVALID_CONTEXT if the context associated with command_queue and buffer are not the same.
252 if (&queue.getContext() != &buf.getContext())
253 {
254 return CL_INVALID_CONTEXT;
255 }
256
257 // CL_MISALIGNED_SUB_BUFFER_OFFSET if buffer is a sub-buffer object and offset specified
258 // when the sub-buffer object is created is not aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN
259 // value (which is in bits!) for device associated with queue.
260 if (buf.isSubBuffer() &&
261 (buf.getOffset() % (queue.getDevice().getInfo().memBaseAddrAlign / 8u)) != 0u)
262 {
263 return CL_MISALIGNED_SUB_BUFFER_OFFSET;
264 }
265
266 // CL_INVALID_OPERATION if a read function is called on buffer which
267 // has been created with CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS.
268 if (hostRead && buf.getFlags().isSet(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS))
269 {
270 return CL_INVALID_OPERATION;
271 }
272
273 // CL_INVALID_OPERATION if a write function is called on buffer which
274 // has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS.
275 if (hostWrite && buf.getFlags().isSet(CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS))
276 {
277 return CL_INVALID_OPERATION;
278 }
279
280 return CL_SUCCESS;
281 }
282
ValidateBufferRect(const Buffer & buffer,const size_t * origin,const size_t * region,size_t rowPitch,size_t slicePitch)283 cl_int ValidateBufferRect(const Buffer &buffer,
284 const size_t *origin,
285 const size_t *region,
286 size_t rowPitch,
287 size_t slicePitch)
288 {
289 // CL_INVALID_VALUE if origin or region is NULL.
290 if (origin == nullptr || region == nullptr)
291 {
292 return CL_INVALID_VALUE;
293 }
294
295 // CL_INVALID_VALUE if any region array element is 0.
296 if (region[0] == 0u || region[1] == 0u || region[2] == 0u)
297 {
298 return CL_INVALID_VALUE;
299 }
300
301 // CL_INVALID_VALUE if row_pitch is not 0 and is less than region[0].
302 if (rowPitch == 0u)
303 {
304 rowPitch = region[0];
305 }
306 else if (rowPitch < region[0])
307 {
308 return CL_INVALID_VALUE;
309 }
310
311 // CL_INVALID_VALUE if slice_pitch is not 0 and is less than
312 // region[1] x row_pitch and not a multiple of row_pitch.
313 if (slicePitch == 0u)
314 {
315 slicePitch = region[1] * rowPitch;
316 }
317 else if (slicePitch < region[1] * rowPitch || (slicePitch % rowPitch) != 0u)
318 {
319 return CL_INVALID_VALUE;
320 }
321
322 // CL_INVALID_VALUE if the region being read or written specified
323 // by (origin, region, row_pitch, slice_pitch) is out of bounds.
324 if (!buffer.isRegionValid(
325 origin[2] * slicePitch + origin[1] * rowPitch + origin[0],
326 (region[2] - 1u) * slicePitch + (region[1] - 1u) * rowPitch + region[0]))
327 {
328 return CL_INVALID_VALUE;
329 }
330
331 return CL_SUCCESS;
332 }
333
ValidateHostRect(const size_t * hostOrigin,const size_t * region,size_t hostRowPitch,size_t hostSlicePitch,const void * ptr)334 cl_int ValidateHostRect(const size_t *hostOrigin,
335 const size_t *region,
336 size_t hostRowPitch,
337 size_t hostSlicePitch,
338 const void *ptr)
339 {
340 // CL_INVALID_VALUE if host_origin or region is NULL.
341 if (hostOrigin == nullptr || region == nullptr)
342 {
343 return CL_INVALID_VALUE;
344 }
345
346 // CL_INVALID_VALUE if any region array element is 0.
347 if (region[0] == 0u || region[1] == 0u || region[2] == 0u)
348 {
349 return CL_INVALID_VALUE;
350 }
351
352 // CL_INVALID_VALUE if host_row_pitch is not 0 and is less than region[0].
353 if (hostRowPitch == 0u)
354 {
355 hostRowPitch = region[0];
356 }
357 else if (hostRowPitch < region[0])
358 {
359 return CL_INVALID_VALUE;
360 }
361
362 // CL_INVALID_VALUE if host_slice_pitch is not 0 and is less than
363 // region[1] x host_row_pitch and not a multiple of host_row_pitch.
364 if (hostSlicePitch != 0u &&
365 (hostSlicePitch < region[1] * hostRowPitch || (hostSlicePitch % hostRowPitch) != 0u))
366 {
367 return CL_INVALID_VALUE;
368 }
369
370 // CL_INVALID_VALUE if ptr is NULL.
371 if (ptr == nullptr)
372 {
373 return CL_INVALID_VALUE;
374 }
375
376 return CL_SUCCESS;
377 }
378
ValidateEnqueueImage(const CommandQueue & queue,cl_mem image,bool hostRead,bool hostWrite)379 cl_int ValidateEnqueueImage(const CommandQueue &queue, cl_mem image, bool hostRead, bool hostWrite)
380 {
381 // CL_INVALID_MEM_OBJECT if image is not a valid image object.
382 if (!Image::IsValid(image))
383 {
384 return CL_INVALID_MEM_OBJECT;
385 }
386 const Image &img = image->cast<Image>();
387
388 // CL_INVALID_CONTEXT if the context associated with command_queue and image are not the same.
389 if (&queue.getContext() != &img.getContext())
390 {
391 return CL_INVALID_CONTEXT;
392 }
393
394 // CL_INVALID_OPERATION if a read function is called on image which
395 // has been created with CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS.
396 if (hostRead && img.getFlags().isSet(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS))
397 {
398 return CL_INVALID_OPERATION;
399 }
400
401 // CL_INVALID_OPERATION if a write function is called on image which
402 // has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS.
403 if (hostWrite && img.getFlags().isSet(CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS))
404 {
405 return CL_INVALID_OPERATION;
406 }
407
408 return CL_SUCCESS;
409 }
410
ValidateImageForDevice(const Image & image,const Device & device,const size_t * origin,const size_t * region)411 cl_int ValidateImageForDevice(const Image &image,
412 const Device &device,
413 const size_t *origin,
414 const size_t *region)
415 {
416 // CL_INVALID_VALUE if origin or region is NULL.
417 if (origin == nullptr || region == nullptr)
418 {
419 return CL_INVALID_VALUE;
420 }
421
422 // CL_INVALID_VALUE if values in origin and region do not follow rules
423 // described in the argument description for origin and region.
424 // The values in region cannot be 0.
425 if (region[0] == 0u || region[1] == 0u || region[2] == 0u)
426 {
427 return CL_INVALID_VALUE;
428 }
429 switch (image.getType())
430 {
431 // If image is a 1D image or 1D image buffer object,
432 // origin[1] and origin[2] must be 0 and region[1] and region[2] must be 1.
433 case MemObjectType::Image1D:
434 case MemObjectType::Image1D_Buffer:
435 if (origin[1] != 0u || origin[2] != 0u || region[1] != 1u || region[2] != 1u)
436 {
437 return CL_INVALID_VALUE;
438 }
439 break;
440 // If image is a 2D image object or a 1D image array object,
441 // origin[2] must be 0 and region[2] must be 1.
442 case MemObjectType::Image2D:
443 case MemObjectType::Image1D_Array:
444 if (origin[2] != 0u || region[2] != 1u)
445 {
446 return CL_INVALID_VALUE;
447 }
448 break;
449 case MemObjectType::Image3D:
450 case MemObjectType::Image2D_Array:
451 break;
452 default:
453 ASSERT(false);
454 return CL_INVALID_IMAGE_DESCRIPTOR;
455 }
456
457 // CL_INVALID_VALUE if the region being read or written
458 // specified by origin and region is out of bounds.
459
460 if (!image.isRegionValid(cl::MemOffsets{origin[0], origin[1], origin[2]},
461 cl::Coordinate{region[0], region[1], region[2]}))
462 {
463 return CL_INVALID_VALUE;
464 }
465
466 // CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute
467 // row and/or slice pitch) for image are not supported by device associated with queue.
468 if (!device.supportsImageDimensions(image.getDescriptor()))
469 {
470 return CL_INVALID_IMAGE_SIZE;
471 }
472
473 return CL_SUCCESS;
474 }
475
ValidateHostRegionForImage(const Image & image,const size_t region[3],size_t rowPitch,size_t slicePitch,const void * ptr)476 cl_int ValidateHostRegionForImage(const Image &image,
477 const size_t region[3],
478 size_t rowPitch,
479 size_t slicePitch,
480 const void *ptr)
481 {
482 // CL_INVALID_VALUE if row_pitch is not 0 and is less than the element size in bytes x width.
483 if (rowPitch == 0u)
484 {
485 rowPitch = image.getElementSize() * region[0];
486 }
487 else if (rowPitch < image.getElementSize() * region[0])
488 {
489 return CL_INVALID_VALUE;
490 }
491 if (slicePitch != 0u)
492 {
493 // TODO(jplate) Follow up with https://github.com/KhronosGroup/OpenCL-Docs/issues/624
494 // This error is missing in the OpenCL spec.
495 // slice_pitch must be 0 if image is a 1D or 2D image.
496 if (image.getType() == MemObjectType::Image1D ||
497 image.getType() == MemObjectType::Image1D_Buffer ||
498 image.getType() == MemObjectType::Image2D)
499 {
500 return CL_INVALID_VALUE;
501 }
502 // CL_INVALID_VALUE if slice_pitch is not 0 and is less than row_pitch x height.
503 if (slicePitch < rowPitch * region[1])
504 {
505 return CL_INVALID_VALUE;
506 }
507 }
508
509 // CL_INVALID_VALUE if ptr is NULL.
510 if (ptr == nullptr)
511 {
512 return CL_INVALID_VALUE;
513 }
514
515 return CL_SUCCESS;
516 }
517
518 } // namespace
519
520 // CL 1.0
ValidateGetPlatformIDs(cl_uint num_entries,const cl_platform_id * platforms,const cl_uint * num_platforms)521 cl_int ValidateGetPlatformIDs(cl_uint num_entries,
522 const cl_platform_id *platforms,
523 const cl_uint *num_platforms)
524 {
525 // CL_INVALID_VALUE if num_entries is equal to zero and platforms is not NULL
526 // or if both num_platforms and platforms are NULL.
527 if ((num_entries == 0u && platforms != nullptr) ||
528 (platforms == nullptr && num_platforms == nullptr))
529 {
530 return CL_INVALID_VALUE;
531 }
532
533 return CL_SUCCESS;
534 }
535
ValidateGetPlatformInfo(cl_platform_id platform,PlatformInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)536 cl_int ValidateGetPlatformInfo(cl_platform_id platform,
537 PlatformInfo param_name,
538 size_t param_value_size,
539 const void *param_value,
540 const size_t *param_value_size_ret)
541 {
542 // CL_INVALID_PLATFORM if platform is not a valid platform.
543 if (!Platform::IsValidOrDefault(platform))
544 {
545 return CL_INVALID_PLATFORM;
546 }
547
548 // CL_INVALID_VALUE if param_name is not one of the supported values.
549 const cl_version version = platform->cast<Platform>().getVersion();
550 switch (param_name)
551 {
552 case PlatformInfo::HostTimerResolution:
553 ANGLE_VALIDATE_VERSION(version, 2, 1);
554 break;
555 case PlatformInfo::NumericVersion:
556 case PlatformInfo::ExtensionsWithVersion:
557 ANGLE_VALIDATE_VERSION(version, 3, 0);
558 break;
559 case PlatformInfo::InvalidEnum:
560 return CL_INVALID_VALUE;
561 default:
562 // All remaining possible values for param_name are valid for all versions.
563 break;
564 }
565
566 return CL_SUCCESS;
567 }
568
ValidateGetDeviceIDs(cl_platform_id platform,DeviceType device_type,cl_uint num_entries,const cl_device_id * devices,const cl_uint * num_devices)569 cl_int ValidateGetDeviceIDs(cl_platform_id platform,
570 DeviceType device_type,
571 cl_uint num_entries,
572 const cl_device_id *devices,
573 const cl_uint *num_devices)
574 {
575 // CL_INVALID_PLATFORM if platform is not a valid platform.
576 if (!Platform::IsValidOrDefault(platform))
577 {
578 return CL_INVALID_PLATFORM;
579 }
580
581 // CL_INVALID_DEVICE_TYPE if device_type is not a valid value.
582 if (!Device::IsValidType(device_type))
583 {
584 return CL_INVALID_DEVICE_TYPE;
585 }
586
587 // CL_INVALID_VALUE if num_entries is equal to zero and devices is not NULL
588 // or if both num_devices and devices are NULL.
589 if ((num_entries == 0u && devices != nullptr) || (num_devices == nullptr && devices == nullptr))
590 {
591 return CL_INVALID_VALUE;
592 }
593
594 return CL_SUCCESS;
595 }
596
ValidateGetDeviceInfo(cl_device_id device,DeviceInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)597 cl_int ValidateGetDeviceInfo(cl_device_id device,
598 DeviceInfo param_name,
599 size_t param_value_size,
600 const void *param_value,
601 const size_t *param_value_size_ret)
602 {
603 // CL_INVALID_DEVICE if device is not a valid device.
604 if (!Device::IsValid(device))
605 {
606 return CL_INVALID_DEVICE;
607 }
608 const Device &dev = device->cast<Device>();
609
610 // CL_INVALID_VALUE if param_name is not one of the supported values
611 // or if param_name is a value that is available as an extension
612 // and the corresponding extension is not supported by the device.
613 const cl_version version = dev.getVersion();
614 const rx::CLDeviceImpl::Info &info = dev.getInfo();
615 // Enums ordered within their version block as they appear in the OpenCL spec V3.0.7, table 5
616 switch (param_name)
617 {
618 case DeviceInfo::PreferredVectorWidthHalf:
619 case DeviceInfo::NativeVectorWidthChar:
620 case DeviceInfo::NativeVectorWidthShort:
621 case DeviceInfo::NativeVectorWidthInt:
622 case DeviceInfo::NativeVectorWidthLong:
623 case DeviceInfo::NativeVectorWidthFloat:
624 case DeviceInfo::NativeVectorWidthDouble:
625 case DeviceInfo::NativeVectorWidthHalf:
626 case DeviceInfo::HostUnifiedMemory:
627 case DeviceInfo::OpenCL_C_Version:
628 ANGLE_VALIDATE_VERSION(version, 1, 1);
629 break;
630
631 case DeviceInfo::ImageMaxBufferSize:
632 case DeviceInfo::ImageMaxArraySize:
633 case DeviceInfo::LinkerAvailable:
634 case DeviceInfo::BuiltInKernels:
635 case DeviceInfo::PrintfBufferSize:
636 case DeviceInfo::PreferredInteropUserSync:
637 case DeviceInfo::ParentDevice:
638 case DeviceInfo::PartitionMaxSubDevices:
639 case DeviceInfo::PartitionProperties:
640 case DeviceInfo::PartitionAffinityDomain:
641 case DeviceInfo::PartitionType:
642 case DeviceInfo::ReferenceCount:
643 ANGLE_VALIDATE_VERSION(version, 1, 2);
644 break;
645
646 case DeviceInfo::MaxReadWriteImageArgs:
647 case DeviceInfo::ImagePitchAlignment:
648 case DeviceInfo::ImageBaseAddressAlignment:
649 case DeviceInfo::MaxPipeArgs:
650 case DeviceInfo::PipeMaxActiveReservations:
651 case DeviceInfo::PipeMaxPacketSize:
652 case DeviceInfo::MaxGlobalVariableSize:
653 case DeviceInfo::GlobalVariablePreferredTotalSize:
654 case DeviceInfo::QueueOnDeviceProperties:
655 case DeviceInfo::QueueOnDevicePreferredSize:
656 case DeviceInfo::QueueOnDeviceMaxSize:
657 case DeviceInfo::MaxOnDeviceQueues:
658 case DeviceInfo::MaxOnDeviceEvents:
659 case DeviceInfo::SVM_Capabilities:
660 case DeviceInfo::PreferredPlatformAtomicAlignment:
661 case DeviceInfo::PreferredGlobalAtomicAlignment:
662 case DeviceInfo::PreferredLocalAtomicAlignment:
663 ANGLE_VALIDATE_VERSION(version, 2, 0);
664 break;
665
666 case DeviceInfo::IL_Version:
667 case DeviceInfo::MaxNumSubGroups:
668 case DeviceInfo::SubGroupIndependentForwardProgress:
669 ANGLE_VALIDATE_VERSION(version, 2, 1);
670 break;
671
672 case DeviceInfo::ILsWithVersion:
673 case DeviceInfo::BuiltInKernelsWithVersion:
674 case DeviceInfo::NumericVersion:
675 case DeviceInfo::OpenCL_C_AllVersions:
676 case DeviceInfo::OpenCL_C_Features:
677 case DeviceInfo::ExtensionsWithVersion:
678 case DeviceInfo::AtomicMemoryCapabilities:
679 case DeviceInfo::AtomicFenceCapabilities:
680 case DeviceInfo::NonUniformWorkGroupSupport:
681 case DeviceInfo::WorkGroupCollectiveFunctionsSupport:
682 case DeviceInfo::GenericAddressSpaceSupport:
683 case DeviceInfo::DeviceEnqueueCapabilities:
684 case DeviceInfo::PipeSupport:
685 case DeviceInfo::PreferredWorkGroupSizeMultiple:
686 case DeviceInfo::LatestConformanceVersionPassed:
687 ANGLE_VALIDATE_VERSION(version, 3, 0);
688 break;
689
690 case DeviceInfo::DoubleFpConfig:
691 // This extension became a core query from OpenCL 1.2 onward.
692 // Only need to validate for OpenCL versions less than 1.2 here.
693 ANGLE_VALIDATE_VERSION_OR_EXTENSION(version, 1, 2, info.khrFP64);
694 break;
695
696 case DeviceInfo::InvalidEnum:
697 return CL_INVALID_VALUE;
698 default:
699 // All remaining possible values for param_name are valid for all versions.
700 break;
701 }
702
703 return CL_SUCCESS;
704 }
705
ValidateCreateContext(const cl_context_properties * properties,cl_uint num_devices,const cl_device_id * devices,void (CL_CALLBACK * pfn_notify)(const char * errinfo,const void * private_info,size_t cb,void * user_data),const void * user_data)706 cl_int ValidateCreateContext(const cl_context_properties *properties,
707 cl_uint num_devices,
708 const cl_device_id *devices,
709 void(CL_CALLBACK *pfn_notify)(const char *errinfo,
710 const void *private_info,
711 size_t cb,
712 void *user_data),
713 const void *user_data)
714 {
715 const Platform *platform = nullptr;
716 ANGLE_VALIDATE(ValidateContextProperties(properties, platform));
717
718 // CL_INVALID_VALUE if devices is NULL or if num_devices is equal to zero
719 // or if pfn_notify is NULL but user_data is not NULL.
720 if (devices == nullptr || num_devices == 0u || (pfn_notify == nullptr && user_data != nullptr))
721 {
722 return CL_INVALID_VALUE;
723 }
724
725 // CL_INVALID_DEVICE if any device in devices is not a valid device.
726 while (num_devices-- > 0u)
727 {
728 if (!Device::IsValid(*devices) || &(*devices)->cast<Device>().getPlatform() != platform)
729 {
730 return CL_INVALID_DEVICE;
731 }
732 ++devices;
733 }
734
735 return CL_SUCCESS;
736 }
737
ValidateCreateContextFromType(const cl_context_properties * properties,DeviceType device_type,void (CL_CALLBACK * pfn_notify)(const char * errinfo,const void * private_info,size_t cb,void * user_data),const void * user_data)738 cl_int ValidateCreateContextFromType(const cl_context_properties *properties,
739 DeviceType device_type,
740 void(CL_CALLBACK *pfn_notify)(const char *errinfo,
741 const void *private_info,
742 size_t cb,
743 void *user_data),
744 const void *user_data)
745 {
746 const Platform *platform = nullptr;
747 ANGLE_VALIDATE(ValidateContextProperties(properties, platform));
748
749 // CL_INVALID_DEVICE_TYPE if device_type is not a valid value.
750 if (!Device::IsValidType(device_type))
751 {
752 return CL_INVALID_DEVICE_TYPE;
753 }
754
755 if (!platform->hasDeviceType(device_type))
756 {
757 return CL_DEVICE_NOT_FOUND;
758 }
759
760 // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
761 if (pfn_notify == nullptr && user_data != nullptr)
762 {
763 return CL_INVALID_VALUE;
764 }
765
766 return CL_SUCCESS;
767 }
768
ValidateRetainContext(cl_context context)769 cl_int ValidateRetainContext(cl_context context)
770 {
771 // CL_INVALID_CONTEXT if context is not a valid OpenCL context.
772 return Context::IsValid(context) ? CL_SUCCESS : CL_INVALID_CONTEXT;
773 }
774
ValidateReleaseContext(cl_context context)775 cl_int ValidateReleaseContext(cl_context context)
776 {
777 // CL_INVALID_CONTEXT if context is not a valid OpenCL context.
778 return Context::IsValid(context) ? CL_SUCCESS : CL_INVALID_CONTEXT;
779 }
780
ValidateGetContextInfo(cl_context context,ContextInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)781 cl_int ValidateGetContextInfo(cl_context context,
782 ContextInfo param_name,
783 size_t param_value_size,
784 const void *param_value,
785 const size_t *param_value_size_ret)
786 {
787 // CL_INVALID_CONTEXT if context is not a valid context.
788 if (!Context::IsValid(context))
789 {
790 return CL_INVALID_CONTEXT;
791 }
792
793 // CL_INVALID_VALUE if param_name is not one of the supported values.
794 if (param_name == ContextInfo::InvalidEnum)
795 {
796 return CL_INVALID_VALUE;
797 }
798
799 return CL_SUCCESS;
800 }
801
ValidateRetainCommandQueue(cl_command_queue command_queue)802 cl_int ValidateRetainCommandQueue(cl_command_queue command_queue)
803 {
804 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
805 return CommandQueue::IsValid(command_queue) ? CL_SUCCESS : CL_INVALID_COMMAND_QUEUE;
806 }
807
ValidateReleaseCommandQueue(cl_command_queue command_queue)808 cl_int ValidateReleaseCommandQueue(cl_command_queue command_queue)
809 {
810 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
811 return CommandQueue::IsValid(command_queue) ? CL_SUCCESS : CL_INVALID_COMMAND_QUEUE;
812 }
813
ValidateGetCommandQueueInfo(cl_command_queue command_queue,CommandQueueInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)814 cl_int ValidateGetCommandQueueInfo(cl_command_queue command_queue,
815 CommandQueueInfo param_name,
816 size_t param_value_size,
817 const void *param_value,
818 const size_t *param_value_size_ret)
819 {
820 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue ...
821 if (!CommandQueue::IsValid(command_queue))
822 {
823 return CL_INVALID_COMMAND_QUEUE;
824 }
825 const CommandQueue &queue = command_queue->cast<CommandQueue>();
826 // or if command_queue is not a valid command-queue for param_name.
827 if (param_name == CommandQueueInfo::Size && queue.isOnDevice())
828 {
829 return CL_INVALID_COMMAND_QUEUE;
830 }
831
832 // CL_INVALID_VALUE if param_name is not one of the supported values.
833 const cl_version version = queue.getDevice().getVersion();
834 switch (param_name)
835 {
836 case CommandQueueInfo::Size:
837 ANGLE_VALIDATE_VERSION(version, 2, 0);
838 break;
839 case CommandQueueInfo::DeviceDefault:
840 ANGLE_VALIDATE_VERSION(version, 2, 1);
841 break;
842 case CommandQueueInfo::PropertiesArray:
843 ANGLE_VALIDATE_VERSION(version, 3, 0);
844 break;
845 case CommandQueueInfo::InvalidEnum:
846 return CL_INVALID_VALUE;
847 default:
848 // All remaining possible values for param_name are valid for all versions.
849 break;
850 }
851
852 return CL_SUCCESS;
853 }
854
ValidateCreateBuffer(cl_context context,MemFlags flags,size_t size,const void * host_ptr)855 cl_int ValidateCreateBuffer(cl_context context, MemFlags flags, size_t size, const void *host_ptr)
856 {
857 // CL_INVALID_CONTEXT if context is not a valid context.
858 if (!Context::IsValid(context))
859 {
860 return CL_INVALID_CONTEXT;
861 }
862 const Context &ctx = context->cast<Context>();
863
864 // CL_INVALID_VALUE if values specified in flags are not valid
865 // as defined in the Memory Flags table.
866 if (!ValidateMemoryFlags(flags, ctx.getPlatform()))
867 {
868 return CL_INVALID_VALUE;
869 }
870
871 // CL_INVALID_BUFFER_SIZE if size is 0 ...
872 if (size == 0u)
873 {
874 CL_INVALID_BUFFER_SIZE;
875 }
876 for (const DevicePtr &device : ctx.getDevices())
877 {
878 // or if size is greater than CL_DEVICE_MAX_MEM_ALLOC_SIZE for all devices in context.
879 if (size > device->getInfo().maxMemAllocSize)
880 {
881 return CL_INVALID_BUFFER_SIZE;
882 }
883 }
884
885 // CL_INVALID_HOST_PTR
886 // if host_ptr is NULL and CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR are set in flags or
887 // if host_ptr is not NULL but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in flags.
888 if ((host_ptr != nullptr) != flags.isSet(CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))
889 {
890 return CL_INVALID_HOST_PTR;
891 }
892
893 return CL_SUCCESS;
894 }
895
ValidateRetainMemObject(cl_mem memobj)896 cl_int ValidateRetainMemObject(cl_mem memobj)
897 {
898 // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object.
899 return Memory::IsValid(memobj) ? CL_SUCCESS : CL_INVALID_MEM_OBJECT;
900 }
901
ValidateReleaseMemObject(cl_mem memobj)902 cl_int ValidateReleaseMemObject(cl_mem memobj)
903 {
904 // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object.
905 return Memory::IsValid(memobj) ? CL_SUCCESS : CL_INVALID_MEM_OBJECT;
906 }
907
ValidateGetSupportedImageFormats(cl_context context,MemFlags flags,MemObjectType image_type,cl_uint num_entries,const cl_image_format * image_formats,const cl_uint * num_image_formats)908 cl_int ValidateGetSupportedImageFormats(cl_context context,
909 MemFlags flags,
910 MemObjectType image_type,
911 cl_uint num_entries,
912 const cl_image_format *image_formats,
913 const cl_uint *num_image_formats)
914 {
915 // CL_INVALID_CONTEXT if context is not a valid context.
916 if (!Context::IsValid(context))
917 {
918 return CL_INVALID_CONTEXT;
919 }
920 const Context &ctx = context->cast<Context>();
921
922 // CL_INVALID_VALUE if flags or image_type are not valid,
923 if (!ValidateMemoryFlags(flags, ctx.getPlatform()) || !Image::IsTypeValid(image_type))
924 {
925 return CL_INVALID_VALUE;
926 }
927 // or if num_entries is 0 and image_formats is not NULL.
928 if (num_entries == 0u && image_formats != nullptr)
929 {
930 return CL_INVALID_VALUE;
931 }
932
933 return CL_SUCCESS;
934 }
935
ValidateGetMemObjectInfo(cl_mem memobj,MemInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)936 cl_int ValidateGetMemObjectInfo(cl_mem memobj,
937 MemInfo param_name,
938 size_t param_value_size,
939 const void *param_value,
940 const size_t *param_value_size_ret)
941 {
942 // CL_INVALID_MEM_OBJECT if memobj is a not a valid memory object.
943 if (!Memory::IsValid(memobj))
944 {
945 return CL_INVALID_MEM_OBJECT;
946 }
947
948 // CL_INVALID_VALUE if param_name is not valid.
949 const cl_version version = memobj->cast<Memory>().getContext().getPlatform().getVersion();
950 switch (param_name)
951 {
952 case MemInfo::AssociatedMemObject:
953 case MemInfo::Offset:
954 ANGLE_VALIDATE_VERSION(version, 1, 1);
955 break;
956 case MemInfo::UsesSVM_Pointer:
957 ANGLE_VALIDATE_VERSION(version, 2, 0);
958 break;
959 case MemInfo::Properties:
960 ANGLE_VALIDATE_VERSION(version, 3, 0);
961 break;
962 case MemInfo::InvalidEnum:
963 return CL_INVALID_VALUE;
964 default:
965 // All remaining possible values for param_name are valid for all versions.
966 break;
967 }
968
969 return CL_SUCCESS;
970 }
971
ValidateGetImageInfo(cl_mem image,ImageInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)972 cl_int ValidateGetImageInfo(cl_mem image,
973 ImageInfo param_name,
974 size_t param_value_size,
975 const void *param_value,
976 const size_t *param_value_size_ret)
977 {
978 // CL_INVALID_MEM_OBJECT if image is a not a valid image object.
979 if (!Image::IsValid(image))
980 {
981 return CL_INVALID_MEM_OBJECT;
982 }
983
984 // CL_INVALID_VALUE if param_name is not valid.
985 const cl_version version = image->cast<Image>().getContext().getPlatform().getVersion();
986 switch (param_name)
987 {
988 case ImageInfo::ArraySize:
989 case ImageInfo::Buffer:
990 case ImageInfo::NumMipLevels:
991 case ImageInfo::NumSamples:
992 ANGLE_VALIDATE_VERSION(version, 1, 2);
993 break;
994 case ImageInfo::InvalidEnum:
995 return CL_INVALID_VALUE;
996 default:
997 // All remaining possible values for param_name are valid for all versions.
998 break;
999 }
1000
1001 return CL_SUCCESS;
1002 }
1003
ValidateRetainSampler(cl_sampler sampler)1004 cl_int ValidateRetainSampler(cl_sampler sampler)
1005 {
1006 // CL_INVALID_SAMPLER if sampler is not a valid sampler object.
1007 return Sampler::IsValid(sampler) ? CL_SUCCESS : CL_INVALID_SAMPLER;
1008 }
1009
ValidateReleaseSampler(cl_sampler sampler)1010 cl_int ValidateReleaseSampler(cl_sampler sampler)
1011 {
1012 // CL_INVALID_SAMPLER if sampler is not a valid sampler object.
1013 return Sampler::IsValid(sampler) ? CL_SUCCESS : CL_INVALID_SAMPLER;
1014 }
1015
ValidateGetSamplerInfo(cl_sampler sampler,SamplerInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)1016 cl_int ValidateGetSamplerInfo(cl_sampler sampler,
1017 SamplerInfo param_name,
1018 size_t param_value_size,
1019 const void *param_value,
1020 const size_t *param_value_size_ret)
1021 {
1022 // CL_INVALID_SAMPLER if sampler is a not a valid sampler object.
1023 if (!Sampler::IsValid(sampler))
1024 {
1025 return CL_INVALID_SAMPLER;
1026 }
1027
1028 // CL_INVALID_VALUE if param_name is not valid.
1029 const cl_version version = sampler->cast<Sampler>().getContext().getPlatform().getVersion();
1030 switch (param_name)
1031 {
1032 case SamplerInfo::Properties:
1033 ANGLE_VALIDATE_VERSION(version, 3, 0);
1034 break;
1035 case SamplerInfo::InvalidEnum:
1036 return CL_INVALID_VALUE;
1037 default:
1038 // All remaining possible values for param_name are valid for all versions.
1039 break;
1040 }
1041
1042 return CL_SUCCESS;
1043 }
1044
ValidateCreateProgramWithSource(cl_context context,cl_uint count,const char ** strings,const size_t * lengths)1045 cl_int ValidateCreateProgramWithSource(cl_context context,
1046 cl_uint count,
1047 const char **strings,
1048 const size_t *lengths)
1049 {
1050 // CL_INVALID_CONTEXT if context is not a valid context.
1051 if (!Context::IsValid(context))
1052 {
1053 return CL_INVALID_CONTEXT;
1054 }
1055
1056 // CL_INVALID_VALUE if count is zero or if strings or any entry in strings is NULL.
1057 if (count == 0u || strings == nullptr)
1058 {
1059 return CL_INVALID_VALUE;
1060 }
1061 while (count-- != 0u)
1062 {
1063 if (*strings++ == nullptr)
1064 {
1065 return CL_INVALID_VALUE;
1066 }
1067 }
1068
1069 return CL_SUCCESS;
1070 }
1071
ValidateCreateProgramWithBinary(cl_context context,cl_uint num_devices,const cl_device_id * device_list,const size_t * lengths,const unsigned char ** binaries,const cl_int * binary_status)1072 cl_int ValidateCreateProgramWithBinary(cl_context context,
1073 cl_uint num_devices,
1074 const cl_device_id *device_list,
1075 const size_t *lengths,
1076 const unsigned char **binaries,
1077 const cl_int *binary_status)
1078 {
1079 // CL_INVALID_CONTEXT if context is not a valid context.
1080 if (!Context::IsValid(context))
1081 {
1082 return CL_INVALID_CONTEXT;
1083 }
1084 const Context &ctx = context->cast<Context>();
1085
1086 // CL_INVALID_VALUE if device_list is NULL or num_devices is zero.
1087 // CL_INVALID_VALUE if lengths or binaries is NULL.
1088 if (device_list == nullptr || num_devices == 0u || lengths == nullptr || binaries == nullptr)
1089 {
1090 return CL_INVALID_VALUE;
1091 }
1092 while (num_devices-- != 0u)
1093 {
1094 // CL_INVALID_DEVICE if any device in device_list
1095 // is not in the list of devices associated with context.
1096 if (!ctx.hasDevice(*device_list++))
1097 {
1098 return CL_INVALID_DEVICE;
1099 }
1100
1101 // CL_INVALID_VALUE if any entry in lengths[i] is zero or binaries[i] is NULL.
1102 if (*lengths++ == 0u || *binaries++ == nullptr)
1103 {
1104 return CL_INVALID_VALUE;
1105 }
1106 }
1107
1108 return CL_SUCCESS;
1109 }
1110
ValidateRetainProgram(cl_program program)1111 cl_int ValidateRetainProgram(cl_program program)
1112 {
1113 // CL_INVALID_PROGRAM if program is not a valid program object.
1114 return Program::IsValid(program) ? CL_SUCCESS : CL_INVALID_PROGRAM;
1115 }
1116
ValidateReleaseProgram(cl_program program)1117 cl_int ValidateReleaseProgram(cl_program program)
1118 {
1119 // CL_INVALID_PROGRAM if program is not a valid program object.
1120 return Program::IsValid(program) ? CL_SUCCESS : CL_INVALID_PROGRAM;
1121 }
1122
ValidateBuildProgram(cl_program program,cl_uint num_devices,const cl_device_id * device_list,const char * options,void (CL_CALLBACK * pfn_notify)(cl_program program,void * user_data),const void * user_data)1123 cl_int ValidateBuildProgram(cl_program program,
1124 cl_uint num_devices,
1125 const cl_device_id *device_list,
1126 const char *options,
1127 void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
1128 const void *user_data)
1129 {
1130 // CL_INVALID_PROGRAM if program is not a valid program object.
1131 if (!Program::IsValid(program))
1132 {
1133 return CL_INVALID_PROGRAM;
1134 }
1135 const Program &prog = program->cast<Program>();
1136
1137 // CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero,
1138 // or if device_list is not NULL and num_devices is zero.
1139 if ((device_list != nullptr) != (num_devices != 0u))
1140 {
1141 return CL_INVALID_VALUE;
1142 }
1143
1144 // CL_INVALID_DEVICE if any device in device_list
1145 // is not in the list of devices associated with program.
1146 while (num_devices-- != 0u)
1147 {
1148 if (!prog.hasDevice(*device_list++))
1149 {
1150 return CL_INVALID_DEVICE;
1151 }
1152 }
1153
1154 // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
1155 if (pfn_notify == nullptr && user_data != nullptr)
1156 {
1157 return CL_INVALID_VALUE;
1158 }
1159
1160 // CL_INVALID_OPERATION if the build of a program executable for any of the devices listed
1161 // in device_list by a previous call to clBuildProgram for program has not completed.
1162 if (prog.isBuilding())
1163 {
1164 return CL_INVALID_OPERATION;
1165 }
1166
1167 // CL_INVALID_OPERATION if there are kernel objects attached to program.
1168 if (prog.hasAttachedKernels())
1169 {
1170 return CL_INVALID_OPERATION;
1171 }
1172
1173 // If program was created with clCreateProgramWithBinary and device does not have a valid
1174 // program binary loaded
1175 std::vector<size_t> binSizes{prog.getDevices().size()};
1176 std::vector<std::vector<unsigned char *>> bins{prog.getDevices().size()};
1177 if (IsError(prog.getInfo(ProgramInfo::BinarySizes, binSizes.size() * sizeof(size_t),
1178 binSizes.data(), nullptr)))
1179 {
1180 return CL_INVALID_PROGRAM;
1181 }
1182 for (size_t i = 0; i < prog.getDevices().size(); ++i)
1183 {
1184 cl_program_binary_type binType;
1185 bins.at(i).resize(binSizes[i]);
1186
1187 if (IsError(prog.getInfo(ProgramInfo::Binaries, sizeof(unsigned char *) * bins.size(),
1188 bins.data(), nullptr)))
1189 {
1190 return CL_INVALID_VALUE;
1191 }
1192 if (IsError(prog.getBuildInfo(prog.getDevices()[i]->getNative(),
1193 ProgramBuildInfo::BinaryType, sizeof(cl_program_binary_type),
1194 &binType, nullptr)))
1195 {
1196 return CL_INVALID_VALUE;
1197 }
1198 if ((binType != CL_PROGRAM_BINARY_TYPE_NONE) && bins[i].empty())
1199 {
1200 return CL_INVALID_BINARY;
1201 }
1202 }
1203
1204 return CL_SUCCESS;
1205 }
1206
ValidateGetProgramInfo(cl_program program,ProgramInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)1207 cl_int ValidateGetProgramInfo(cl_program program,
1208 ProgramInfo param_name,
1209 size_t param_value_size,
1210 const void *param_value,
1211 const size_t *param_value_size_ret)
1212 {
1213 // CL_INVALID_PROGRAM if program is not a valid program object.
1214 if (!Program::IsValid(program))
1215 {
1216 return CL_INVALID_PROGRAM;
1217 }
1218 const Program &prog = program->cast<Program>();
1219
1220 // CL_INVALID_VALUE if param_name is not valid.
1221 const cl_version version = prog.getContext().getPlatform().getVersion();
1222 switch (param_name)
1223 {
1224 case ProgramInfo::NumKernels:
1225 case ProgramInfo::KernelNames:
1226 ANGLE_VALIDATE_VERSION(version, 1, 2);
1227 break;
1228 case ProgramInfo::IL:
1229 ANGLE_VALIDATE_VERSION(version, 2, 1);
1230 break;
1231 case ProgramInfo::ScopeGlobalCtorsPresent:
1232 case ProgramInfo::ScopeGlobalDtorsPresent:
1233 ANGLE_VALIDATE_VERSION(version, 2, 2);
1234 break;
1235 case ProgramInfo::InvalidEnum:
1236 return CL_INVALID_VALUE;
1237 default:
1238 // All remaining possible values for param_name are valid for all versions.
1239 break;
1240 }
1241
1242 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
1243 // as described in the Program Object Queries table and param_value is not NULL.
1244 if (param_value != nullptr)
1245 {
1246 size_t valueSizeRet = 0;
1247 if (IsError(prog.getInfo(param_name, 0, nullptr, &valueSizeRet)) ||
1248 param_value_size < valueSizeRet)
1249 {
1250 return CL_INVALID_VALUE;
1251 }
1252 }
1253
1254 return CL_SUCCESS;
1255 }
1256
ValidateGetProgramBuildInfo(cl_program program,cl_device_id device,ProgramBuildInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)1257 cl_int ValidateGetProgramBuildInfo(cl_program program,
1258 cl_device_id device,
1259 ProgramBuildInfo param_name,
1260 size_t param_value_size,
1261 const void *param_value,
1262 const size_t *param_value_size_ret)
1263 {
1264 // CL_INVALID_PROGRAM if program is not a valid program object.
1265 if (!Program::IsValid(program))
1266 {
1267 return CL_INVALID_PROGRAM;
1268 }
1269 const Program &prog = program->cast<Program>();
1270
1271 // CL_INVALID_DEVICE if device is not in the list of devices associated with program.
1272 if (!prog.hasDevice(device))
1273 {
1274 return CL_INVALID_DEVICE;
1275 }
1276
1277 // CL_INVALID_VALUE if param_name is not valid.
1278 const cl_version version = prog.getContext().getPlatform().getVersion();
1279 switch (param_name)
1280 {
1281 case ProgramBuildInfo::BinaryType:
1282 ANGLE_VALIDATE_VERSION(version, 1, 2);
1283 break;
1284 case ProgramBuildInfo::GlobalVariableTotalSize:
1285 ANGLE_VALIDATE_VERSION(version, 2, 0);
1286 break;
1287 case ProgramBuildInfo::InvalidEnum:
1288 return CL_INVALID_VALUE;
1289 default:
1290 // All remaining possible values for param_name are valid for all versions.
1291 break;
1292 }
1293
1294 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
1295 // as described in the Program Object Queries table and param_value is not NULL.
1296 if (param_value != nullptr)
1297 {
1298 size_t valueSizeRet = 0;
1299 if (IsError(prog.getBuildInfo(device, param_name, 0, nullptr, &valueSizeRet)) ||
1300 param_value_size < valueSizeRet)
1301 {
1302 return CL_INVALID_VALUE;
1303 }
1304 }
1305
1306 return CL_SUCCESS;
1307 }
1308
ValidateCreateKernel(cl_program program,const char * kernel_name)1309 cl_int ValidateCreateKernel(cl_program program, const char *kernel_name)
1310 {
1311 // CL_INVALID_PROGRAM if program is not a valid program object.
1312 if (!Program::IsValid(program))
1313 {
1314 return CL_INVALID_PROGRAM;
1315 }
1316 cl::Program &prog = program->cast<cl::Program>();
1317
1318 // CL_INVALID_VALUE if kernel_name is NULL.
1319 if (kernel_name == nullptr)
1320 {
1321 return CL_INVALID_VALUE;
1322 }
1323
1324 // CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built executable for program.
1325 std::vector<cl_device_id> associatedDevices;
1326 size_t associatedDeviceCount = 0;
1327 bool isAnyDeviceProgramBuilt = false;
1328 if (IsError(prog.getInfo(ProgramInfo::Devices, 0, nullptr, &associatedDeviceCount)))
1329 {
1330 return CL_INVALID_PROGRAM;
1331 }
1332 associatedDevices.resize(associatedDeviceCount / sizeof(cl_device_id));
1333 if (IsError(prog.getInfo(ProgramInfo::Devices, associatedDeviceCount, associatedDevices.data(),
1334 nullptr)))
1335 {
1336 return CL_INVALID_PROGRAM;
1337 }
1338 for (const cl_device_id &device : associatedDevices)
1339 {
1340 cl_build_status status = CL_BUILD_NONE;
1341 if (IsError(prog.getBuildInfo(device, ProgramBuildInfo::Status, sizeof(cl_build_status),
1342 &status, nullptr)))
1343 {
1344 return CL_INVALID_PROGRAM;
1345 }
1346
1347 if (status == CL_BUILD_SUCCESS)
1348 {
1349 isAnyDeviceProgramBuilt = true;
1350 break;
1351 }
1352 }
1353 if (!isAnyDeviceProgramBuilt)
1354 {
1355 return CL_INVALID_PROGRAM_EXECUTABLE;
1356 }
1357
1358 // CL_INVALID_KERNEL_NAME if kernel_name is not found in program.
1359 std::string kernelNames;
1360 size_t kernelNamesSize = 0;
1361 if (IsError(prog.getInfo(ProgramInfo::KernelNames, 0, nullptr, &kernelNamesSize)))
1362 {
1363 return CL_INVALID_PROGRAM;
1364 }
1365 kernelNames.resize(kernelNamesSize);
1366 if (IsError(
1367 prog.getInfo(ProgramInfo::KernelNames, kernelNamesSize, kernelNames.data(), nullptr)))
1368 {
1369 return CL_INVALID_PROGRAM;
1370 }
1371 std::vector<std::string> tokenizedKernelNames =
1372 angle::SplitString(kernelNames.c_str(), ";", angle::WhitespaceHandling::TRIM_WHITESPACE,
1373 angle::SplitResult::SPLIT_WANT_NONEMPTY);
1374 if (std::find(tokenizedKernelNames.begin(), tokenizedKernelNames.end(), kernel_name) ==
1375 tokenizedKernelNames.end())
1376 {
1377 return CL_INVALID_KERNEL_NAME;
1378 }
1379
1380 return CL_SUCCESS;
1381 }
1382
ValidateCreateKernelsInProgram(cl_program program,cl_uint num_kernels,const cl_kernel * kernels,const cl_uint * num_kernels_ret)1383 cl_int ValidateCreateKernelsInProgram(cl_program program,
1384 cl_uint num_kernels,
1385 const cl_kernel *kernels,
1386 const cl_uint *num_kernels_ret)
1387 {
1388 // CL_INVALID_PROGRAM if program is not a valid program object.
1389 if (!Program::IsValid(program))
1390 {
1391 return CL_INVALID_PROGRAM;
1392 }
1393
1394 // CL_INVALID_VALUE if kernels is not NULL and num_kernels is less than the number of kernels in
1395 // program.
1396 size_t kernelCount = 0;
1397 cl::Program &prog = program->cast<cl::Program>();
1398 if (IsError(prog.getInfo(ProgramInfo::NumKernels, sizeof(size_t), &prog, nullptr)))
1399 {
1400 return CL_INVALID_PROGRAM;
1401 }
1402 if (kernels != nullptr && num_kernels < kernelCount)
1403 {
1404 return CL_INVALID_VALUE;
1405 }
1406
1407 return CL_SUCCESS;
1408 }
1409
ValidateRetainKernel(cl_kernel kernel)1410 cl_int ValidateRetainKernel(cl_kernel kernel)
1411 {
1412 // CL_INVALID_KERNEL if kernel is not a valid kernel object.
1413 return Kernel::IsValid(kernel) ? CL_SUCCESS : CL_INVALID_KERNEL;
1414 }
1415
ValidateReleaseKernel(cl_kernel kernel)1416 cl_int ValidateReleaseKernel(cl_kernel kernel)
1417 {
1418 // CL_INVALID_KERNEL if kernel is not a valid kernel object.
1419 return Kernel::IsValid(kernel) ? CL_SUCCESS : CL_INVALID_KERNEL;
1420 }
1421
ValidateSetKernelArg(cl_kernel kernel,cl_uint arg_index,size_t arg_size,const void * arg_value)1422 cl_int ValidateSetKernelArg(cl_kernel kernel,
1423 cl_uint arg_index,
1424 size_t arg_size,
1425 const void *arg_value)
1426 {
1427 // CL_INVALID_KERNEL if kernel is not a valid kernel object.
1428 if (!Kernel::IsValid(kernel))
1429 {
1430 return CL_INVALID_KERNEL;
1431 }
1432 const Kernel &krnl = kernel->cast<Kernel>();
1433
1434 // CL_INVALID_ARG_INDEX if arg_index is not a valid argument index.
1435 if (arg_index >= krnl.getInfo().args.size())
1436 {
1437 return CL_INVALID_ARG_INDEX;
1438 }
1439
1440 if (arg_size == sizeof(cl_mem) && arg_value != nullptr)
1441 {
1442 const std::string &typeName = krnl.getInfo().args[arg_index].typeName;
1443
1444 // CL_INVALID_MEM_OBJECT for an argument declared to be a memory object
1445 // when the specified arg_value is not a valid memory object.
1446 if (typeName == "image1d_t")
1447 {
1448 const cl_mem image = *static_cast<const cl_mem *>(arg_value);
1449 if (!Image::IsValid(image) || image->cast<Image>().getType() != MemObjectType::Image1D)
1450 {
1451 return CL_INVALID_MEM_OBJECT;
1452 }
1453 }
1454 else if (typeName == "image2d_t")
1455 {
1456 const cl_mem image = *static_cast<const cl_mem *>(arg_value);
1457 if (!Image::IsValid(image) || image->cast<Image>().getType() != MemObjectType::Image2D)
1458 {
1459 return CL_INVALID_MEM_OBJECT;
1460 }
1461 }
1462 else if (typeName == "image3d_t")
1463 {
1464 const cl_mem image = *static_cast<const cl_mem *>(arg_value);
1465 if (!Image::IsValid(image) || image->cast<Image>().getType() != MemObjectType::Image3D)
1466 {
1467 return CL_INVALID_MEM_OBJECT;
1468 }
1469 }
1470 else if (typeName == "image1d_array_t")
1471 {
1472 const cl_mem image = *static_cast<const cl_mem *>(arg_value);
1473 if (!Image::IsValid(image) ||
1474 image->cast<Image>().getType() != MemObjectType::Image1D_Array)
1475 {
1476 return CL_INVALID_MEM_OBJECT;
1477 }
1478 }
1479 else if (typeName == "image2d_array_t")
1480 {
1481 const cl_mem image = *static_cast<const cl_mem *>(arg_value);
1482 if (!Image::IsValid(image) ||
1483 image->cast<Image>().getType() != MemObjectType::Image2D_Array)
1484 {
1485 return CL_INVALID_MEM_OBJECT;
1486 }
1487 }
1488 else if (typeName == "image1d_buffer_t")
1489 {
1490 const cl_mem image = *static_cast<const cl_mem *>(arg_value);
1491 if (!Image::IsValid(image) ||
1492 image->cast<Image>().getType() != MemObjectType::Image1D_Buffer)
1493 {
1494 return CL_INVALID_MEM_OBJECT;
1495 }
1496 }
1497 // CL_INVALID_SAMPLER for an argument declared to be of type sampler_t
1498 // when the specified arg_value is not a valid sampler object.
1499 else if (typeName == "sampler_t")
1500 {
1501 static_assert(sizeof(cl_mem) == sizeof(cl_sampler), "api object size check failed");
1502 if (!Sampler::IsValid(*static_cast<const cl_sampler *>(arg_value)))
1503 {
1504 return CL_INVALID_SAMPLER;
1505 }
1506 }
1507 // CL_INVALID_DEVICE_QUEUE for an argument declared to be of type queue_t
1508 // when the specified arg_value is not a valid device queue object.
1509 else if (typeName == "queue_t")
1510 {
1511 static_assert(sizeof(cl_mem) == sizeof(cl_command_queue),
1512 "api object size check failed");
1513 const cl_command_queue queue = *static_cast<const cl_command_queue *>(arg_value);
1514 if (!CommandQueue::IsValid(queue) || !queue->cast<CommandQueue>().isOnDevice())
1515 {
1516 return CL_INVALID_DEVICE_QUEUE;
1517 }
1518 }
1519 }
1520
1521 return CL_SUCCESS;
1522 }
1523
ValidateGetKernelInfo(cl_kernel kernel,KernelInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)1524 cl_int ValidateGetKernelInfo(cl_kernel kernel,
1525 KernelInfo param_name,
1526 size_t param_value_size,
1527 const void *param_value,
1528 const size_t *param_value_size_ret)
1529 {
1530 // CL_INVALID_KERNEL if kernel is a not a valid kernel object.
1531 if (!Kernel::IsValid(kernel))
1532 {
1533 return CL_INVALID_KERNEL;
1534 }
1535
1536 // CL_INVALID_VALUE if param_name is not valid.
1537 const cl_version version =
1538 kernel->cast<Kernel>().getProgram().getContext().getPlatform().getVersion();
1539 switch (param_name)
1540 {
1541 case KernelInfo::Attributes:
1542 ANGLE_VALIDATE_VERSION(version, 1, 2);
1543 break;
1544 case KernelInfo::InvalidEnum:
1545 return CL_INVALID_VALUE;
1546 default:
1547 // All remaining possible values for param_name are valid for all versions.
1548 break;
1549 }
1550
1551 return CL_SUCCESS;
1552 }
1553
ValidateGetKernelWorkGroupInfo(cl_kernel kernel,cl_device_id device,KernelWorkGroupInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)1554 cl_int ValidateGetKernelWorkGroupInfo(cl_kernel kernel,
1555 cl_device_id device,
1556 KernelWorkGroupInfo param_name,
1557 size_t param_value_size,
1558 const void *param_value,
1559 const size_t *param_value_size_ret)
1560 {
1561 // CL_INVALID_KERNEL if kernel is a not a valid kernel object.
1562 if (!Kernel::IsValid(kernel))
1563 {
1564 return CL_INVALID_KERNEL;
1565 }
1566 const Kernel &krnl = kernel->cast<Kernel>();
1567
1568 const Device *dev = nullptr;
1569 if (device != nullptr)
1570 {
1571 // CL_INVALID_DEVICE if device is not in the list of devices associated with kernel ...
1572 if (krnl.getProgram().getContext().hasDevice(device))
1573 {
1574 dev = &device->cast<Device>();
1575 }
1576 else
1577 {
1578 return CL_INVALID_DEVICE;
1579 }
1580 }
1581 else
1582 {
1583 // or if device is NULL but there is more than one device associated with kernel.
1584 if (krnl.getProgram().getContext().getDevices().size() == 1u)
1585 {
1586 dev = krnl.getProgram().getContext().getDevices().front().get();
1587 }
1588 else
1589 {
1590 return CL_INVALID_DEVICE;
1591 }
1592 }
1593
1594 // CL_INVALID_VALUE if param_name is not valid.
1595 const cl_version version = krnl.getProgram().getContext().getPlatform().getInfo().version;
1596 switch (param_name)
1597 {
1598 case KernelWorkGroupInfo::GlobalWorkSize:
1599 ANGLE_VALIDATE_VERSION(version, 1, 2);
1600 // CL_INVALID_VALUE if param_name is CL_KERNEL_GLOBAL_WORK_SIZE and
1601 // device is not a custom device and kernel is not a built-in kernel.
1602 if (!dev->supportsBuiltInKernel(krnl.getInfo().functionName))
1603 {
1604 return CL_INVALID_VALUE;
1605 }
1606 break;
1607 case KernelWorkGroupInfo::InvalidEnum:
1608 return CL_INVALID_VALUE;
1609 default:
1610 // All remaining possible values for param_name are valid for all versions.
1611 break;
1612 }
1613
1614 return CL_SUCCESS;
1615 }
1616
ValidateWaitForEvents(cl_uint num_events,const cl_event * event_list)1617 cl_int ValidateWaitForEvents(cl_uint num_events, const cl_event *event_list)
1618 {
1619 // CL_INVALID_VALUE if num_events is zero or event_list is NULL.
1620 if (num_events == 0u || event_list == nullptr)
1621 {
1622 return CL_INVALID_VALUE;
1623 }
1624
1625 const Context *context = nullptr;
1626 while (num_events-- != 0u)
1627 {
1628 // CL_INVALID_EVENT if event objects specified in event_list are not valid event objects.
1629 if (!Event::IsValid(*event_list))
1630 {
1631 return CL_INVALID_EVENT;
1632 }
1633
1634 // CL_INVALID_CONTEXT if events specified in event_list do not belong to the same context.
1635 const Context *eventContext = &(*event_list++)->cast<Event>().getContext();
1636 if (context == nullptr)
1637 {
1638 context = eventContext;
1639 }
1640 else if (context != eventContext)
1641 {
1642 return CL_INVALID_CONTEXT;
1643 }
1644 }
1645
1646 return CL_SUCCESS;
1647 }
1648
ValidateGetEventInfo(cl_event event,EventInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)1649 cl_int ValidateGetEventInfo(cl_event event,
1650 EventInfo param_name,
1651 size_t param_value_size,
1652 const void *param_value,
1653 const size_t *param_value_size_ret)
1654 {
1655 // CL_INVALID_EVENT if event is a not a valid event object.
1656 if (!Event::IsValid(event))
1657 {
1658 return CL_INVALID_EVENT;
1659 }
1660
1661 // CL_INVALID_VALUE if param_name is not valid.
1662 const cl_version version = event->cast<Event>().getContext().getPlatform().getVersion();
1663 switch (param_name)
1664 {
1665 case EventInfo::Context:
1666 ANGLE_VALIDATE_VERSION(version, 1, 1);
1667 break;
1668 case EventInfo::InvalidEnum:
1669 return CL_INVALID_VALUE;
1670 default:
1671 // All remaining possible values for param_name are valid for all versions.
1672 break;
1673 }
1674
1675 return CL_SUCCESS;
1676 }
1677
ValidateRetainEvent(cl_event event)1678 cl_int ValidateRetainEvent(cl_event event)
1679 {
1680 // CL_INVALID_EVENT if event is not a valid event object.
1681 return Event::IsValid(event) ? CL_SUCCESS : CL_INVALID_EVENT;
1682 }
1683
ValidateReleaseEvent(cl_event event)1684 cl_int ValidateReleaseEvent(cl_event event)
1685 {
1686 // CL_INVALID_EVENT if event is not a valid event object.
1687 return Event::IsValid(event) ? CL_SUCCESS : CL_INVALID_EVENT;
1688 }
1689
ValidateGetEventProfilingInfo(cl_event event,ProfilingInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)1690 cl_int ValidateGetEventProfilingInfo(cl_event event,
1691 ProfilingInfo param_name,
1692 size_t param_value_size,
1693 const void *param_value,
1694 const size_t *param_value_size_ret)
1695 {
1696 // CL_INVALID_EVENT if event is a not a valid event object.
1697 if (!Event::IsValid(event))
1698 {
1699 return CL_INVALID_EVENT;
1700 }
1701 const Event &evt = event->cast<Event>();
1702
1703 // CL_PROFILING_INFO_NOT_AVAILABLE if event is a user event object,
1704 if (evt.getCommandType() == CL_COMMAND_USER)
1705 {
1706 return CL_PROFILING_INFO_NOT_AVAILABLE;
1707 }
1708 // or if the CL_QUEUE_PROFILING_ENABLE flag is not set for the command-queue.
1709 if (evt.getCommandQueue()->getProperties().isNotSet(CL_QUEUE_PROFILING_ENABLE))
1710 {
1711 return CL_PROFILING_INFO_NOT_AVAILABLE;
1712 }
1713
1714 // CL_INVALID_VALUE if param_name is not valid.
1715 const cl_version version = evt.getContext().getPlatform().getVersion();
1716 switch (param_name)
1717 {
1718 case ProfilingInfo::CommandComplete:
1719 ANGLE_VALIDATE_VERSION(version, 2, 0);
1720 break;
1721 case ProfilingInfo::InvalidEnum:
1722 return CL_INVALID_VALUE;
1723 default:
1724 // All remaining possible values for param_name are valid for all versions.
1725 break;
1726 }
1727
1728 return CL_SUCCESS;
1729 }
1730
ValidateFlush(cl_command_queue command_queue)1731 cl_int ValidateFlush(cl_command_queue command_queue)
1732 {
1733 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
1734 if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
1735 {
1736 return CL_INVALID_COMMAND_QUEUE;
1737 }
1738 return CL_SUCCESS;
1739 }
1740
ValidateFinish(cl_command_queue command_queue)1741 cl_int ValidateFinish(cl_command_queue command_queue)
1742 {
1743 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
1744 if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
1745 {
1746 return CL_INVALID_COMMAND_QUEUE;
1747 }
1748 return CL_SUCCESS;
1749 }
1750
ValidateEnqueueReadBuffer(cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_read,size_t offset,size_t size,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)1751 cl_int ValidateEnqueueReadBuffer(cl_command_queue command_queue,
1752 cl_mem buffer,
1753 cl_bool blocking_read,
1754 size_t offset,
1755 size_t size,
1756 const void *ptr,
1757 cl_uint num_events_in_wait_list,
1758 const cl_event *event_wait_list,
1759 const cl_event *event)
1760 {
1761 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
1762 num_events_in_wait_list, event_wait_list));
1763 ANGLE_VALIDATE(ValidateEnqueueBuffer(command_queue->cast<CommandQueue>(), buffer, true, false));
1764
1765 // CL_INVALID_VALUE if the region being read or written specified
1766 // by (offset, size) is out of bounds or if ptr is a NULL value.
1767 if (!buffer->cast<Buffer>().isRegionValid(offset, size) || ptr == nullptr)
1768 {
1769 return CL_INVALID_VALUE;
1770 }
1771
1772 return CL_SUCCESS;
1773 }
1774
ValidateEnqueueWriteBuffer(cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_write,size_t offset,size_t size,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)1775 cl_int ValidateEnqueueWriteBuffer(cl_command_queue command_queue,
1776 cl_mem buffer,
1777 cl_bool blocking_write,
1778 size_t offset,
1779 size_t size,
1780 const void *ptr,
1781 cl_uint num_events_in_wait_list,
1782 const cl_event *event_wait_list,
1783 const cl_event *event)
1784 {
1785 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
1786 num_events_in_wait_list, event_wait_list));
1787 ANGLE_VALIDATE(ValidateEnqueueBuffer(command_queue->cast<CommandQueue>(), buffer, false, true));
1788
1789 // CL_INVALID_VALUE if the region being read or written specified
1790 // by (offset, size) is out of bounds or if ptr is a NULL value.
1791 if (!buffer->cast<Buffer>().isRegionValid(offset, size) || ptr == nullptr)
1792 {
1793 return CL_INVALID_VALUE;
1794 }
1795
1796 return CL_SUCCESS;
1797 }
1798
ValidateEnqueueCopyBuffer(cl_command_queue command_queue,cl_mem src_buffer,cl_mem dst_buffer,size_t src_offset,size_t dst_offset,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)1799 cl_int ValidateEnqueueCopyBuffer(cl_command_queue command_queue,
1800 cl_mem src_buffer,
1801 cl_mem dst_buffer,
1802 size_t src_offset,
1803 size_t dst_offset,
1804 size_t size,
1805 cl_uint num_events_in_wait_list,
1806 const cl_event *event_wait_list,
1807 const cl_event *event)
1808 {
1809 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
1810 num_events_in_wait_list, event_wait_list));
1811 const CommandQueue &queue = command_queue->cast<CommandQueue>();
1812
1813 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, src_buffer, false, false));
1814 const Buffer &src = src_buffer->cast<Buffer>();
1815
1816 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, dst_buffer, false, false));
1817 const Buffer &dst = dst_buffer->cast<Buffer>();
1818
1819 // CL_INVALID_VALUE if src_offset, dst_offset, size, src_offset + size or dst_offset + size
1820 // require accessing elements outside the src_buffer and dst_buffer buffer objects respectively.
1821 if (!src.isRegionValid(src_offset, size) || !dst.isRegionValid(dst_offset, size))
1822 {
1823 return CL_INVALID_VALUE;
1824 }
1825
1826 // CL_MEM_COPY_OVERLAP if src_buffer and dst_buffer are the same buffer or sub-buffer object
1827 // and the source and destination regions overlap or if src_buffer and dst_buffer are
1828 // different sub-buffers of the same associated buffer object and they overlap.
1829 if ((src.isSubBuffer() ? src.getParent().get() : &src) ==
1830 (dst.isSubBuffer() ? dst.getParent().get() : &dst))
1831 {
1832 // Only sub-buffers have offsets larger than zero
1833 src_offset += src.getOffset();
1834 dst_offset += dst.getOffset();
1835
1836 if (OverlapRegions(src_offset, dst_offset, size))
1837 {
1838 return CL_MEM_COPY_OVERLAP;
1839 }
1840 }
1841
1842 return CL_SUCCESS;
1843 }
1844
ValidateEnqueueReadImage(cl_command_queue command_queue,cl_mem image,cl_bool blocking_read,const size_t * origin,const size_t * region,size_t row_pitch,size_t slice_pitch,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)1845 cl_int ValidateEnqueueReadImage(cl_command_queue command_queue,
1846 cl_mem image,
1847 cl_bool blocking_read,
1848 const size_t *origin,
1849 const size_t *region,
1850 size_t row_pitch,
1851 size_t slice_pitch,
1852 const void *ptr,
1853 cl_uint num_events_in_wait_list,
1854 const cl_event *event_wait_list,
1855 const cl_event *event)
1856 {
1857 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
1858 num_events_in_wait_list, event_wait_list));
1859 const CommandQueue &queue = command_queue->cast<CommandQueue>();
1860
1861 ANGLE_VALIDATE(ValidateEnqueueImage(queue, image, true, false));
1862 const Image &img = image->cast<Image>();
1863
1864 ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));
1865 ANGLE_VALIDATE(ValidateHostRegionForImage(img, region, row_pitch, slice_pitch, ptr));
1866
1867 return CL_SUCCESS;
1868 }
1869
ValidateEnqueueWriteImage(cl_command_queue command_queue,cl_mem image,cl_bool blocking_write,const size_t * origin,const size_t * region,size_t input_row_pitch,size_t input_slice_pitch,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)1870 cl_int ValidateEnqueueWriteImage(cl_command_queue command_queue,
1871 cl_mem image,
1872 cl_bool blocking_write,
1873 const size_t *origin,
1874 const size_t *region,
1875 size_t input_row_pitch,
1876 size_t input_slice_pitch,
1877 const void *ptr,
1878 cl_uint num_events_in_wait_list,
1879 const cl_event *event_wait_list,
1880 const cl_event *event)
1881 {
1882 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
1883 num_events_in_wait_list, event_wait_list));
1884 const CommandQueue &queue = command_queue->cast<CommandQueue>();
1885
1886 ANGLE_VALIDATE(ValidateEnqueueImage(queue, image, false, true));
1887 const Image &img = image->cast<Image>();
1888
1889 ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));
1890 ANGLE_VALIDATE(
1891 ValidateHostRegionForImage(img, region, input_row_pitch, input_slice_pitch, ptr));
1892
1893 return CL_SUCCESS;
1894 }
1895
ValidateEnqueueCopyImage(cl_command_queue command_queue,cl_mem src_image,cl_mem dst_image,const size_t * src_origin,const size_t * dst_origin,const size_t * region,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)1896 cl_int ValidateEnqueueCopyImage(cl_command_queue command_queue,
1897 cl_mem src_image,
1898 cl_mem dst_image,
1899 const size_t *src_origin,
1900 const size_t *dst_origin,
1901 const size_t *region,
1902 cl_uint num_events_in_wait_list,
1903 const cl_event *event_wait_list,
1904 const cl_event *event)
1905 {
1906 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
1907 num_events_in_wait_list, event_wait_list));
1908 const CommandQueue &queue = command_queue->cast<CommandQueue>();
1909
1910 ANGLE_VALIDATE(ValidateEnqueueImage(queue, src_image, false, false));
1911 const Image &src = src_image->cast<Image>();
1912
1913 ANGLE_VALIDATE(ValidateEnqueueImage(queue, dst_image, false, false));
1914 const Image &dst = dst_image->cast<Image>();
1915
1916 // CL_IMAGE_FORMAT_MISMATCH if src_image and dst_image do not use the same image format.
1917 if (src.getFormat().image_channel_order != dst.getFormat().image_channel_order ||
1918 src.getFormat().image_channel_data_type != dst.getFormat().image_channel_data_type)
1919 {
1920 return CL_IMAGE_FORMAT_MISMATCH;
1921 }
1922
1923 ANGLE_VALIDATE(ValidateImageForDevice(src, queue.getDevice(), src_origin, region));
1924 ANGLE_VALIDATE(ValidateImageForDevice(dst, queue.getDevice(), dst_origin, region));
1925
1926 // CL_MEM_COPY_OVERLAP if src_image and dst_image are the same image object
1927 // and the source and destination regions overlap.
1928 if (&src == &dst)
1929 {
1930 const MemObjectType type = src.getType();
1931 // Check overlap in first dimension
1932 if (OverlapRegions(src_origin[0], dst_origin[0], region[0]))
1933 {
1934 if (type == MemObjectType::Image1D || type == MemObjectType::Image1D_Buffer)
1935 {
1936 return CL_MEM_COPY_OVERLAP;
1937 }
1938
1939 // Check overlap in second dimension
1940 if (OverlapRegions(src_origin[1], dst_origin[1], region[1]))
1941 {
1942 if (type == MemObjectType::Image2D || type == MemObjectType::Image1D_Array)
1943 {
1944 return CL_MEM_COPY_OVERLAP;
1945 }
1946
1947 // Check overlap in third dimension
1948 if (OverlapRegions(src_origin[2], dst_origin[2], region[2]))
1949 {
1950 return CL_MEM_COPY_OVERLAP;
1951 }
1952 }
1953 }
1954 }
1955
1956 return CL_SUCCESS;
1957 }
1958
ValidateEnqueueCopyImageToBuffer(cl_command_queue command_queue,cl_mem src_image,cl_mem dst_buffer,const size_t * src_origin,const size_t * region,size_t dst_offset,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)1959 cl_int ValidateEnqueueCopyImageToBuffer(cl_command_queue command_queue,
1960 cl_mem src_image,
1961 cl_mem dst_buffer,
1962 const size_t *src_origin,
1963 const size_t *region,
1964 size_t dst_offset,
1965 cl_uint num_events_in_wait_list,
1966 const cl_event *event_wait_list,
1967 const cl_event *event)
1968 {
1969 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
1970 num_events_in_wait_list, event_wait_list));
1971 const CommandQueue &queue = command_queue->cast<CommandQueue>();
1972
1973 ANGLE_VALIDATE(ValidateEnqueueImage(queue, src_image, false, false));
1974 const Image &src = src_image->cast<Image>();
1975
1976 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, dst_buffer, false, false));
1977 const Buffer &dst = dst_buffer->cast<Buffer>();
1978
1979 // CL_INVALID_MEM_OBJECT if src_image is a 1D image buffer object created from dst_buffer.
1980 if (src.getType() == MemObjectType::Image1D_Buffer && src.getParent() == &dst)
1981 {
1982 return CL_INVALID_MEM_OBJECT;
1983 }
1984
1985 ANGLE_VALIDATE(ValidateImageForDevice(src, queue.getDevice(), src_origin, region));
1986
1987 // CL_INVALID_VALUE if the region specified by dst_offset and dst_offset + dst_cb
1988 // refer to a region outside dst_buffer.
1989 const MemObjectType type = src.getType();
1990 size_t dst_cb = src.getElementSize() * region[0];
1991 if (type != MemObjectType::Image1D && type != MemObjectType::Image1D_Buffer)
1992 {
1993 dst_cb *= region[1];
1994 if (type != MemObjectType::Image2D && type != MemObjectType::Image1D_Array)
1995 {
1996 dst_cb *= region[2];
1997 }
1998 }
1999 if (!dst.isRegionValid(dst_offset, dst_cb))
2000 {
2001 return CL_INVALID_VALUE;
2002 }
2003
2004 return CL_SUCCESS;
2005 }
2006
ValidateEnqueueCopyBufferToImage(cl_command_queue command_queue,cl_mem src_buffer,cl_mem dst_image,size_t src_offset,const size_t * dst_origin,const size_t * region,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2007 cl_int ValidateEnqueueCopyBufferToImage(cl_command_queue command_queue,
2008 cl_mem src_buffer,
2009 cl_mem dst_image,
2010 size_t src_offset,
2011 const size_t *dst_origin,
2012 const size_t *region,
2013 cl_uint num_events_in_wait_list,
2014 const cl_event *event_wait_list,
2015 const cl_event *event)
2016 {
2017 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
2018 num_events_in_wait_list, event_wait_list));
2019 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2020
2021 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, src_buffer, false, false));
2022 const Buffer &src = src_buffer->cast<Buffer>();
2023
2024 ANGLE_VALIDATE(ValidateEnqueueImage(queue, dst_image, false, false));
2025 const Image &dst = dst_image->cast<Image>();
2026
2027 // CL_INVALID_MEM_OBJECT if dst_image is a 1D image buffer object created from src_buffer.
2028 if (dst.getType() == MemObjectType::Image1D_Buffer && dst.getParent() == &src)
2029 {
2030 return CL_INVALID_MEM_OBJECT;
2031 }
2032
2033 ANGLE_VALIDATE(ValidateImageForDevice(dst, queue.getDevice(), dst_origin, region));
2034
2035 // CL_INVALID_VALUE if the region specified by src_offset and src_offset + src_cb
2036 // refer to a region outside src_buffer.
2037 const MemObjectType type = dst.getType();
2038 size_t src_cb = dst.getElementSize() * region[0];
2039 if (type != MemObjectType::Image1D && type != MemObjectType::Image1D_Buffer)
2040 {
2041 src_cb *= region[1];
2042 if (type != MemObjectType::Image2D && type != MemObjectType::Image1D_Array)
2043 {
2044 src_cb *= region[2];
2045 }
2046 }
2047 if (!src.isRegionValid(src_offset, src_cb))
2048 {
2049 return CL_INVALID_VALUE;
2050 }
2051
2052 return CL_SUCCESS;
2053 }
2054
ValidateEnqueueMapBuffer(cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_map,MapFlags map_flags,size_t offset,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2055 cl_int ValidateEnqueueMapBuffer(cl_command_queue command_queue,
2056 cl_mem buffer,
2057 cl_bool blocking_map,
2058 MapFlags map_flags,
2059 size_t offset,
2060 size_t size,
2061 cl_uint num_events_in_wait_list,
2062 const cl_event *event_wait_list,
2063 const cl_event *event)
2064 {
2065 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2066 num_events_in_wait_list, event_wait_list));
2067 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2068
2069 // CL_INVALID_OPERATION if buffer has been created with CL_MEM_HOST_WRITE_ONLY or
2070 // CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set in map_flags
2071 // or if buffer has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS
2072 // and CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is set in map_flags.
2073 ANGLE_VALIDATE(
2074 ValidateEnqueueBuffer(queue, buffer, map_flags.isSet(CL_MAP_READ),
2075 map_flags.isSet(CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)));
2076
2077 // CL_INVALID_VALUE if region being mapped given by (offset, size) is out of bounds
2078 // or if size is 0 or if values specified in map_flags are not valid.
2079 if (!buffer->cast<Buffer>().isRegionValid(offset, size) || size == 0u ||
2080 !ValidateMapFlags(map_flags, queue.getContext().getPlatform()))
2081 {
2082 return CL_INVALID_VALUE;
2083 }
2084
2085 return CL_SUCCESS;
2086 }
2087
ValidateEnqueueMapImage(cl_command_queue command_queue,cl_mem image,cl_bool blocking_map,MapFlags map_flags,const size_t * origin,const size_t * region,const size_t * image_row_pitch,const size_t * image_slice_pitch,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2088 cl_int ValidateEnqueueMapImage(cl_command_queue command_queue,
2089 cl_mem image,
2090 cl_bool blocking_map,
2091 MapFlags map_flags,
2092 const size_t *origin,
2093 const size_t *region,
2094 const size_t *image_row_pitch,
2095 const size_t *image_slice_pitch,
2096 cl_uint num_events_in_wait_list,
2097 const cl_event *event_wait_list,
2098 const cl_event *event)
2099 {
2100 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
2101 num_events_in_wait_list, event_wait_list));
2102 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2103
2104 // CL_INVALID_OPERATION if image has been created with CL_MEM_HOST_WRITE_ONLY or
2105 // CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set in map_flags
2106 // or if image has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS
2107 // and CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is set in map_flags.
2108 ANGLE_VALIDATE(
2109 ValidateEnqueueImage(queue, image, map_flags.isSet(CL_MAP_READ),
2110 map_flags.isSet(CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)));
2111 const Image &img = image->cast<Image>();
2112
2113 ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));
2114
2115 // CL_INVALID_VALUE if values specified in map_flags are not valid.
2116 if (!ValidateMapFlags(map_flags, queue.getContext().getPlatform()))
2117 {
2118 return CL_INVALID_VALUE;
2119 }
2120
2121 // CL_INVALID_VALUE if image_row_pitch is NULL.
2122 if (image_row_pitch == nullptr)
2123 {
2124 return CL_INVALID_VALUE;
2125 }
2126
2127 // CL_INVALID_VALUE if image is a 3D image, 1D or 2D image array object
2128 // and image_slice_pitch is NULL.
2129 if ((img.getType() == MemObjectType::Image3D || img.getType() == MemObjectType::Image1D_Array ||
2130 img.getType() == MemObjectType::Image2D_Array) &&
2131 image_slice_pitch == nullptr)
2132 {
2133 return CL_INVALID_VALUE;
2134 }
2135
2136 return CL_SUCCESS;
2137 }
2138
ValidateEnqueueUnmapMemObject(cl_command_queue command_queue,cl_mem memobj,const void * mapped_ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2139 cl_int ValidateEnqueueUnmapMemObject(cl_command_queue command_queue,
2140 cl_mem memobj,
2141 const void *mapped_ptr,
2142 cl_uint num_events_in_wait_list,
2143 const cl_event *event_wait_list,
2144 const cl_event *event)
2145 {
2146 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2147 num_events_in_wait_list, event_wait_list));
2148 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2149
2150 // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object or is a pipe object.
2151 if (!Memory::IsValid(memobj))
2152 {
2153 return CL_INVALID_MEM_OBJECT;
2154 }
2155 const Memory &memory = memobj->cast<Memory>();
2156 if (memory.getType() == MemObjectType::Pipe)
2157 {
2158 return CL_INVALID_MEM_OBJECT;
2159 }
2160
2161 // CL_INVALID_CONTEXT if context associated with command_queue and memobj are not the same.
2162 if (&queue.getContext() != &memory.getContext())
2163 {
2164 return CL_INVALID_CONTEXT;
2165 }
2166
2167 return CL_SUCCESS;
2168 }
2169
ValidateEnqueueNDRangeKernel(cl_command_queue command_queue,cl_kernel kernel,cl_uint work_dim,const size_t * global_work_offset,const size_t * global_work_size,const size_t * local_work_size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2170 cl_int ValidateEnqueueNDRangeKernel(cl_command_queue command_queue,
2171 cl_kernel kernel,
2172 cl_uint work_dim,
2173 const size_t *global_work_offset,
2174 const size_t *global_work_size,
2175 const size_t *local_work_size,
2176 cl_uint num_events_in_wait_list,
2177 const cl_event *event_wait_list,
2178 const cl_event *event)
2179 {
2180 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2181 num_events_in_wait_list, event_wait_list));
2182 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2183 const Device &device = queue.getDevice();
2184
2185 // CL_INVALID_KERNEL if kernel is not a valid kernel object.
2186 if (!Kernel::IsValid(kernel))
2187 {
2188 return CL_INVALID_KERNEL;
2189 }
2190 const Kernel &krnl = kernel->cast<Kernel>();
2191
2192 // CL_INVALID_CONTEXT if context associated with command_queue and kernel are not the same.
2193 if (&queue.getContext() != &krnl.getProgram().getContext())
2194 {
2195 return CL_INVALID_CONTEXT;
2196 }
2197
2198 // CL_INVALID_WORK_DIMENSION if work_dim is not a valid value.
2199 if (work_dim == 0u || work_dim > device.getInfo().maxWorkItemSizes.size())
2200 {
2201 return CL_INVALID_WORK_DIMENSION;
2202 }
2203
2204 // CL_INVALID_GLOBAL_OFFSET if global_work_offset is non-NULL before version 1.1.
2205 if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u) && global_work_offset != nullptr)
2206 {
2207 return CL_INVALID_GLOBAL_OFFSET;
2208 }
2209
2210 // CL_INVALID_WORK_GROUP_SIZE if local_work_size is specified and does not match the required
2211 // work-group size for kernel in the program source.
2212 size_t compileWorkGroupSize[3] = {0, 0, 0};
2213 if (IsError(krnl.getWorkGroupInfo(const_cast<cl_device_id>(device.getNative()),
2214 KernelWorkGroupInfo::CompileWorkGroupSize,
2215 sizeof(compileWorkGroupSize), compileWorkGroupSize, nullptr)))
2216 {
2217 return CL_INVALID_VALUE;
2218 }
2219 if (local_work_size != nullptr)
2220 {
2221 for (cl_uint i = 0; i < work_dim; ++i)
2222 {
2223 if (compileWorkGroupSize[i] != 0 && local_work_size[i] != compileWorkGroupSize[i])
2224 {
2225 return CL_INVALID_WORK_GROUP_SIZE;
2226 }
2227 }
2228 }
2229
2230 // CL_INVALID_GLOBAL_WORK_SIZE if global_work_size is NULL or if any of the values
2231 // specified in global_work_size[0] ... global_work_size[work_dim - 1] are 0.
2232 // Returning this error code under these circumstances is deprecated by version 2.1.
2233 if (!queue.getContext().getPlatform().isVersionOrNewer(2u, 1u))
2234 {
2235 if (global_work_size == nullptr)
2236 {
2237 return CL_INVALID_GLOBAL_WORK_SIZE;
2238 }
2239 for (cl_uint dim = 0u; dim < work_dim; ++dim)
2240 {
2241 if (global_work_size[dim] == 0u)
2242 {
2243 return CL_INVALID_GLOBAL_WORK_SIZE;
2244 }
2245 }
2246 }
2247
2248 if (local_work_size != nullptr)
2249 {
2250 size_t numWorkItems = 1u; // Initialize with neutral element for multiplication
2251
2252 // CL_INVALID_WORK_ITEM_SIZE if the number of work-items specified
2253 // in any of local_work_size[0] ... local_work_size[work_dim - 1]
2254 // is greater than the corresponding values specified by
2255 // CL_DEVICE_MAX_WORK_ITEM_SIZES[0] ... CL_DEVICE_MAX_WORK_ITEM_SIZES[work_dim - 1].
2256 for (cl_uint dim = 0u; dim < work_dim; ++dim)
2257 {
2258 if (local_work_size[dim] > device.getInfo().maxWorkItemSizes[dim])
2259 {
2260 return CL_INVALID_WORK_ITEM_SIZE;
2261 }
2262 numWorkItems *= local_work_size[dim];
2263 }
2264
2265 // CL_INVALID_WORK_GROUP_SIZE if local_work_size is specified
2266 // and the total number of work-items in the work-group computed as
2267 // local_work_size[0] x ... local_work_size[work_dim - 1] is greater than the value
2268 // specified by CL_KERNEL_WORK_GROUP_SIZE in the Kernel Object Device Queries table.
2269 if (numWorkItems > krnl.getInfo().workGroups[queue.getDeviceIndex()].workGroupSize)
2270 {
2271 return CL_INVALID_WORK_GROUP_SIZE;
2272 }
2273 }
2274
2275 return CL_SUCCESS;
2276 }
2277
ValidateEnqueueNativeKernel(cl_command_queue command_queue,void (CL_CALLBACK * user_func)(void *),const void * args,size_t cb_args,cl_uint num_mem_objects,const cl_mem * mem_list,const void ** args_mem_loc,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2278 cl_int ValidateEnqueueNativeKernel(cl_command_queue command_queue,
2279 void(CL_CALLBACK *user_func)(void *),
2280 const void *args,
2281 size_t cb_args,
2282 cl_uint num_mem_objects,
2283 const cl_mem *mem_list,
2284 const void **args_mem_loc,
2285 cl_uint num_events_in_wait_list,
2286 const cl_event *event_wait_list,
2287 const cl_event *event)
2288 {
2289 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2290 num_events_in_wait_list, event_wait_list));
2291 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2292
2293 // CL_INVALID_OPERATION if the device associated with command_queue
2294 // cannot execute the native kernel.
2295 if (queue.getDevice().getInfo().execCapabilities.isNotSet(CL_EXEC_NATIVE_KERNEL))
2296 {
2297 return CL_INVALID_OPERATION;
2298 }
2299
2300 // CL_INVALID_VALUE if user_func is NULL.
2301 if (user_func == nullptr)
2302 {
2303 return CL_INVALID_VALUE;
2304 }
2305
2306 if (args == nullptr)
2307 {
2308 // CL_INVALID_VALUE if args is a NULL value and cb_args > 0 or num_mem_objects > 0.
2309 if (cb_args > 0u || num_mem_objects > 0u)
2310 {
2311 return CL_INVALID_VALUE;
2312 }
2313 }
2314 else
2315 {
2316 // CL_INVALID_VALUE if args is not NULL and cb_args is 0.
2317 if (cb_args == 0u)
2318 {
2319 return CL_INVALID_VALUE;
2320 }
2321 }
2322
2323 if (num_mem_objects == 0u)
2324 {
2325 // CL_INVALID_VALUE if num_mem_objects = 0 and mem_list or args_mem_loc are not NULL.
2326 if (mem_list != nullptr || args_mem_loc != nullptr)
2327 {
2328 return CL_INVALID_VALUE;
2329 }
2330 }
2331 else
2332 {
2333 // CL_INVALID_VALUE if num_mem_objects > 0 and mem_list or args_mem_loc are NULL.
2334 if (mem_list == nullptr || args_mem_loc == nullptr)
2335 {
2336 return CL_INVALID_VALUE;
2337 }
2338
2339 // CL_INVALID_MEM_OBJECT if one or more memory objects
2340 // specified in mem_list are not valid or are not buffer objects.
2341 while (num_mem_objects-- != 0u)
2342 {
2343 if (!Buffer::IsValid(*mem_list++))
2344 {
2345 return CL_INVALID_MEM_OBJECT;
2346 }
2347 }
2348 }
2349
2350 return CL_SUCCESS;
2351 }
2352
ValidateSetCommandQueueProperty(cl_command_queue command_queue,CommandQueueProperties properties,cl_bool enable,const cl_command_queue_properties * old_properties)2353 cl_int ValidateSetCommandQueueProperty(cl_command_queue command_queue,
2354 CommandQueueProperties properties,
2355 cl_bool enable,
2356 const cl_command_queue_properties *old_properties)
2357 {
2358 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
2359 if (!CommandQueue::IsValid(command_queue))
2360 {
2361 return CL_INVALID_COMMAND_QUEUE;
2362 }
2363
2364 // CL_INVALID_VALUE if values specified in properties are not valid.
2365 if (properties.hasOtherBitsThan(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
2366 CL_QUEUE_PROFILING_ENABLE))
2367 {
2368 return CL_INVALID_VALUE;
2369 }
2370
2371 return CL_SUCCESS;
2372 }
2373
ValidateCreateImage2D(cl_context context,MemFlags flags,const cl_image_format * image_format,size_t image_width,size_t image_height,size_t image_row_pitch,const void * host_ptr)2374 cl_int ValidateCreateImage2D(cl_context context,
2375 MemFlags flags,
2376 const cl_image_format *image_format,
2377 size_t image_width,
2378 size_t image_height,
2379 size_t image_row_pitch,
2380 const void *host_ptr)
2381 {
2382 const cl_image_desc desc = {CL_MEM_OBJECT_IMAGE2D, image_width, image_height, 0u, 0u,
2383 image_row_pitch, 0u, 0u, 0u, {nullptr}};
2384 return ValidateCreateImage(context, flags, image_format, &desc, host_ptr);
2385 }
2386
ValidateCreateImage3D(cl_context context,MemFlags flags,const cl_image_format * image_format,size_t image_width,size_t image_height,size_t image_depth,size_t image_row_pitch,size_t image_slice_pitch,const void * host_ptr)2387 cl_int ValidateCreateImage3D(cl_context context,
2388 MemFlags flags,
2389 const cl_image_format *image_format,
2390 size_t image_width,
2391 size_t image_height,
2392 size_t image_depth,
2393 size_t image_row_pitch,
2394 size_t image_slice_pitch,
2395 const void *host_ptr)
2396 {
2397 const cl_image_desc desc = {
2398 CL_MEM_OBJECT_IMAGE3D, image_width, image_height, image_depth, 0u,
2399 image_row_pitch, image_slice_pitch, 0u, 0u, {nullptr}};
2400 return ValidateCreateImage(context, flags, image_format, &desc, host_ptr);
2401 }
2402
ValidateEnqueueMarker(cl_command_queue command_queue,const cl_event * event)2403 cl_int ValidateEnqueueMarker(cl_command_queue command_queue, const cl_event *event)
2404 {
2405 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
2406 if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
2407 {
2408 return CL_INVALID_COMMAND_QUEUE;
2409 }
2410
2411 // CL_INVALID_VALUE if event is NULL.
2412 if (event == nullptr)
2413 {
2414 return CL_INVALID_VALUE;
2415 }
2416
2417 return CL_SUCCESS;
2418 }
2419
ValidateEnqueueWaitForEvents(cl_command_queue command_queue,cl_uint num_events,const cl_event * event_list)2420 cl_int ValidateEnqueueWaitForEvents(cl_command_queue command_queue,
2421 cl_uint num_events,
2422 const cl_event *event_list)
2423 {
2424 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
2425 if (!CommandQueue::IsValid(command_queue))
2426 {
2427 return CL_INVALID_COMMAND_QUEUE;
2428 }
2429 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2430 if (!queue.isOnHost())
2431 {
2432 return CL_INVALID_COMMAND_QUEUE;
2433 }
2434
2435 // CL_INVALID_VALUE if num_events is 0 or event_list is NULL.
2436 if (num_events == 0u || event_list == nullptr)
2437 {
2438 return CL_INVALID_VALUE;
2439 }
2440
2441 while (num_events-- != 0u)
2442 {
2443 // The documentation for invalid events is missing.
2444 if (!Event::IsValid(*event_list))
2445 {
2446 return CL_INVALID_VALUE;
2447 }
2448
2449 // CL_INVALID_CONTEXT if context associated with command_queue
2450 // and events in event_list are not the same.
2451 if (&queue.getContext() != &(*event_list++)->cast<Event>().getContext())
2452 {
2453 return CL_INVALID_CONTEXT;
2454 }
2455 }
2456
2457 return CL_SUCCESS;
2458 }
2459
ValidateEnqueueBarrier(cl_command_queue command_queue)2460 cl_int ValidateEnqueueBarrier(cl_command_queue command_queue)
2461 {
2462 // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
2463 if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
2464 {
2465 return CL_INVALID_COMMAND_QUEUE;
2466 }
2467 return CL_SUCCESS;
2468 }
2469
ValidateUnloadCompiler()2470 cl_int ValidateUnloadCompiler()
2471 {
2472 return CL_SUCCESS;
2473 }
2474
ValidateGetExtensionFunctionAddress(const char * func_name)2475 cl_int ValidateGetExtensionFunctionAddress(const char *func_name)
2476 {
2477 return func_name != nullptr && *func_name != '\0' ? CL_SUCCESS : CL_INVALID_VALUE;
2478 }
2479
ValidateCreateCommandQueue(cl_context context,cl_device_id device,CommandQueueProperties properties)2480 cl_int ValidateCreateCommandQueue(cl_context context,
2481 cl_device_id device,
2482 CommandQueueProperties properties)
2483 {
2484 // CL_INVALID_CONTEXT if context is not a valid context.
2485 if (!Context::IsValid(context))
2486 {
2487 return CL_INVALID_CONTEXT;
2488 }
2489
2490 // CL_INVALID_DEVICE if device is not a valid device or is not associated with context.
2491 if (!context->cast<Context>().hasDevice(device))
2492 {
2493 return CL_INVALID_DEVICE;
2494 }
2495
2496 // CL_INVALID_VALUE if values specified in properties are not valid.
2497 if (properties.hasOtherBitsThan(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
2498 CL_QUEUE_PROFILING_ENABLE))
2499 {
2500 return CL_INVALID_VALUE;
2501 }
2502
2503 return CL_SUCCESS;
2504 }
2505
ValidateCreateSampler(cl_context context,cl_bool normalized_coords,AddressingMode addressing_mode,FilterMode filter_mode)2506 cl_int ValidateCreateSampler(cl_context context,
2507 cl_bool normalized_coords,
2508 AddressingMode addressing_mode,
2509 FilterMode filter_mode)
2510 {
2511 // CL_INVALID_CONTEXT if context is not a valid context.
2512 if (!Context::IsValid(context))
2513 {
2514 return CL_INVALID_CONTEXT;
2515 }
2516
2517 // CL_INVALID_VALUE if addressing_mode, filter_mode, normalized_coords
2518 // or a combination of these arguements are not valid.
2519 if ((normalized_coords != CL_FALSE && normalized_coords != CL_TRUE) ||
2520 addressing_mode == AddressingMode::InvalidEnum || filter_mode == FilterMode::InvalidEnum)
2521 {
2522 return CL_INVALID_VALUE;
2523 }
2524
2525 // CL_INVALID_OPERATION if images are not supported by any device associated with context.
2526 if (!context->cast<Context>().supportsImages())
2527 {
2528 return CL_INVALID_OPERATION;
2529 }
2530
2531 return CL_SUCCESS;
2532 }
2533
ValidateEnqueueTask(cl_command_queue command_queue,cl_kernel kernel,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2534 cl_int ValidateEnqueueTask(cl_command_queue command_queue,
2535 cl_kernel kernel,
2536 cl_uint num_events_in_wait_list,
2537 const cl_event *event_wait_list,
2538 const cl_event *event)
2539 {
2540 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2541 num_events_in_wait_list, event_wait_list));
2542
2543 // CL_INVALID_KERNEL if kernel is not a valid kernel object.
2544 if (!Kernel::IsValid(kernel))
2545 {
2546 return CL_INVALID_KERNEL;
2547 }
2548
2549 // CL_INVALID_CONTEXT if context associated with command_queue and kernel are not the same.
2550 if (&command_queue->cast<CommandQueue>().getContext() !=
2551 &kernel->cast<Kernel>().getProgram().getContext())
2552 {
2553 return CL_INVALID_CONTEXT;
2554 }
2555
2556 return CL_SUCCESS;
2557 }
2558
2559 // CL 1.1
ValidateCreateSubBuffer(cl_mem buffer,MemFlags flags,cl_buffer_create_type buffer_create_type,const void * buffer_create_info)2560 cl_int ValidateCreateSubBuffer(cl_mem buffer,
2561 MemFlags flags,
2562 cl_buffer_create_type buffer_create_type,
2563 const void *buffer_create_info)
2564 {
2565 // CL_INVALID_MEM_OBJECT if buffer is not a valid buffer object or is a sub-buffer object.
2566 if (!Buffer::IsValid(buffer))
2567 {
2568 return CL_INVALID_MEM_OBJECT;
2569 }
2570 const Buffer &buf = buffer->cast<Buffer>();
2571 if (buf.isSubBuffer() || !buf.getContext().getPlatform().isVersionOrNewer(1u, 1u))
2572 {
2573 return CL_INVALID_MEM_OBJECT;
2574 }
2575
2576 if (!ValidateMemoryFlags(flags, buf.getContext().getPlatform()))
2577 {
2578 return CL_INVALID_VALUE;
2579 }
2580
2581 const MemFlags bufFlags = buf.getFlags();
2582 // CL_INVALID_VALUE if buffer was created with CL_MEM_WRITE_ONLY
2583 // and flags specifies CL_MEM_READ_WRITE or CL_MEM_READ_ONLY,
2584 if ((bufFlags.isSet(CL_MEM_WRITE_ONLY) && flags.isSet(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY)) ||
2585 // or if buffer was created with CL_MEM_READ_ONLY
2586 // and flags specifies CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY,
2587 (bufFlags.isSet(CL_MEM_READ_ONLY) && flags.isSet(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY)) ||
2588 // or if flags specifies CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR or CL_MEM_COPY_HOST_PTR.
2589 flags.isSet(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR))
2590 {
2591 return CL_INVALID_VALUE;
2592 }
2593
2594 // CL_INVALID_VALUE if buffer was created with CL_MEM_HOST_WRITE_ONLY
2595 // and flags specify CL_MEM_HOST_READ_ONLY,
2596 if ((bufFlags.isSet(CL_MEM_HOST_WRITE_ONLY) && flags.isSet(CL_MEM_HOST_READ_ONLY)) ||
2597 // or if buffer was created with CL_MEM_HOST_READ_ONLY
2598 // and flags specify CL_MEM_HOST_WRITE_ONLY,
2599 (bufFlags.isSet(CL_MEM_HOST_READ_ONLY) && flags.isSet(CL_MEM_HOST_WRITE_ONLY)) ||
2600 // or if buffer was created with CL_MEM_HOST_NO_ACCESS
2601 // and flags specify CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_WRITE_ONLY.
2602 (bufFlags.isSet(CL_MEM_HOST_NO_ACCESS) &&
2603 flags.isSet(CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY)))
2604 {
2605 return CL_INVALID_VALUE;
2606 }
2607
2608 // CL_INVALID_VALUE if the value specified in buffer_create_type is not valid.
2609 if (buffer_create_type != CL_BUFFER_CREATE_TYPE_REGION)
2610 {
2611 return CL_INVALID_VALUE;
2612 }
2613
2614 // CL_INVALID_VALUE if value(s) specified in buffer_create_info
2615 // (for a given buffer_create_type) is not valid or if buffer_create_info is NULL.
2616 // CL_INVALID_VALUE if the region specified by the cl_buffer_region structure
2617 // passed in buffer_create_info is out of bounds in buffer.
2618 const cl_buffer_region *region = static_cast<const cl_buffer_region *>(buffer_create_info);
2619 if (region == nullptr || !buf.isRegionValid(*region))
2620 {
2621 return CL_INVALID_VALUE;
2622 }
2623
2624 // CL_INVALID_BUFFER_SIZE if the size field of the cl_buffer_region structure
2625 // passed in buffer_create_info is 0.
2626 if (region->size == 0u)
2627 {
2628 return CL_INVALID_BUFFER_SIZE;
2629 }
2630
2631 return CL_SUCCESS;
2632 }
2633
ValidateSetMemObjectDestructorCallback(cl_mem memobj,void (CL_CALLBACK * pfn_notify)(cl_mem memobj,void * user_data),const void * user_data)2634 cl_int ValidateSetMemObjectDestructorCallback(cl_mem memobj,
2635 void(CL_CALLBACK *pfn_notify)(cl_mem memobj,
2636 void *user_data),
2637 const void *user_data)
2638 {
2639 // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object.
2640 if (!Memory::IsValid(memobj))
2641 {
2642 return CL_INVALID_MEM_OBJECT;
2643 }
2644
2645 // CL_INVALID_VALUE if pfn_notify is NULL.
2646 if (pfn_notify == nullptr)
2647 {
2648 return CL_INVALID_VALUE;
2649 }
2650
2651 return CL_SUCCESS;
2652 }
2653
ValidateCreateUserEvent(cl_context context)2654 cl_int ValidateCreateUserEvent(cl_context context)
2655 {
2656 // CL_INVALID_CONTEXT if context is not a valid context.
2657 return Context::IsValidAndVersionOrNewer(context, 1u, 1u) ? CL_SUCCESS : CL_INVALID_CONTEXT;
2658 }
2659
ValidateSetUserEventStatus(cl_event event,cl_int execution_status)2660 cl_int ValidateSetUserEventStatus(cl_event event, cl_int execution_status)
2661 {
2662 // CL_INVALID_EVENT if event is not a valid user event object.
2663 if (!Event::IsValid(event))
2664 {
2665 return CL_INVALID_EVENT;
2666 }
2667 const Event &evt = event->cast<Event>();
2668 if (!evt.getContext().getPlatform().isVersionOrNewer(1u, 1u) ||
2669 evt.getCommandType() != CL_COMMAND_USER)
2670 {
2671 return CL_INVALID_EVENT;
2672 }
2673
2674 // CL_INVALID_VALUE if the execution_status is not CL_COMPLETE or a negative integer value.
2675 if (execution_status != CL_COMPLETE && execution_status >= 0)
2676 {
2677 return CL_INVALID_VALUE;
2678 }
2679
2680 // CL_INVALID_OPERATION if the execution_status for event has already been changed
2681 // by a previous call to clSetUserEventStatus.
2682 if (evt.wasStatusChanged())
2683 {
2684 return CL_INVALID_OPERATION;
2685 }
2686
2687 return CL_SUCCESS;
2688 }
2689
ValidateSetEventCallback(cl_event event,cl_int command_exec_callback_type,void (CL_CALLBACK * pfn_notify)(cl_event event,cl_int event_command_status,void * user_data),const void * user_data)2690 cl_int ValidateSetEventCallback(cl_event event,
2691 cl_int command_exec_callback_type,
2692 void(CL_CALLBACK *pfn_notify)(cl_event event,
2693 cl_int event_command_status,
2694 void *user_data),
2695 const void *user_data)
2696 {
2697 // CL_INVALID_EVENT if event is not a valid event object.
2698 if (!Event::IsValid(event) ||
2699 !event->cast<Event>().getContext().getPlatform().isVersionOrNewer(1u, 1u))
2700 {
2701 return CL_INVALID_EVENT;
2702 }
2703
2704 // CL_INVALID_VALUE if pfn_event_notify is NULL
2705 // or if command_exec_callback_type is not CL_SUBMITTED, CL_RUNNING, or CL_COMPLETE.
2706 if (pfn_notify == nullptr ||
2707 (command_exec_callback_type != CL_SUBMITTED && command_exec_callback_type != CL_RUNNING &&
2708 command_exec_callback_type != CL_COMPLETE))
2709 {
2710 return CL_INVALID_VALUE;
2711 }
2712
2713 return CL_SUCCESS;
2714 }
2715
ValidateEnqueueReadBufferRect(cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_read,const size_t * buffer_origin,const size_t * host_origin,const size_t * region,size_t buffer_row_pitch,size_t buffer_slice_pitch,size_t host_row_pitch,size_t host_slice_pitch,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2716 cl_int ValidateEnqueueReadBufferRect(cl_command_queue command_queue,
2717 cl_mem buffer,
2718 cl_bool blocking_read,
2719 const size_t *buffer_origin,
2720 const size_t *host_origin,
2721 const size_t *region,
2722 size_t buffer_row_pitch,
2723 size_t buffer_slice_pitch,
2724 size_t host_row_pitch,
2725 size_t host_slice_pitch,
2726 const void *ptr,
2727 cl_uint num_events_in_wait_list,
2728 const cl_event *event_wait_list,
2729 const cl_event *event)
2730 {
2731 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2732 num_events_in_wait_list, event_wait_list));
2733 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2734 if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u))
2735 {
2736 return CL_INVALID_COMMAND_QUEUE;
2737 }
2738
2739 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, buffer, true, false));
2740 ANGLE_VALIDATE(ValidateBufferRect(buffer->cast<Buffer>(), buffer_origin, region,
2741 buffer_row_pitch, buffer_slice_pitch));
2742 ANGLE_VALIDATE(ValidateHostRect(host_origin, region, host_row_pitch, host_slice_pitch, ptr));
2743
2744 return CL_SUCCESS;
2745 }
2746
ValidateEnqueueWriteBufferRect(cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_write,const size_t * buffer_origin,const size_t * host_origin,const size_t * region,size_t buffer_row_pitch,size_t buffer_slice_pitch,size_t host_row_pitch,size_t host_slice_pitch,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2747 cl_int ValidateEnqueueWriteBufferRect(cl_command_queue command_queue,
2748 cl_mem buffer,
2749 cl_bool blocking_write,
2750 const size_t *buffer_origin,
2751 const size_t *host_origin,
2752 const size_t *region,
2753 size_t buffer_row_pitch,
2754 size_t buffer_slice_pitch,
2755 size_t host_row_pitch,
2756 size_t host_slice_pitch,
2757 const void *ptr,
2758 cl_uint num_events_in_wait_list,
2759 const cl_event *event_wait_list,
2760 const cl_event *event)
2761 {
2762 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2763 num_events_in_wait_list, event_wait_list));
2764 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2765 if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u))
2766 {
2767 return CL_INVALID_COMMAND_QUEUE;
2768 }
2769
2770 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, buffer, false, true));
2771 ANGLE_VALIDATE(ValidateBufferRect(buffer->cast<Buffer>(), buffer_origin, region,
2772 buffer_row_pitch, buffer_slice_pitch));
2773 ANGLE_VALIDATE(ValidateHostRect(host_origin, region, host_row_pitch, host_slice_pitch, ptr));
2774
2775 return CL_SUCCESS;
2776 }
2777
ValidateEnqueueCopyBufferRect(cl_command_queue command_queue,cl_mem src_buffer,cl_mem dst_buffer,const size_t * src_origin,const size_t * dst_origin,const size_t * region,size_t src_row_pitch,size_t src_slice_pitch,size_t dst_row_pitch,size_t dst_slice_pitch,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)2778 cl_int ValidateEnqueueCopyBufferRect(cl_command_queue command_queue,
2779 cl_mem src_buffer,
2780 cl_mem dst_buffer,
2781 const size_t *src_origin,
2782 const size_t *dst_origin,
2783 const size_t *region,
2784 size_t src_row_pitch,
2785 size_t src_slice_pitch,
2786 size_t dst_row_pitch,
2787 size_t dst_slice_pitch,
2788 cl_uint num_events_in_wait_list,
2789 const cl_event *event_wait_list,
2790 const cl_event *event)
2791 {
2792 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
2793 num_events_in_wait_list, event_wait_list));
2794 const CommandQueue &queue = command_queue->cast<CommandQueue>();
2795 if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u))
2796 {
2797 return CL_INVALID_COMMAND_QUEUE;
2798 }
2799
2800 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, src_buffer, false, false));
2801 const Buffer &src = src_buffer->cast<Buffer>();
2802
2803 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, dst_buffer, false, false));
2804 const Buffer &dst = dst_buffer->cast<Buffer>();
2805
2806 ANGLE_VALIDATE(ValidateBufferRect(src, src_origin, region, src_row_pitch, src_slice_pitch));
2807 ANGLE_VALIDATE(ValidateBufferRect(dst, dst_origin, region, dst_row_pitch, dst_slice_pitch));
2808
2809 // CL_INVALID_VALUE if src_buffer and dst_buffer are the same buffer object and src_slice_pitch
2810 // is not equal to dst_slice_pitch or src_row_pitch is not equal to dst_row_pitch.
2811 if (&src == &dst && (src_slice_pitch != dst_slice_pitch || src_row_pitch != dst_row_pitch))
2812 {
2813 return CL_INVALID_VALUE;
2814 }
2815
2816 return CL_SUCCESS;
2817 }
2818
2819 // CL 1.2
ValidateCreateSubDevices(cl_device_id in_device,const cl_device_partition_property * properties,cl_uint num_devices,const cl_device_id * out_devices,const cl_uint * num_devices_ret)2820 cl_int ValidateCreateSubDevices(cl_device_id in_device,
2821 const cl_device_partition_property *properties,
2822 cl_uint num_devices,
2823 const cl_device_id *out_devices,
2824 const cl_uint *num_devices_ret)
2825 {
2826 // CL_INVALID_DEVICE if in_device is not a valid device.
2827 if (!Device::IsValid(in_device))
2828 {
2829 return CL_INVALID_DEVICE;
2830 }
2831 const Device &device = in_device->cast<Device>();
2832 if (!device.isVersionOrNewer(1u, 2u))
2833 {
2834 return CL_INVALID_DEVICE;
2835 }
2836
2837 // CL_INVALID_VALUE if values specified in properties are not valid
2838 // or if values specified in properties are valid but not supported by the device
2839 const std::vector<cl_device_partition_property> &devProps =
2840 device.getInfo().partitionProperties;
2841 if (properties == nullptr ||
2842 std::find(devProps.cbegin(), devProps.cend(), *properties) == devProps.cend())
2843 {
2844 return CL_INVALID_VALUE;
2845 }
2846
2847 return CL_SUCCESS;
2848 }
2849
ValidateRetainDevice(cl_device_id device)2850 cl_int ValidateRetainDevice(cl_device_id device)
2851 {
2852 // CL_INVALID_DEVICE if device is not a valid device.
2853 if (!Device::IsValid(device) || !device->cast<Device>().isVersionOrNewer(1u, 2u))
2854 {
2855 return CL_INVALID_DEVICE;
2856 }
2857 return CL_SUCCESS;
2858 }
2859
ValidateReleaseDevice(cl_device_id device)2860 cl_int ValidateReleaseDevice(cl_device_id device)
2861 {
2862 // CL_INVALID_DEVICE if device is not a valid device.
2863 if (!Device::IsValid(device) || !device->cast<Device>().isVersionOrNewer(1u, 2u))
2864 {
2865 return CL_INVALID_DEVICE;
2866 }
2867 return CL_SUCCESS;
2868 }
2869
ValidateCreateImage(cl_context context,MemFlags flags,const cl_image_format * image_format,const cl_image_desc * image_desc,const void * host_ptr)2870 cl_int ValidateCreateImage(cl_context context,
2871 MemFlags flags,
2872 const cl_image_format *image_format,
2873 const cl_image_desc *image_desc,
2874 const void *host_ptr)
2875 {
2876 // CL_INVALID_CONTEXT if context is not a valid context.
2877 if (!Context::IsValidAndVersionOrNewer(context, 1u, 2u))
2878 {
2879 return CL_INVALID_CONTEXT;
2880 }
2881 const Context &ctx = context->cast<Context>();
2882
2883 // CL_INVALID_VALUE if values specified in flags are not valid.
2884 if (!ValidateMemoryFlags(flags, ctx.getPlatform()))
2885 {
2886 return CL_INVALID_VALUE;
2887 }
2888
2889 // CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if values specified in image_format are not valid
2890 // or if image_format is NULL.
2891 if (!IsValidImageFormat(image_format, ctx.getPlatform().getInfo()))
2892 {
2893 return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
2894 }
2895
2896 // CL_INVALID_IMAGE_DESCRIPTOR if image_desc is NULL.
2897 if (image_desc == nullptr)
2898 {
2899 return CL_INVALID_IMAGE_DESCRIPTOR;
2900 }
2901
2902 const size_t elemSize = GetElementSize(*image_format);
2903 if (elemSize == 0u)
2904 {
2905 ASSERT(false);
2906 ERR() << "Failed to calculate image element size";
2907 return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
2908 }
2909 const size_t rowPitch = image_desc->image_row_pitch != 0u ? image_desc->image_row_pitch
2910 : image_desc->image_width * elemSize;
2911 const size_t imageHeight =
2912 image_desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY ? 1u : image_desc->image_height;
2913 const size_t sliceSize = imageHeight * rowPitch;
2914
2915 // CL_INVALID_IMAGE_DESCRIPTOR if values specified in image_desc are not valid.
2916 switch (FromCLenum<MemObjectType>(image_desc->image_type))
2917 {
2918 case MemObjectType::Image1D:
2919 if (image_desc->image_width == 0u)
2920 {
2921 return CL_INVALID_IMAGE_DESCRIPTOR;
2922 }
2923 break;
2924 case MemObjectType::Image2D:
2925 if (image_desc->image_width == 0u || image_desc->image_height == 0u)
2926 {
2927 return CL_INVALID_IMAGE_DESCRIPTOR;
2928 }
2929 break;
2930 case MemObjectType::Image3D:
2931 if (image_desc->image_width == 0u || image_desc->image_height == 0u ||
2932 image_desc->image_depth == 0u)
2933 {
2934 return CL_INVALID_IMAGE_DESCRIPTOR;
2935 }
2936 break;
2937 case MemObjectType::Image1D_Array:
2938 if (image_desc->image_width == 0u || image_desc->image_array_size == 0u)
2939 {
2940 return CL_INVALID_IMAGE_DESCRIPTOR;
2941 }
2942 break;
2943 case MemObjectType::Image2D_Array:
2944 if (image_desc->image_width == 0u || image_desc->image_height == 0u ||
2945 image_desc->image_array_size == 0u)
2946 {
2947 return CL_INVALID_IMAGE_DESCRIPTOR;
2948 }
2949 break;
2950 case MemObjectType::Image1D_Buffer:
2951 if (image_desc->image_width == 0u)
2952 {
2953 return CL_INVALID_IMAGE_DESCRIPTOR;
2954 }
2955 break;
2956 default:
2957 return CL_INVALID_IMAGE_DESCRIPTOR;
2958 }
2959 if (image_desc->image_row_pitch != 0u)
2960 {
2961 // image_row_pitch must be 0 if host_ptr is NULL.
2962 if (host_ptr == nullptr)
2963 {
2964 return CL_INVALID_IMAGE_DESCRIPTOR;
2965 }
2966 // image_row_pitch can be either 0
2967 // or >= image_width * size of element in bytes if host_ptr is not NULL.
2968 if (image_desc->image_row_pitch < image_desc->image_width * elemSize)
2969 {
2970 return CL_INVALID_IMAGE_DESCRIPTOR;
2971 }
2972 // If image_row_pitch is not 0, it must be a multiple of the image element size in bytes.
2973 if ((image_desc->image_row_pitch % elemSize) != 0u)
2974 {
2975 return CL_INVALID_IMAGE_DESCRIPTOR;
2976 }
2977 }
2978 if (image_desc->image_slice_pitch != 0u)
2979 {
2980 // image_slice_pitch must be 0 if host_ptr is NULL.
2981 if (host_ptr == nullptr)
2982 {
2983 return CL_INVALID_IMAGE_DESCRIPTOR;
2984 }
2985 // If host_ptr is not NULL, image_slice_pitch can be either 0
2986 // or >= image_row_pitch * image_height for a 2D image array or 3D image
2987 // and can be either 0 or >= image_row_pitch for a 1D image array.
2988 if (image_desc->image_slice_pitch < sliceSize)
2989 {
2990 return CL_INVALID_IMAGE_DESCRIPTOR;
2991 }
2992 // If image_slice_pitch is not 0, it must be a multiple of the image_row_pitch.
2993 if ((image_desc->image_slice_pitch % rowPitch) != 0u)
2994 {
2995 return CL_INVALID_IMAGE_DESCRIPTOR;
2996 }
2997 }
2998 // num_mip_levels and num_samples must be 0.
2999 if (image_desc->num_mip_levels != 0u || image_desc->num_samples != 0u)
3000 {
3001 return CL_INVALID_IMAGE_DESCRIPTOR;
3002 }
3003 // buffer can be a buffer memory object if image_type is CL_MEM_OBJECT_IMAGE1D_BUFFER or
3004 // CL_MEM_OBJECT_IMAGE2D. buffer can be an image object if image_type is CL_MEM_OBJECT_IMAGE2D.
3005 // Otherwise it must be NULL.
3006 if (image_desc->buffer != nullptr &&
3007 (!Buffer::IsValid(image_desc->buffer) ||
3008 (image_desc->image_type != CL_MEM_OBJECT_IMAGE1D_BUFFER &&
3009 image_desc->image_type != CL_MEM_OBJECT_IMAGE2D)) &&
3010 (!Image::IsValid(image_desc->buffer) || image_desc->image_type != CL_MEM_OBJECT_IMAGE2D))
3011 {
3012 return CL_INVALID_IMAGE_DESCRIPTOR;
3013 }
3014
3015 // CL_INVALID_OPERATION if there are no devices in context that support images.
3016 if (!ctx.supportsImages())
3017 {
3018 return CL_INVALID_OPERATION;
3019 }
3020
3021 // CL_INVALID_IMAGE_SIZE if image dimensions specified in image_desc exceed the maximum
3022 // image dimensions described in the Device Queries table for all devices in context.
3023 const DevicePtrs &devices = ctx.getDevices();
3024 if (std::find_if(devices.cbegin(), devices.cend(), [&](const DevicePtr &ptr) {
3025 return ptr->supportsNativeImageDimensions(*image_desc);
3026 }) == devices.cend())
3027 {
3028 return CL_INVALID_IMAGE_SIZE;
3029 }
3030
3031 // CL_INVALID_HOST_PTR
3032 // if host_ptr is NULL and CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR are set in flags or
3033 // if host_ptr is not NULL but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in flags.
3034 if ((host_ptr != nullptr) != flags.isSet(CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))
3035 {
3036 return CL_INVALID_HOST_PTR;
3037 }
3038
3039 return CL_SUCCESS;
3040 }
3041
ValidateCreateProgramWithBuiltInKernels(cl_context context,cl_uint num_devices,const cl_device_id * device_list,const char * kernel_names)3042 cl_int ValidateCreateProgramWithBuiltInKernels(cl_context context,
3043 cl_uint num_devices,
3044 const cl_device_id *device_list,
3045 const char *kernel_names)
3046 {
3047 // CL_INVALID_CONTEXT if context is not a valid context.
3048 if (!Context::IsValidAndVersionOrNewer(context, 1u, 2u))
3049 {
3050 return CL_INVALID_CONTEXT;
3051 }
3052 const Context &ctx = context->cast<Context>();
3053
3054 // CL_INVALID_VALUE if device_list is NULL or num_devices is zero or if kernel_names is NULL.
3055 if (device_list == nullptr || num_devices == 0u || kernel_names == nullptr)
3056 {
3057 return CL_INVALID_VALUE;
3058 }
3059
3060 // CL_INVALID_DEVICE if any device in device_list
3061 // is not in the list of devices associated with context.
3062 for (size_t index = 0u; index < num_devices; ++index)
3063 {
3064 if (!ctx.hasDevice(device_list[index]))
3065 {
3066 return CL_INVALID_DEVICE;
3067 }
3068 }
3069
3070 // CL_INVALID_VALUE if kernel_names contains a kernel name
3071 // that is not supported by any of the devices in device_list.
3072 const char *start = kernel_names;
3073 do
3074 {
3075 const char *end = start;
3076 while (*end != '\0' && *end != ';')
3077 {
3078 ++end;
3079 }
3080 const size_t length = end - start;
3081 if (length != 0u && !ctx.supportsBuiltInKernel(std::string(start, length)))
3082 {
3083 return CL_INVALID_VALUE;
3084 }
3085 start = end;
3086 } while (*start++ != '\0');
3087
3088 return CL_SUCCESS;
3089 }
3090
ValidateCompileProgram(cl_program program,cl_uint num_devices,const cl_device_id * device_list,const char * options,cl_uint num_input_headers,const cl_program * input_headers,const char ** header_include_names,void (CL_CALLBACK * pfn_notify)(cl_program program,void * user_data),const void * user_data)3091 cl_int ValidateCompileProgram(cl_program program,
3092 cl_uint num_devices,
3093 const cl_device_id *device_list,
3094 const char *options,
3095 cl_uint num_input_headers,
3096 const cl_program *input_headers,
3097 const char **header_include_names,
3098 void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
3099 const void *user_data)
3100 {
3101 // CL_INVALID_PROGRAM if program is not a valid program object.
3102 if (!Program::IsValid(program))
3103 {
3104 return CL_INVALID_PROGRAM;
3105 }
3106 const Program &prog = program->cast<Program>();
3107 if (!prog.getContext().getPlatform().isVersionOrNewer(1u, 2u))
3108 {
3109 return CL_INVALID_PROGRAM;
3110 }
3111
3112 // CL_INVALID_OPERATION if we do not have source code.
3113 if (prog.getSource().empty())
3114 {
3115 ERR() << "No OpenCL C source available from program object (" << &prog << ")!";
3116 return CL_INVALID_OPERATION;
3117 }
3118
3119 // CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero,
3120 // or if device_list is not NULL and num_devices is zero.
3121 if ((device_list != nullptr) != (num_devices != 0u))
3122 {
3123 return CL_INVALID_VALUE;
3124 }
3125
3126 // CL_INVALID_DEVICE if any device in device_list
3127 // is not in the list of devices associated with program.
3128 while (num_devices-- != 0u)
3129 {
3130 if (!prog.hasDevice(*device_list++))
3131 {
3132 return CL_INVALID_DEVICE;
3133 }
3134 }
3135
3136 // CL_INVALID_VALUE if num_input_headers is zero and header_include_names
3137 // or input_headers are not NULL
3138 // or if num_input_headers is not zero and header_include_names or input_headers are NULL.
3139 if ((num_input_headers != 0u) != (header_include_names != nullptr) ||
3140 (num_input_headers != 0u) != (input_headers != nullptr))
3141 {
3142 return CL_INVALID_VALUE;
3143 }
3144
3145 // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
3146 if (pfn_notify == nullptr && user_data != nullptr)
3147 {
3148 return CL_INVALID_VALUE;
3149 }
3150
3151 // CL_INVALID_OPERATION if the build of a program executable for any of the devices listed
3152 // in device_list by a previous call to clBuildProgram for program has not completed.
3153 if (prog.isBuilding())
3154 {
3155 return CL_INVALID_OPERATION;
3156 }
3157
3158 // CL_INVALID_OPERATION if there are kernel objects attached to program.
3159 if (prog.hasAttachedKernels())
3160 {
3161 return CL_INVALID_OPERATION;
3162 }
3163
3164 return CL_SUCCESS;
3165 }
3166
ValidateLinkProgram(cl_context context,cl_uint num_devices,const cl_device_id * device_list,const char * options,cl_uint num_input_programs,const cl_program * input_programs,void (CL_CALLBACK * pfn_notify)(cl_program program,void * user_data),const void * user_data)3167 cl_int ValidateLinkProgram(cl_context context,
3168 cl_uint num_devices,
3169 const cl_device_id *device_list,
3170 const char *options,
3171 cl_uint num_input_programs,
3172 const cl_program *input_programs,
3173 void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
3174 const void *user_data)
3175 {
3176 // CL_INVALID_CONTEXT if context is not a valid context.
3177 if (!Context::IsValidAndVersionOrNewer(context, 1u, 2u))
3178 {
3179 return CL_INVALID_CONTEXT;
3180 }
3181 const Context &ctx = context->cast<Context>();
3182
3183 // CL_INVALID_OPERATION if the compilation or build of a program executable for any of the
3184 // devices listed in device_list by a previous call to clCompileProgram or clBuildProgram for
3185 // program has not completed.
3186 for (size_t i = 0; i < num_devices; ++i)
3187 {
3188 Device &device = device_list[i]->cast<Device>();
3189 for (size_t j = 0; j < num_input_programs; ++j)
3190 {
3191 cl_build_status buildStatus = CL_BUILD_NONE;
3192 Program &program = input_programs[j]->cast<Program>();
3193 if (IsError(program.getBuildInfo(device.getNative(), ProgramBuildInfo::Status,
3194 sizeof(cl_build_status), &buildStatus, nullptr)))
3195 {
3196 return CL_INVALID_PROGRAM;
3197 }
3198
3199 if (buildStatus != CL_BUILD_SUCCESS)
3200 {
3201 return CL_INVALID_OPERATION;
3202 }
3203 }
3204 }
3205
3206 // CL_INVALID_OPERATION if the rules for devices containing compiled binaries or libraries as
3207 // described in input_programs argument below are not followed.
3208 //
3209 // All programs specified by input_programs contain a compiled binary or library for the device.
3210 // In this case, a link is performed to generate a program executable for this device.
3211 //
3212 // None of the programs contain a compiled binary or library for that device. In this case, no
3213 // link is performed and there will be no program executable generated for this device.
3214 //
3215 // All other cases will return a CL_INVALID_OPERATION error.
3216 BitField libraryOrObject(CL_PROGRAM_BINARY_TYPE_LIBRARY |
3217 CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT);
3218 for (size_t i = 0; i < num_devices; ++i)
3219 {
3220 bool foundAnyLibraryOrObject = false;
3221 Device &device = device_list[i]->cast<Device>();
3222 for (size_t j = 0; j < num_input_programs; ++j)
3223 {
3224 cl_program_binary_type binaryType = CL_PROGRAM_BINARY_TYPE_NONE;
3225 Program &program = input_programs[j]->cast<Program>();
3226 if (IsError(program.getBuildInfo(device.getNative(), ProgramBuildInfo::BinaryType,
3227 sizeof(cl_program_binary_type), &binaryType, nullptr)))
3228 {
3229 return CL_INVALID_PROGRAM;
3230 }
3231
3232 if (libraryOrObject.isNotSet(binaryType))
3233 {
3234 if (foundAnyLibraryOrObject)
3235 {
3236 return CL_INVALID_OPERATION;
3237 }
3238 }
3239 else
3240 {
3241 foundAnyLibraryOrObject = true;
3242 }
3243 }
3244 }
3245
3246 // CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero,
3247 // or if device_list is not NULL and num_devices is zero.
3248 if ((device_list != nullptr) != (num_devices != 0u))
3249 {
3250 return CL_INVALID_VALUE;
3251 }
3252
3253 // CL_INVALID_DEVICE if any device in device_list
3254 // is not in the list of devices associated with context.
3255 while (num_devices-- != 0u)
3256 {
3257 if (!ctx.hasDevice(*device_list++))
3258 {
3259 return CL_INVALID_DEVICE;
3260 }
3261 }
3262
3263 // CL_INVALID_VALUE if num_input_programs is zero or input_programs is NULL.
3264 if (num_input_programs == 0u || input_programs == nullptr)
3265 {
3266 return CL_INVALID_VALUE;
3267 }
3268
3269 // CL_INVALID_PROGRAM if programs specified in input_programs are not valid program objects.
3270 while (num_input_programs-- != 0u)
3271 {
3272 if (!Program::IsValid(*input_programs++))
3273 {
3274 return CL_INVALID_PROGRAM;
3275 }
3276 }
3277
3278 // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
3279 if (pfn_notify == nullptr && user_data != nullptr)
3280 {
3281 return CL_INVALID_VALUE;
3282 }
3283
3284 return CL_SUCCESS;
3285 }
3286
ValidateUnloadPlatformCompiler(cl_platform_id platform)3287 cl_int ValidateUnloadPlatformCompiler(cl_platform_id platform)
3288 {
3289 // CL_INVALID_PLATFORM if platform is not a valid platform.
3290 if (!Platform::IsValid(platform) || !platform->cast<Platform>().isVersionOrNewer(1u, 2u))
3291 {
3292 return CL_INVALID_PLATFORM;
3293 }
3294 return CL_SUCCESS;
3295 }
3296
ValidateGetKernelArgInfo(cl_kernel kernel,cl_uint arg_index,KernelArgInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)3297 cl_int ValidateGetKernelArgInfo(cl_kernel kernel,
3298 cl_uint arg_index,
3299 KernelArgInfo param_name,
3300 size_t param_value_size,
3301 const void *param_value,
3302 const size_t *param_value_size_ret)
3303 {
3304 // CL_INVALID_KERNEL if kernel is a not a valid kernel object.
3305 if (!Kernel::IsValid(kernel))
3306 {
3307 return CL_INVALID_KERNEL;
3308 }
3309 const Kernel &krnl = kernel->cast<Kernel>();
3310 if (!krnl.getProgram().getContext().getPlatform().isVersionOrNewer(1u, 2u))
3311 {
3312 return CL_INVALID_KERNEL;
3313 }
3314
3315 // CL_INVALID_ARG_INDEX if arg_index is not a valid argument index.
3316 if (arg_index >= krnl.getInfo().args.size())
3317 {
3318 return CL_INVALID_ARG_INDEX;
3319 }
3320
3321 // CL_KERNEL_ARG_INFO_NOT_AVAILABLE if the argument information is not available for kernel.
3322 if (!krnl.getInfo().args[arg_index].isAvailable())
3323 {
3324 return CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
3325 }
3326
3327 // CL_INVALID_VALUE if param_name is not valid.
3328 if (param_name == KernelArgInfo::InvalidEnum)
3329 {
3330 return CL_INVALID_VALUE;
3331 }
3332
3333 return CL_SUCCESS;
3334 }
3335
ValidateEnqueueFillBuffer(cl_command_queue command_queue,cl_mem buffer,const void * pattern,size_t pattern_size,size_t offset,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3336 cl_int ValidateEnqueueFillBuffer(cl_command_queue command_queue,
3337 cl_mem buffer,
3338 const void *pattern,
3339 size_t pattern_size,
3340 size_t offset,
3341 size_t size,
3342 cl_uint num_events_in_wait_list,
3343 const cl_event *event_wait_list,
3344 const cl_event *event)
3345 {
3346 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
3347 num_events_in_wait_list, event_wait_list));
3348 const CommandQueue &queue = command_queue->cast<CommandQueue>();
3349 if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 2u))
3350 {
3351 return CL_INVALID_COMMAND_QUEUE;
3352 }
3353
3354 ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, buffer, false, false));
3355
3356 // CL_INVALID_VALUE if offset or offset + size require accessing
3357 // elements outside the buffer object respectively.
3358 if (!buffer->cast<Buffer>().isRegionValid(offset, size))
3359 {
3360 return CL_INVALID_VALUE;
3361 }
3362
3363 // CL_INVALID_VALUE if pattern is NULL or if pattern_size is 0 or
3364 // if pattern_size is not one of { 1, 2, 4, 8, 16, 32, 64, 128 }.
3365 if (pattern == nullptr || pattern_size == 0u || pattern_size > 128u ||
3366 (pattern_size & (pattern_size - 1u)) != 0u)
3367 {
3368 return CL_INVALID_VALUE;
3369 }
3370
3371 // CL_INVALID_VALUE if offset and size are not a multiple of pattern_size.
3372 if ((offset % pattern_size) != 0u || (size % pattern_size) != 0u)
3373 {
3374 return CL_INVALID_VALUE;
3375 }
3376
3377 return CL_SUCCESS;
3378 }
3379
ValidateEnqueueFillImage(cl_command_queue command_queue,cl_mem image,const void * fill_color,const size_t * origin,const size_t * region,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3380 cl_int ValidateEnqueueFillImage(cl_command_queue command_queue,
3381 cl_mem image,
3382 const void *fill_color,
3383 const size_t *origin,
3384 const size_t *region,
3385 cl_uint num_events_in_wait_list,
3386 const cl_event *event_wait_list,
3387 const cl_event *event)
3388 {
3389 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
3390 num_events_in_wait_list, event_wait_list));
3391 const CommandQueue &queue = command_queue->cast<CommandQueue>();
3392 if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 2u))
3393 {
3394 return CL_INVALID_COMMAND_QUEUE;
3395 }
3396
3397 ANGLE_VALIDATE(ValidateEnqueueImage(queue, image, false, false));
3398 const Image &img = image->cast<Image>();
3399
3400 ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));
3401
3402 // CL_INVALID_VALUE if fill_color is NULL.
3403 if (fill_color == nullptr)
3404 {
3405 return CL_INVALID_VALUE;
3406 }
3407
3408 return CL_SUCCESS;
3409 }
3410
ValidateEnqueueMigrateMemObjects(cl_command_queue command_queue,cl_uint num_mem_objects,const cl_mem * mem_objects,MemMigrationFlags flags,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3411 cl_int ValidateEnqueueMigrateMemObjects(cl_command_queue command_queue,
3412 cl_uint num_mem_objects,
3413 const cl_mem *mem_objects,
3414 MemMigrationFlags flags,
3415 cl_uint num_events_in_wait_list,
3416 const cl_event *event_wait_list,
3417 const cl_event *event)
3418 {
3419 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
3420 num_events_in_wait_list, event_wait_list));
3421 const CommandQueue &queue = command_queue->cast<CommandQueue>();
3422 if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 2u))
3423 {
3424 return CL_INVALID_COMMAND_QUEUE;
3425 }
3426
3427 // CL_INVALID_VALUE if num_mem_objects is zero or if mem_objects is NULL.
3428 if (num_mem_objects == 0u || mem_objects == nullptr)
3429 {
3430 return CL_INVALID_VALUE;
3431 }
3432
3433 while (num_mem_objects-- != 0u)
3434 {
3435 // CL_INVALID_MEM_OBJECT if any of the memory objects
3436 // in mem_objects is not a valid memory object.
3437 if (!Memory::IsValid(*mem_objects))
3438 {
3439 return CL_INVALID_MEM_OBJECT;
3440 }
3441
3442 // CL_INVALID_CONTEXT if the context associated with command_queue
3443 // and memory objects in mem_objects are not the same.
3444 if (&queue.getContext() != &(*mem_objects++)->cast<Memory>().getContext())
3445 {
3446 return CL_INVALID_CONTEXT;
3447 }
3448 }
3449
3450 // CL_INVALID_VALUE if flags is not 0 or is not any of the values described in the table.
3451 const MemMigrationFlags allowedFlags(CL_MIGRATE_MEM_OBJECT_HOST |
3452 CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED);
3453 if (flags.hasOtherBitsThan(allowedFlags))
3454 {
3455 return CL_INVALID_VALUE;
3456 }
3457
3458 return CL_SUCCESS;
3459 }
3460
ValidateEnqueueMarkerWithWaitList(cl_command_queue command_queue,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3461 cl_int ValidateEnqueueMarkerWithWaitList(cl_command_queue command_queue,
3462 cl_uint num_events_in_wait_list,
3463 const cl_event *event_wait_list,
3464 const cl_event *event)
3465 {
3466 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
3467 num_events_in_wait_list, event_wait_list));
3468 if (!command_queue->cast<CommandQueue>().getContext().getPlatform().isVersionOrNewer(1u, 2u))
3469 {
3470 return CL_INVALID_COMMAND_QUEUE;
3471 }
3472 return CL_SUCCESS;
3473 }
3474
ValidateEnqueueBarrierWithWaitList(cl_command_queue command_queue,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3475 cl_int ValidateEnqueueBarrierWithWaitList(cl_command_queue command_queue,
3476 cl_uint num_events_in_wait_list,
3477 const cl_event *event_wait_list,
3478 const cl_event *event)
3479 {
3480 ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
3481 num_events_in_wait_list, event_wait_list));
3482 if (!command_queue->cast<CommandQueue>().getContext().getPlatform().isVersionOrNewer(1u, 2u))
3483 {
3484 return CL_INVALID_COMMAND_QUEUE;
3485 }
3486 return CL_SUCCESS;
3487 }
3488
ValidateGetExtensionFunctionAddressForPlatform(cl_platform_id platform,const char * func_name)3489 cl_int ValidateGetExtensionFunctionAddressForPlatform(cl_platform_id platform,
3490 const char *func_name)
3491 {
3492 if (!Platform::IsValid(platform) || func_name == nullptr || *func_name == '\0')
3493 {
3494 return CL_INVALID_VALUE;
3495 }
3496 return CL_SUCCESS;
3497 }
3498
3499 // CL 2.0
ValidateCreateCommandQueueWithProperties(cl_context context,cl_device_id device,const cl_queue_properties * properties)3500 cl_int ValidateCreateCommandQueueWithProperties(cl_context context,
3501 cl_device_id device,
3502 const cl_queue_properties *properties)
3503 {
3504 // CL_INVALID_CONTEXT if context is not a valid context.
3505 if (!Context::IsValidAndVersionOrNewer(context, 2u, 0u))
3506 {
3507 return CL_INVALID_CONTEXT;
3508 }
3509
3510 // CL_INVALID_DEVICE if device is not a valid device or is not associated with context.
3511 if (!context->cast<Context>().hasDevice(device) ||
3512 !device->cast<Device>().isVersionOrNewer(2u, 0u))
3513 {
3514 return CL_INVALID_DEVICE;
3515 }
3516
3517 // CL_INVALID_VALUE if values specified in properties are not valid.
3518 if (properties != nullptr)
3519 {
3520 bool isQueueOnDevice = false;
3521 bool hasQueueSize = false;
3522 while (*properties != 0)
3523 {
3524 switch (*properties++)
3525 {
3526 case CL_QUEUE_PROPERTIES:
3527 {
3528 const CommandQueueProperties props(*properties++);
3529 const CommandQueueProperties validProps(
3530 CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE |
3531 CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT);
3532 if (props.hasOtherBitsThan(validProps) ||
3533 // If CL_QUEUE_ON_DEVICE is set, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
3534 // must also be set.
3535 (props.isSet(CL_QUEUE_ON_DEVICE) &&
3536 !props.isSet(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)) ||
3537 // CL_QUEUE_ON_DEVICE_DEFAULT can only be used with CL_QUEUE_ON_DEVICE.
3538 (props.isSet(CL_QUEUE_ON_DEVICE_DEFAULT) &&
3539 !props.isSet(CL_QUEUE_ON_DEVICE)))
3540 {
3541 return CL_INVALID_VALUE;
3542 }
3543 isQueueOnDevice = props.isSet(CL_QUEUE_ON_DEVICE);
3544 break;
3545 }
3546 case CL_QUEUE_SIZE:
3547 {
3548 // CL_QUEUE_SIZE must be a value <= CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE.
3549 if (*properties++ > device->cast<Device>().getInfo().queueOnDeviceMaxSize)
3550 {
3551 return CL_INVALID_VALUE;
3552 }
3553 hasQueueSize = true;
3554 break;
3555 }
3556 default:
3557 return CL_INVALID_VALUE;
3558 }
3559 }
3560
3561 // CL_QUEUE_SIZE can only be specified if CL_QUEUE_ON_DEVICE is set in CL_QUEUE_PROPERTIES.
3562 if (hasQueueSize && !isQueueOnDevice)
3563 {
3564 return CL_INVALID_VALUE;
3565 }
3566 }
3567
3568 return CL_SUCCESS;
3569 }
3570
ValidateCreatePipe(cl_context context,MemFlags flags,cl_uint pipe_packet_size,cl_uint pipe_max_packets,const cl_pipe_properties * properties)3571 cl_int ValidateCreatePipe(cl_context context,
3572 MemFlags flags,
3573 cl_uint pipe_packet_size,
3574 cl_uint pipe_max_packets,
3575 const cl_pipe_properties *properties)
3576 {
3577 return CL_SUCCESS;
3578 }
3579
ValidateGetPipeInfo(cl_mem pipe,PipeInfo param_name,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)3580 cl_int ValidateGetPipeInfo(cl_mem pipe,
3581 PipeInfo param_name,
3582 size_t param_value_size,
3583 const void *param_value,
3584 const size_t *param_value_size_ret)
3585 {
3586 return CL_SUCCESS;
3587 }
3588
ValidateSVMAlloc(cl_context context,SVM_MemFlags flags,size_t size,cl_uint alignment)3589 cl_int ValidateSVMAlloc(cl_context context, SVM_MemFlags flags, size_t size, cl_uint alignment)
3590 {
3591 return CL_SUCCESS;
3592 }
3593
ValidateSVMFree(cl_context context,const void * svm_pointer)3594 cl_int ValidateSVMFree(cl_context context, const void *svm_pointer)
3595 {
3596 return CL_SUCCESS;
3597 }
3598
ValidateCreateSamplerWithProperties(cl_context context,const cl_sampler_properties * sampler_properties)3599 cl_int ValidateCreateSamplerWithProperties(cl_context context,
3600 const cl_sampler_properties *sampler_properties)
3601 {
3602 // CL_INVALID_CONTEXT if context is not a valid context.
3603 if (!Context::IsValidAndVersionOrNewer(context, 2u, 0u))
3604 {
3605 return CL_INVALID_CONTEXT;
3606 }
3607
3608 // CL_INVALID_VALUE if the property name in sampler_properties is not a supported property name,
3609 // if the value specified for a supported property name is not valid,
3610 // or if the same property name is specified more than once.
3611 if (sampler_properties != nullptr)
3612 {
3613 bool hasNormalizedCoords = false;
3614 bool hasAddressingMode = false;
3615 bool hasFilterMode = false;
3616 const cl_sampler_properties *propIt = sampler_properties;
3617 while (*propIt != 0)
3618 {
3619 switch (*propIt++)
3620 {
3621 case CL_SAMPLER_NORMALIZED_COORDS:
3622 if (hasNormalizedCoords || (*propIt != CL_FALSE && *propIt != CL_TRUE))
3623 {
3624 return CL_INVALID_VALUE;
3625 }
3626 hasNormalizedCoords = true;
3627 ++propIt;
3628 break;
3629 case CL_SAMPLER_ADDRESSING_MODE:
3630 if (hasAddressingMode || FromCLenum<AddressingMode>(static_cast<CLenum>(
3631 *propIt++)) == AddressingMode::InvalidEnum)
3632 {
3633 return CL_INVALID_VALUE;
3634 }
3635 hasAddressingMode = true;
3636 break;
3637 case CL_SAMPLER_FILTER_MODE:
3638 if (hasFilterMode || FromCLenum<FilterMode>(static_cast<CLenum>(*propIt++)) ==
3639 FilterMode::InvalidEnum)
3640 {
3641 return CL_INVALID_VALUE;
3642 }
3643 hasFilterMode = true;
3644 break;
3645 default:
3646 return CL_INVALID_VALUE;
3647 }
3648 }
3649 }
3650
3651 // CL_INVALID_OPERATION if images are not supported by any device associated with context.
3652 if (!context->cast<Context>().supportsImages())
3653 {
3654 return CL_INVALID_OPERATION;
3655 }
3656
3657 return CL_SUCCESS;
3658 }
3659
ValidateSetKernelArgSVMPointer(cl_kernel kernel,cl_uint arg_index,const void * arg_value)3660 cl_int ValidateSetKernelArgSVMPointer(cl_kernel kernel, cl_uint arg_index, const void *arg_value)
3661 {
3662 return CL_SUCCESS;
3663 }
3664
ValidateSetKernelExecInfo(cl_kernel kernel,KernelExecInfo param_name,size_t param_value_size,const void * param_value)3665 cl_int ValidateSetKernelExecInfo(cl_kernel kernel,
3666 KernelExecInfo param_name,
3667 size_t param_value_size,
3668 const void *param_value)
3669 {
3670 return CL_SUCCESS;
3671 }
3672
ValidateEnqueueSVMFree(cl_command_queue command_queue,cl_uint num_svm_pointers,void * const svm_pointers[],void (CL_CALLBACK * pfn_free_func)(cl_command_queue queue,cl_uint num_svm_pointers,void * svm_pointers[],void * user_data),const void * user_data,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3673 cl_int ValidateEnqueueSVMFree(cl_command_queue command_queue,
3674 cl_uint num_svm_pointers,
3675 void *const svm_pointers[],
3676 void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue,
3677 cl_uint num_svm_pointers,
3678 void *svm_pointers[],
3679 void *user_data),
3680 const void *user_data,
3681 cl_uint num_events_in_wait_list,
3682 const cl_event *event_wait_list,
3683 const cl_event *event)
3684 {
3685 return CL_SUCCESS;
3686 }
3687
ValidateEnqueueSVMMemcpy(cl_command_queue command_queue,cl_bool blocking_copy,const void * dst_ptr,const void * src_ptr,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3688 cl_int ValidateEnqueueSVMMemcpy(cl_command_queue command_queue,
3689 cl_bool blocking_copy,
3690 const void *dst_ptr,
3691 const void *src_ptr,
3692 size_t size,
3693 cl_uint num_events_in_wait_list,
3694 const cl_event *event_wait_list,
3695 const cl_event *event)
3696 {
3697 return CL_SUCCESS;
3698 }
3699
ValidateEnqueueSVMMemFill(cl_command_queue command_queue,const void * svm_ptr,const void * pattern,size_t pattern_size,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3700 cl_int ValidateEnqueueSVMMemFill(cl_command_queue command_queue,
3701 const void *svm_ptr,
3702 const void *pattern,
3703 size_t pattern_size,
3704 size_t size,
3705 cl_uint num_events_in_wait_list,
3706 const cl_event *event_wait_list,
3707 const cl_event *event)
3708 {
3709 return CL_SUCCESS;
3710 }
3711
ValidateEnqueueSVMMap(cl_command_queue command_queue,cl_bool blocking_map,MapFlags flags,const void * svm_ptr,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3712 cl_int ValidateEnqueueSVMMap(cl_command_queue command_queue,
3713 cl_bool blocking_map,
3714 MapFlags flags,
3715 const void *svm_ptr,
3716 size_t size,
3717 cl_uint num_events_in_wait_list,
3718 const cl_event *event_wait_list,
3719 const cl_event *event)
3720 {
3721 return CL_SUCCESS;
3722 }
3723
ValidateEnqueueSVMUnmap(cl_command_queue command_queue,const void * svm_ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3724 cl_int ValidateEnqueueSVMUnmap(cl_command_queue command_queue,
3725 const void *svm_ptr,
3726 cl_uint num_events_in_wait_list,
3727 const cl_event *event_wait_list,
3728 const cl_event *event)
3729 {
3730 return CL_SUCCESS;
3731 }
3732
3733 // CL 2.1
ValidateSetDefaultDeviceCommandQueue(cl_context context,cl_device_id device,cl_command_queue command_queue)3734 cl_int ValidateSetDefaultDeviceCommandQueue(cl_context context,
3735 cl_device_id device,
3736 cl_command_queue command_queue)
3737 {
3738 return CL_SUCCESS;
3739 }
3740
ValidateGetDeviceAndHostTimer(cl_device_id device,const cl_ulong * device_timestamp,const cl_ulong * host_timestamp)3741 cl_int ValidateGetDeviceAndHostTimer(cl_device_id device,
3742 const cl_ulong *device_timestamp,
3743 const cl_ulong *host_timestamp)
3744 {
3745 return CL_SUCCESS;
3746 }
3747
ValidateGetHostTimer(cl_device_id device,const cl_ulong * host_timestamp)3748 cl_int ValidateGetHostTimer(cl_device_id device, const cl_ulong *host_timestamp)
3749 {
3750 return CL_SUCCESS;
3751 }
3752
ValidateCreateProgramWithIL(cl_context context,const void * il,size_t length)3753 cl_int ValidateCreateProgramWithIL(cl_context context, const void *il, size_t length)
3754 {
3755 // CL_INVALID_CONTEXT if context is not a valid context.
3756 if (!Context::IsValidAndVersionOrNewer(context, 2u, 1u))
3757 {
3758 return CL_INVALID_CONTEXT;
3759 }
3760 const Context &ctx = context->cast<Context>();
3761
3762 // CL_INVALID_OPERATION if no devices in context support intermediate language programs.
3763 if (!ctx.supportsIL())
3764 {
3765 return CL_INVALID_OPERATION;
3766 }
3767
3768 // CL_INVALID_VALUE if il is NULL or if length is zero.
3769 if (il == nullptr || length == 0u)
3770 {
3771 return CL_INVALID_VALUE;
3772 }
3773
3774 return CL_SUCCESS;
3775 }
3776
ValidateCloneKernel(cl_kernel source_kernel)3777 cl_int ValidateCloneKernel(cl_kernel source_kernel)
3778 {
3779 return CL_SUCCESS;
3780 }
3781
ValidateGetKernelSubGroupInfo(cl_kernel kernel,cl_device_id device,KernelSubGroupInfo param_name,size_t input_value_size,const void * input_value,size_t param_value_size,const void * param_value,const size_t * param_value_size_ret)3782 cl_int ValidateGetKernelSubGroupInfo(cl_kernel kernel,
3783 cl_device_id device,
3784 KernelSubGroupInfo param_name,
3785 size_t input_value_size,
3786 const void *input_value,
3787 size_t param_value_size,
3788 const void *param_value,
3789 const size_t *param_value_size_ret)
3790 {
3791 return CL_SUCCESS;
3792 }
3793
ValidateEnqueueSVMMigrateMem(cl_command_queue command_queue,cl_uint num_svm_pointers,const void ** svm_pointers,const size_t * sizes,MemMigrationFlags flags,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,const cl_event * event)3794 cl_int ValidateEnqueueSVMMigrateMem(cl_command_queue command_queue,
3795 cl_uint num_svm_pointers,
3796 const void **svm_pointers,
3797 const size_t *sizes,
3798 MemMigrationFlags flags,
3799 cl_uint num_events_in_wait_list,
3800 const cl_event *event_wait_list,
3801 const cl_event *event)
3802 {
3803 return CL_SUCCESS;
3804 }
3805
3806 // CL 2.2
ValidateSetProgramReleaseCallback(cl_program program,void (CL_CALLBACK * pfn_notify)(cl_program program,void * user_data),const void * user_data)3807 cl_int ValidateSetProgramReleaseCallback(cl_program program,
3808 void(CL_CALLBACK *pfn_notify)(cl_program program,
3809 void *user_data),
3810 const void *user_data)
3811 {
3812 return CL_SUCCESS;
3813 }
3814
ValidateSetProgramSpecializationConstant(cl_program program,cl_uint spec_id,size_t spec_size,const void * spec_value)3815 cl_int ValidateSetProgramSpecializationConstant(cl_program program,
3816 cl_uint spec_id,
3817 size_t spec_size,
3818 const void *spec_value)
3819 {
3820 return CL_SUCCESS;
3821 }
3822
3823 // CL 3.0
ValidateSetContextDestructorCallback(cl_context context,void (CL_CALLBACK * pfn_notify)(cl_context context,void * user_data),const void * user_data)3824 cl_int ValidateSetContextDestructorCallback(cl_context context,
3825 void(CL_CALLBACK *pfn_notify)(cl_context context,
3826 void *user_data),
3827 const void *user_data)
3828 {
3829 return CL_SUCCESS;
3830 }
3831
ValidateCreateBufferWithProperties(cl_context context,const cl_mem_properties * properties,MemFlags flags,size_t size,const void * host_ptr)3832 cl_int ValidateCreateBufferWithProperties(cl_context context,
3833 const cl_mem_properties *properties,
3834 MemFlags flags,
3835 size_t size,
3836 const void *host_ptr)
3837 {
3838 ANGLE_VALIDATE(ValidateCreateBuffer(context, flags, size, host_ptr));
3839
3840 // CL_INVALID_CONTEXT if context is not a valid context.
3841 if (!context->cast<Context>().getPlatform().isVersionOrNewer(3u, 0u))
3842 {
3843 return CL_INVALID_CONTEXT;
3844 }
3845
3846 // CL_INVALID_PROPERTY if a property name in properties is not a supported property name,
3847 // if the value specified for a supported property name is not valid,
3848 // or if the same property name is specified more than once.
3849 if (!ValidateMemoryProperties(properties))
3850 {
3851 return CL_INVALID_PROPERTY;
3852 }
3853
3854 return CL_SUCCESS;
3855 }
3856
ValidateCreateImageWithProperties(cl_context context,const cl_mem_properties * properties,MemFlags flags,const cl_image_format * image_format,const cl_image_desc * image_desc,const void * host_ptr)3857 cl_int ValidateCreateImageWithProperties(cl_context context,
3858 const cl_mem_properties *properties,
3859 MemFlags flags,
3860 const cl_image_format *image_format,
3861 const cl_image_desc *image_desc,
3862 const void *host_ptr)
3863 {
3864 ANGLE_VALIDATE(ValidateCreateImage(context, flags, image_format, image_desc, host_ptr));
3865
3866 // CL_INVALID_CONTEXT if context is not a valid context.
3867 if (!context->cast<Context>().getPlatform().isVersionOrNewer(3u, 0u))
3868 {
3869 return CL_INVALID_CONTEXT;
3870 }
3871
3872 // CL_INVALID_PROPERTY if a property name in properties is not a supported property name,
3873 // if the value specified for a supported property name is not valid,
3874 // or if the same property name is specified more than once.
3875 if (!ValidateMemoryProperties(properties))
3876 {
3877 return CL_INVALID_PROPERTY;
3878 }
3879
3880 return CL_SUCCESS;
3881 }
3882
3883 // cl_khr_icd
ValidateIcdGetPlatformIDsKHR(cl_uint num_entries,const cl_platform_id * platforms,const cl_uint * num_platforms)3884 cl_int ValidateIcdGetPlatformIDsKHR(cl_uint num_entries,
3885 const cl_platform_id *platforms,
3886 const cl_uint *num_platforms)
3887 {
3888 if ((num_entries == 0u && platforms != nullptr) ||
3889 (platforms == nullptr && num_platforms == nullptr))
3890 {
3891 return CL_INVALID_VALUE;
3892 }
3893 return CL_SUCCESS;
3894 }
3895
3896 } // namespace cl
3897