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