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