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