//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// validationCL.cpp: Validation functions for generic CL entry point parameters
// based on the OpenCL Specification V3.0.7, see https://www.khronos.org/registry/OpenCL/
// Each used CL error code is preceeded by a citation of the relevant rule in the spec.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/cl_utils.h"
#include "libANGLE/validationCL_autogen.h"

#include "common/string_utils.h"

#define ANGLE_VALIDATE_VERSION(version, major, minor)          \
    do                                                         \
    {                                                          \
        if (version < CL_MAKE_VERSION(major##u, minor##u, 0u)) \
        {                                                      \
            return CL_INVALID_VALUE;                           \
        }                                                      \
    } while (0)

#define ANGLE_VALIDATE_EXTENSION(extension) \
    do                                      \
    {                                       \
        if (!extension)                     \
        {                                   \
            return CL_INVALID_VALUE;        \
        }                                   \
    } while (0)

#define ANGLE_VALIDATE(expression)            \
    do                                        \
    {                                         \
        const cl_int _errorCode = expression; \
        if (_errorCode != CL_SUCCESS)         \
        {                                     \
            return _errorCode;                \
        }                                     \
    } while (0)

#define ANGLE_VALIDATE_VERSION_OR_EXTENSION(version, major, minor, extension) \
    do                                                                        \
    {                                                                         \
        if (version < CL_MAKE_VERSION(major##u, minor##u, 0u))                \
        {                                                                     \
            ANGLE_VALIDATE_EXTENSION(extension);                              \
        }                                                                     \
    } while (0)

namespace cl
{

namespace
{

cl_int ValidateContextProperties(const cl_context_properties *properties, const Platform *&platform)
{
    platform         = nullptr;
    bool hasUserSync = false;
    if (properties != nullptr)
    {
        while (*properties != 0)
        {
            switch (*properties++)
            {
                case CL_CONTEXT_PLATFORM:
                {
                    // CL_INVALID_PROPERTY if the same property name is specified more than once.
                    if (platform != nullptr)
                    {
                        return CL_INVALID_PROPERTY;
                    }
                    cl_platform_id nativePlatform = reinterpret_cast<cl_platform_id>(*properties++);
                    // CL_INVALID_PLATFORM if platform value specified in properties
                    // is not a valid platform.
                    if (!Platform::IsValid(nativePlatform))
                    {
                        return CL_INVALID_PLATFORM;
                    }
                    platform = &nativePlatform->cast<Platform>();
                    break;
                }
                case CL_CONTEXT_INTEROP_USER_SYNC:
                {
                    // CL_INVALID_PROPERTY if the value specified for a supported property name
                    // is not valid, or if the same property name is specified more than once.
                    if ((*properties != CL_FALSE && *properties != CL_TRUE) || hasUserSync)
                    {
                        return CL_INVALID_PROPERTY;
                    }
                    ++properties;
                    hasUserSync = true;
                    break;
                }
                default:
                {
                    // CL_INVALID_PROPERTY if context property name in properties
                    // is not a supported property name.
                    return CL_INVALID_PROPERTY;
                }
            }
        }
    }
    return CL_SUCCESS;
}

bool ValidateMemoryFlags(MemFlags flags, const Platform &platform)
{
    // CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, and CL_MEM_READ_ONLY are mutually exclusive.
    MemFlags allowedFlags(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY);
    if (!flags.areMutuallyExclusive(CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY))
    {
        return false;
    }
    // CL_MEM_USE_HOST_PTR is mutually exclusive with either of the other two flags.
    allowedFlags.set(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR);
    if (!flags.areMutuallyExclusive(CL_MEM_USE_HOST_PTR,
                                    CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR))
    {
        return false;
    }
    if (platform.isVersionOrNewer(1u, 2u))
    {
        // CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY,
        // and CL_MEM_HOST_NO_ACCESS are mutually exclusive.
        allowedFlags.set(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS);
        if (!flags.areMutuallyExclusive(CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY,
                                        CL_MEM_HOST_NO_ACCESS))
        {
            return false;
        }
    }
    if (platform.isVersionOrNewer(2u, 0u))
    {
        allowedFlags.set(CL_MEM_KERNEL_READ_AND_WRITE);
    }
    if (flags.hasOtherBitsThan(allowedFlags))
    {
        return false;
    }
    return true;
}

bool ValidateMapFlags(MapFlags flags, const Platform &platform)
{
    MemFlags allowedFlags(CL_MAP_READ | CL_MAP_WRITE);
    if (platform.isVersionOrNewer(1u, 2u))
    {
        // CL_MAP_READ or CL_MAP_WRITE and CL_MAP_WRITE_INVALIDATE_REGION are mutually exclusive.
        allowedFlags.set(CL_MAP_WRITE_INVALIDATE_REGION);
        if (!flags.areMutuallyExclusive(CL_MAP_WRITE_INVALIDATE_REGION, CL_MAP_READ | CL_MAP_WRITE))
        {
            return false;
        }
    }
    if (flags.hasOtherBitsThan(allowedFlags))
    {
        return false;
    }
    return true;
}

cl_int ValidateMemoryProperties(cl_context context,
                                MemFlags flags,
                                const cl_mem_properties *properties,
                                const void *host_ptr)
{
    // first, get/validate supported properties
    const NameValueProperty *startOfProperties =
        reinterpret_cast<const NameValueProperty *>(properties);
    const NameValueProperty *propertiesIterator = startOfProperties;
    while (propertiesIterator->name != 0)
    {
        switch (propertiesIterator->name)
        {
            case CL_MEM_DEVICE_HANDLE_LIST_KHR:
            case CL_MEM_DEVICE_HANDLE_LIST_END_KHR:
            case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR:
            case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR:
                break;
            default:
                // CL_INVALID_PROPERTY if a property name in properties is not a supported property
                // name
                return CL_INVALID_PROPERTY;
        }
        propertiesIterator++;
    }

    // next, get/validate the memory type/handle from properties (that we support)
    const NameValueProperty *pMemoryHandle = nullptr;
    propertiesIterator                     = startOfProperties;
    while (propertiesIterator->name != 0)
    {
        switch (propertiesIterator->name)
        {
            case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR:
            case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR:
                if (pMemoryHandle)
                {
                    // CL_INVALID_PROPERTY if properties includes more than one external memory
                    // handle
                    return CL_INVALID_PROPERTY;
                }
                pMemoryHandle = propertiesIterator;
                break;
            default:
                break;
        }
        propertiesIterator++;
    }
    if (!pMemoryHandle)
    {
        // CL_INVALID_PROPERTY if properties does not include a supported external memory handle
        return CL_INVALID_PROPERTY;
    }
    else
    {
        switch (pMemoryHandle->name)
        {
            case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR:
            case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR:
            {
                // just validate the basics for dma_buf and posix fd for now
                uint32_t fdDmaBuf = *reinterpret_cast<uint32_t *>(pMemoryHandle->value);
                if (host_ptr != nullptr)
                {
                    // CL_INVALID_HOST_PTR if properties includes a supported external memory handle
                    // and host_ptr is not NULL
                    return CL_INVALID_HOST_PTR;
                }
                if (fdDmaBuf < 0)
                {
                    return CL_INVALID_PROPERTY;
                }
                break;
            }
            default:
            {
                ASSERT(false);  // should not reach here
                return CL_INVALID_PROPERTY;
            }
        }
    }

    // next, get/validate the device sub-list from properties
    std::vector<Device *> devices;
    bool isDeviceListDefined = false;
    cl::Context &ctx         = context->cast<Context>();
    propertiesIterator       = startOfProperties;
    while (propertiesIterator->name != 0)
    {
        if (propertiesIterator->name == CL_MEM_DEVICE_HANDLE_LIST_KHR)
        {
            if (isDeviceListDefined)
            {
                // CL_INVALID_PROPERTY if the same property name is specified more than once
                return CL_INVALID_PROPERTY;
            }
            isDeviceListDefined = true;
            cl_device_id device = reinterpret_cast<cl_device_id>(propertiesIterator->value);
            while (device != CL_MEM_DEVICE_HANDLE_LIST_END_KHR)
            {
                if (!Device::IsValid(device) || !ctx.hasDevice(device))
                {
                    // CL_INVALID_DEVICE if a device identified by the property
                    // CL_MEM_DEVICE_HANDLE_LIST_KHR is not a valid device or is not associated
                    // with context
                    return CL_INVALID_DEVICE;
                }
                devices.push_back(&device->cast<Device>());
                device++;
            }
        }
        propertiesIterator++;
    }
    if (!devices.empty())
    {
        for (const auto &device : devices)
        {
            if (!device->getInfo().externalMemoryHandleSupport.test(
                    FromCLenum<ExternalMemoryHandle>(static_cast<CLenum>(pMemoryHandle->name))))
            {
                // CL_INVALID_DEVICE if a device identified by property
                // CL_MEM_DEVICE_HANDLE_LIST_KHR cannot import the requested external memory object
                // type
                return CL_INVALID_DEVICE;
            }
        }
    }
    else
    {
        // there was no device list defined in properties, use associated devices with context
        for (const auto &devicePtr : ctx.getDevices())
        {
            if (!devicePtr->getInfo().externalMemoryHandleSupport.test(
                    FromCLenum<ExternalMemoryHandle>(static_cast<CLenum>(pMemoryHandle->name))))
            {
                // if CL_MEM_DEVICE_HANDLE_LIST_KHR is not specified as part of properties and one
                // or more devices in context cannot import the requested external memory object
                // type
                return CL_INVALID_DEVICE;
            }
        }
    }

    // When a buffer or image is created from an external memory handle,
    // the flags used to specify usage information for the buffer or image must not include
    // CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR, or CL_MEM_COPY_HOST_PTR
    if (flags.intersects(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateCommandQueueAndEventWaitList(cl_command_queue commandQueue,
                                            bool validateImageSupport,
                                            cl_uint numEvents,
                                            const cl_event *events)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
    if (!CommandQueue::IsValid(commandQueue))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    const CommandQueue &queue = commandQueue->cast<CommandQueue>();
    if (!queue.isOnHost())
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    if (validateImageSupport)
    {
        // CL_INVALID_OPERATION if the device associated with command_queue does not support images.
        if (queue.getDevice().getInfo().imageSupport == CL_FALSE)
        {
            return CL_INVALID_OPERATION;
        }
    }

    // CL_INVALID_EVENT_WAIT_LIST if event_wait_list is NULL and num_events_in_wait_list > 0,
    // or event_wait_list is not NULL and num_events_in_wait_list is 0, ...
    if ((events == nullptr) != (numEvents == 0u))
    {
        return CL_INVALID_EVENT_WAIT_LIST;
    }
    while (numEvents-- != 0u)
    {
        // or if event objects in event_wait_list are not valid events.
        if (!Event::IsValid(*events))
        {
            return CL_INVALID_EVENT_WAIT_LIST;
        }

        // CL_INVALID_CONTEXT if the context associated with command_queue
        // and events in event_wait_list are not the same.
        if (&queue.getContext() != &(*events++)->cast<Event>().getContext())
        {
            return CL_INVALID_CONTEXT;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateEnqueueBuffer(const CommandQueue &queue,
                             cl_mem buffer,
                             bool hostRead,
                             bool hostWrite)
{
    // CL_INVALID_MEM_OBJECT if buffer is not a valid buffer object.
    if (!Buffer::IsValid(buffer))
    {
        return CL_INVALID_MEM_OBJECT;
    }
    const Buffer &buf = buffer->cast<Buffer>();

    // CL_INVALID_CONTEXT if the context associated with command_queue and buffer are not the same.
    if (&queue.getContext() != &buf.getContext())
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_MISALIGNED_SUB_BUFFER_OFFSET if buffer is a sub-buffer object and offset specified
    // when the sub-buffer object is created is not aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN
    // value (which is in bits!) for device associated with queue.
    if (buf.isSubBuffer() &&
        (buf.getOffset() % (queue.getDevice().getInfo().memBaseAddrAlign / 8u)) != 0u)
    {
        return CL_MISALIGNED_SUB_BUFFER_OFFSET;
    }

    // CL_INVALID_OPERATION if a read function is called on buffer which
    // has been created with CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS.
    if (hostRead && buf.getFlags().intersects(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS))
    {
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_OPERATION if a write function is called on buffer which
    // has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS.
    if (hostWrite && buf.getFlags().intersects(CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS))
    {
        return CL_INVALID_OPERATION;
    }

    return CL_SUCCESS;
}

cl_int ValidateBufferRect(const Buffer &buffer,
                          const size_t *origin,
                          const size_t *region,
                          size_t rowPitch,
                          size_t slicePitch)
{
    // CL_INVALID_VALUE if origin or region is NULL.
    if (origin == nullptr || region == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if any region array element is 0.
    if (region[0] == 0u || region[1] == 0u || region[2] == 0u)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if row_pitch is not 0 and is less than region[0].
    if (rowPitch == 0u)
    {
        rowPitch = region[0];
    }
    else if (rowPitch < region[0])
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if slice_pitch is not 0 and is less than
    // region[1] x row_pitch and not a multiple of row_pitch.
    if (slicePitch == 0u)
    {
        slicePitch = region[1] * rowPitch;
    }
    else if (slicePitch < region[1] * rowPitch || (slicePitch % rowPitch) != 0u)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if the region being read or written specified
    // by (origin, region, row_pitch, slice_pitch) is out of bounds.
    if (!buffer.isRegionValid(
            origin[2] * slicePitch + origin[1] * rowPitch + origin[0],
            (region[2] - 1u) * slicePitch + (region[1] - 1u) * rowPitch + region[0]))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateHostRect(const size_t *hostOrigin,
                        const size_t *region,
                        size_t hostRowPitch,
                        size_t hostSlicePitch,
                        const void *ptr)
{
    // CL_INVALID_VALUE if host_origin or region is NULL.
    if (hostOrigin == nullptr || region == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if any region array element is 0.
    if (region[0] == 0u || region[1] == 0u || region[2] == 0u)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if host_row_pitch is not 0 and is less than region[0].
    if (hostRowPitch == 0u)
    {
        hostRowPitch = region[0];
    }
    else if (hostRowPitch < region[0])
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if host_slice_pitch is not 0 and is less than
    // region[1] x host_row_pitch and not a multiple of host_row_pitch.
    if (hostSlicePitch != 0u &&
        (hostSlicePitch < region[1] * hostRowPitch || (hostSlicePitch % hostRowPitch) != 0u))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if ptr is NULL.
    if (ptr == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateEnqueueImage(const CommandQueue &queue, cl_mem image, bool hostRead, bool hostWrite)
{
    // CL_INVALID_MEM_OBJECT if image is not a valid image object.
    if (!Image::IsValid(image))
    {
        return CL_INVALID_MEM_OBJECT;
    }
    const Image &img = image->cast<Image>();

    // CL_INVALID_CONTEXT if the context associated with command_queue and image are not the same.
    if (&queue.getContext() != &img.getContext())
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_OPERATION if a read function is called on image which
    // has been created with CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS.
    if (hostRead && img.getFlags().intersects(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS))
    {
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_OPERATION if a write function is called on image which
    // has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS.
    if (hostWrite && img.getFlags().intersects(CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS))
    {
        return CL_INVALID_OPERATION;
    }

    return CL_SUCCESS;
}

cl_int ValidateImageForDevice(const Image &image,
                              const Device &device,
                              const size_t *origin,
                              const size_t *region)
{
    // CL_INVALID_VALUE if origin or region is NULL.
    if (origin == nullptr || region == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if values in origin and region do not follow rules
    // described in the argument description for origin and region.
    // The values in region cannot be 0.
    if (region[0] == 0u || region[1] == 0u || region[2] == 0u)
    {
        return CL_INVALID_VALUE;
    }
    switch (image.getType())
    {
        // If image is a 1D image or 1D image buffer object,
        // origin[1] and origin[2] must be 0 and region[1] and region[2] must be 1.
        case MemObjectType::Image1D:
        case MemObjectType::Image1D_Buffer:
            if (origin[1] != 0u || origin[2] != 0u || region[1] != 1u || region[2] != 1u)
            {
                return CL_INVALID_VALUE;
            }
            break;
        // If image is a 2D image object or a 1D image array object,
        // origin[2] must be 0 and region[2] must be 1.
        case MemObjectType::Image2D:
        case MemObjectType::Image1D_Array:
            if (origin[2] != 0u || region[2] != 1u)
            {
                return CL_INVALID_VALUE;
            }
            break;
        case MemObjectType::Image3D:
        case MemObjectType::Image2D_Array:
            break;
        default:
            ASSERT(false);
            return CL_INVALID_IMAGE_DESCRIPTOR;
    }

    // CL_INVALID_VALUE if the region being read or written
    // specified by origin and region is out of bounds.

    if (!image.isRegionValid(cl::Offset{origin[0], origin[1], origin[2]},
                             cl::Extents{region[0], region[1], region[2]}))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute
    // row and/or slice pitch) for image are not supported by device associated with queue.
    if (!device.supportsImageDimensions(image.getDescriptor()))
    {
        return CL_INVALID_IMAGE_SIZE;
    }

    return CL_SUCCESS;
}

cl_int ValidateHostRegionForImage(const Image &image,
                                  const size_t region[3],
                                  size_t rowPitch,
                                  size_t slicePitch,
                                  const void *ptr)
{
    // CL_INVALID_VALUE if row_pitch is not 0 and is less than the element size in bytes x width.
    if (rowPitch == 0u)
    {
        rowPitch = image.getElementSize() * region[0];
    }
    else if (rowPitch < image.getElementSize() * region[0])
    {
        return CL_INVALID_VALUE;
    }
    if (slicePitch != 0u)
    {
        // TODO(jplate) Follow up with https://github.com/KhronosGroup/OpenCL-Docs/issues/624
        // This error is missing in the OpenCL spec.
        // slice_pitch must be 0 if image is a 1D or 2D image.
        if (image.getType() == MemObjectType::Image1D ||
            image.getType() == MemObjectType::Image1D_Buffer ||
            image.getType() == MemObjectType::Image2D)
        {
            return CL_INVALID_VALUE;
        }
        else if (slicePitch < rowPitch)
        {
            return CL_INVALID_VALUE;
        }
        // CL_INVALID_VALUE if slice_pitch is not 0 and is less than row_pitch x height.
        else if (((image.getType() == MemObjectType::Image2D_Array) ||
                  (image.getType() == MemObjectType::Image3D)) &&
                 (slicePitch < rowPitch * region[1]))
        {
            return CL_INVALID_VALUE;
        }
    }

    // CL_INVALID_VALUE if ptr is NULL.
    if (ptr == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

}  // namespace

// CL 1.0
cl_int ValidateGetPlatformIDs(cl_uint num_entries,
                              const cl_platform_id *platforms,
                              const cl_uint *num_platforms)
{
    // CL_INVALID_VALUE if num_entries is equal to zero and platforms is not NULL
    // or if both num_platforms and platforms are NULL.
    if ((num_entries == 0u && platforms != nullptr) ||
        (platforms == nullptr && num_platforms == nullptr))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateGetPlatformInfo(cl_platform_id platform,
                               PlatformInfo param_name,
                               size_t param_value_size,
                               const void *param_value,
                               const size_t *param_value_size_ret)
{
    // CL_INVALID_PLATFORM if platform is not a valid platform.
    if (!Platform::IsValidOrDefault(platform))
    {
        return CL_INVALID_PLATFORM;
    }

    // CL_INVALID_VALUE if param_name is not one of the supported values.
    const cl_version version = platform->cast<Platform>().getVersion();
    switch (param_name)
    {
        case PlatformInfo::HostTimerResolution:
            ANGLE_VALIDATE_VERSION(version, 2, 1);
            break;
        case PlatformInfo::NumericVersion:
        case PlatformInfo::ExtensionsWithVersion:
            ANGLE_VALIDATE_VERSION(version, 3, 0);
            break;
        case PlatformInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    // TODO: we need to validate cl_khr_external_memory enum queries here as well
    // http://anglebug.com/439565645

    return CL_SUCCESS;
}

cl_int ValidateGetDeviceIDs(cl_platform_id platform,
                            DeviceType device_type,
                            cl_uint num_entries,
                            const cl_device_id *devices,
                            const cl_uint *num_devices)
{
    // CL_INVALID_PLATFORM if platform is not a valid platform.
    if (!Platform::IsValidOrDefault(platform))
    {
        return CL_INVALID_PLATFORM;
    }

    // CL_INVALID_DEVICE_TYPE if device_type is not a valid value.
    if (!Device::IsValidType(device_type))
    {
        return CL_INVALID_DEVICE_TYPE;
    }

    // CL_DEVICE_NOT_FOUND if no OpenCL devices that matched device_type were found.
    if (!platform->cast<cl::Platform>().hasDeviceType(device_type))
    {
        return CL_DEVICE_NOT_FOUND;
    }

    // CL_INVALID_VALUE if num_entries is equal to zero and devices is not NULL
    // or if both num_devices and devices are NULL.
    if ((num_entries == 0u && devices != nullptr) || (num_devices == nullptr && devices == nullptr))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateGetDeviceInfo(cl_device_id device,
                             DeviceInfo param_name,
                             size_t param_value_size,
                             const void *param_value,
                             const size_t *param_value_size_ret)
{
    // CL_INVALID_DEVICE if device is not a valid device.
    if (!Device::IsValid(device))
    {
        return CL_INVALID_DEVICE;
    }
    const Device &dev = device->cast<Device>();

    // CL_INVALID_VALUE if param_name is not one of the supported values
    // or if param_name is a value that is available as an extension
    // and the corresponding extension is not supported by the device.
    const cl_version version           = dev.getVersion();
    const rx::CLDeviceImpl::Info &info = dev.getInfo();
    // Enums ordered within their version block as they appear in the OpenCL spec V3.0.7, table 5
    switch (param_name)
    {
        case DeviceInfo::PreferredVectorWidthHalf:
        case DeviceInfo::NativeVectorWidthChar:
        case DeviceInfo::NativeVectorWidthShort:
        case DeviceInfo::NativeVectorWidthInt:
        case DeviceInfo::NativeVectorWidthLong:
        case DeviceInfo::NativeVectorWidthFloat:
        case DeviceInfo::NativeVectorWidthDouble:
        case DeviceInfo::NativeVectorWidthHalf:
        case DeviceInfo::HostUnifiedMemory:
        case DeviceInfo::OpenCL_C_Version:
            ANGLE_VALIDATE_VERSION(version, 1, 1);
            break;

        case DeviceInfo::ImageMaxBufferSize:
        case DeviceInfo::ImageMaxArraySize:
        case DeviceInfo::LinkerAvailable:
        case DeviceInfo::BuiltInKernels:
        case DeviceInfo::PrintfBufferSize:
        case DeviceInfo::PreferredInteropUserSync:
        case DeviceInfo::ParentDevice:
        case DeviceInfo::PartitionMaxSubDevices:
        case DeviceInfo::PartitionProperties:
        case DeviceInfo::PartitionAffinityDomain:
        case DeviceInfo::PartitionType:
        case DeviceInfo::ReferenceCount:
            ANGLE_VALIDATE_VERSION(version, 1, 2);
            break;

        case DeviceInfo::MaxReadWriteImageArgs:
        case DeviceInfo::ImagePitchAlignment:
        case DeviceInfo::ImageBaseAddressAlignment:
        case DeviceInfo::MaxPipeArgs:
        case DeviceInfo::PipeMaxActiveReservations:
        case DeviceInfo::PipeMaxPacketSize:
        case DeviceInfo::MaxGlobalVariableSize:
        case DeviceInfo::GlobalVariablePreferredTotalSize:
        case DeviceInfo::QueueOnDeviceProperties:
        case DeviceInfo::QueueOnDevicePreferredSize:
        case DeviceInfo::QueueOnDeviceMaxSize:
        case DeviceInfo::MaxOnDeviceQueues:
        case DeviceInfo::MaxOnDeviceEvents:
        case DeviceInfo::SVM_Capabilities:
        case DeviceInfo::PreferredPlatformAtomicAlignment:
        case DeviceInfo::PreferredGlobalAtomicAlignment:
        case DeviceInfo::PreferredLocalAtomicAlignment:
            ANGLE_VALIDATE_VERSION(version, 2, 0);
            break;

        case DeviceInfo::IL_Version:
        case DeviceInfo::MaxNumSubGroups:
        case DeviceInfo::SubGroupIndependentForwardProgress:
            ANGLE_VALIDATE_VERSION(version, 2, 1);
            break;

        case DeviceInfo::ILsWithVersion:
        case DeviceInfo::BuiltInKernelsWithVersion:
        case DeviceInfo::NumericVersion:
        case DeviceInfo::OpenCL_C_AllVersions:
        case DeviceInfo::OpenCL_C_Features:
        case DeviceInfo::ExtensionsWithVersion:
        case DeviceInfo::AtomicMemoryCapabilities:
        case DeviceInfo::AtomicFenceCapabilities:
        case DeviceInfo::NonUniformWorkGroupSupport:
        case DeviceInfo::WorkGroupCollectiveFunctionsSupport:
        case DeviceInfo::GenericAddressSpaceSupport:
        case DeviceInfo::DeviceEnqueueCapabilities:
        case DeviceInfo::PipeSupport:
        case DeviceInfo::PreferredWorkGroupSizeMultiple:
        case DeviceInfo::LatestConformanceVersionPassed:
            ANGLE_VALIDATE_VERSION(version, 3, 0);
            break;

        case DeviceInfo::DoubleFpConfig:
            // This extension became a core query from OpenCL 1.2 onward.
            // Only need to validate for OpenCL versions less than 1.2 here.
            ANGLE_VALIDATE_VERSION_OR_EXTENSION(version, 1, 2, info.khrFP64);
            break;

        case DeviceInfo::IntegerDotProductCapabilities:
        case DeviceInfo::IntegerDotProductAccelerationProperties8bit:
        case DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked:
            ANGLE_VALIDATE_VERSION_OR_EXTENSION(version, 3, 0, info.khrIntegerDotProduct);
            break;

        case DeviceInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    // TODO: we need to validate cl_khr_external_memory enum queries here as well
    // http://anglebug.com/439565645

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_VALUE if devices is NULL or if num_devices is equal to zero
    // or if pfn_notify is NULL but user_data is not NULL.
    if (devices == nullptr || num_devices == 0u || (pfn_notify == nullptr && user_data != nullptr))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_DEVICE if any device in devices is not a valid device.
    for (cl_uint i = 0; i < num_devices; ++i)
    {
        if (!Device::IsValid(devices[i]))
        {
            return CL_INVALID_DEVICE;
        }
    }

    // Because ANGLE can have one or more platforms here (e.g. passthrough, Vulkan, etc.), if a
    // context platform is not explicitly specified in the properties, spec says to default to an
    // implementation-defined platform. In ANGLE's case, we can derive the platform from the device
    // object.
    const Platform *platform = nullptr;
    ANGLE_VALIDATE(ValidateContextProperties(properties, platform));
    if (platform == nullptr)
    {
        // Just use/pick the first device's platform object here
        platform = &(devices[0])->cast<Device>().getPlatform();
    }

    // Ensure that each device in device list is derived from the same platform object
    for (cl_uint i = 0; i < num_devices; ++i)
    {
        if (platform != &(devices[i])->cast<Device>().getPlatform())
        {
            return CL_INVALID_PLATFORM;
        }
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_DEVICE_TYPE if device_type is not a valid value.
    if (!Device::IsValidType(device_type))
    {
        return CL_INVALID_DEVICE_TYPE;
    }

    const Platform *platform = nullptr;
    ANGLE_VALIDATE(ValidateContextProperties(properties, platform));
    if (platform == nullptr)
    {
        platform = Platform::GetDefault();
        if (platform == nullptr)
        {
            return CL_INVALID_PLATFORM;
        }
    }

    if (!platform->hasDeviceType(device_type))
    {
        return CL_DEVICE_NOT_FOUND;
    }

    // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
    if (pfn_notify == nullptr && user_data != nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainContext(cl_context context)
{
    // CL_INVALID_CONTEXT if context is not a valid OpenCL context.
    return Context::IsValid(context) ? CL_SUCCESS : CL_INVALID_CONTEXT;
}

cl_int ValidateReleaseContext(cl_context context)
{
    // CL_INVALID_CONTEXT if context is not a valid OpenCL context.
    return Context::IsValid(context) ? CL_SUCCESS : CL_INVALID_CONTEXT;
}

cl_int ValidateGetContextInfo(cl_context context,
                              ContextInfo param_name,
                              size_t param_value_size,
                              const void *param_value,
                              const size_t *param_value_size_ret)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValid(context))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_VALUE if param_name is not one of the supported values.
    if (param_name == ContextInfo::InvalidEnum)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainCommandQueue(cl_command_queue command_queue)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
    return CommandQueue::IsValid(command_queue) ? CL_SUCCESS : CL_INVALID_COMMAND_QUEUE;
}

cl_int ValidateReleaseCommandQueue(cl_command_queue command_queue)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
    return CommandQueue::IsValid(command_queue) ? CL_SUCCESS : CL_INVALID_COMMAND_QUEUE;
}

cl_int 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)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue
    if (!CommandQueue::IsValid(command_queue))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    // CL_INVALID_VALUE if param_name is not one of the supported values.
    const cl_version version = queue.getDevice().getVersion();
    switch (param_name)
    {
        case CommandQueueInfo::Size:
            ANGLE_VALIDATE_VERSION(version, 2, 0);
            break;
        case CommandQueueInfo::DeviceDefault:
            ANGLE_VALIDATE_VERSION(version, 2, 1);
            break;
        case CommandQueueInfo::PropertiesArray:
            ANGLE_VALIDATE_VERSION(version, 3, 0);
            break;
        case CommandQueueInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue for param_name.
    if (param_name == CommandQueueInfo::Size)
    {
        if (queue.isOnDevice() && !queue.getDevice().hasDeviceEnqueueCaps())
        {
            return CL_INVALID_COMMAND_QUEUE;
        }
        if (queue.getDevice().getPlatform().isVersionOrNewer(3u, 0u) && !queue.isOnDevice())
        {
            // Device-side enqueue and on-device queues are optional for devices supporting
            // OpenCL 3.0. When device-side enqueue is not supported:
            // - clGetCommandQueueInfo, passing CL_QUEUE_SIZE Returns CL_INVALID_COMMAND_QUEUE since
            // command_queue cannot be a valid device command-queue.
            return CL_INVALID_COMMAND_QUEUE;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateCreateBuffer(cl_context context, MemFlags flags, size_t size, const void *host_ptr)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValid(context))
    {
        return CL_INVALID_CONTEXT;
    }
    const Context &ctx = context->cast<Context>();

    // CL_INVALID_VALUE if values specified in flags are not valid
    // as defined in the Memory Flags table.
    if (!ValidateMemoryFlags(flags, ctx.getPlatform()))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_BUFFER_SIZE if size is 0 ...
    if (size == 0u)
    {
        CL_INVALID_BUFFER_SIZE;
    }
    for (const DevicePtr &device : ctx.getDevices())
    {
        // or if size is greater than CL_DEVICE_MAX_MEM_ALLOC_SIZE for all devices in context.
        if (size > device->getInfo().maxMemAllocSize)
        {
            return CL_INVALID_BUFFER_SIZE;
        }
    }

    // CL_INVALID_HOST_PTR
    // if host_ptr is NULL and CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR are set in flags or
    // if host_ptr is not NULL but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in flags.
    if ((host_ptr != nullptr) != flags.intersects(CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))
    {
        return CL_INVALID_HOST_PTR;
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainMemObject(cl_mem memobj)
{
    // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object.
    return Memory::IsValid(memobj) ? CL_SUCCESS : CL_INVALID_MEM_OBJECT;
}

cl_int ValidateReleaseMemObject(cl_mem memobj)
{
    // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object.
    return Memory::IsValid(memobj) ? CL_SUCCESS : CL_INVALID_MEM_OBJECT;
}

cl_int 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)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValid(context))
    {
        return CL_INVALID_CONTEXT;
    }
    const Context &ctx = context->cast<Context>();

    // CL_INVALID_VALUE if flags or image_type are not valid,
    if (!ValidateMemoryFlags(flags, ctx.getPlatform()) || !Image::IsTypeValid(image_type))
    {
        return CL_INVALID_VALUE;
    }
    // or if num_entries is 0 and image_formats is not NULL.
    if (num_entries == 0u && image_formats != nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateGetMemObjectInfo(cl_mem memobj,
                                MemInfo param_name,
                                size_t param_value_size,
                                const void *param_value,
                                const size_t *param_value_size_ret)
{
    // CL_INVALID_MEM_OBJECT if memobj is a not a valid memory object.
    if (!Memory::IsValid(memobj))
    {
        return CL_INVALID_MEM_OBJECT;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = memobj->cast<Memory>().getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case MemInfo::AssociatedMemObject:
        case MemInfo::Offset:
            ANGLE_VALIDATE_VERSION(version, 1, 1);
            break;
        case MemInfo::UsesSVM_Pointer:
            ANGLE_VALIDATE_VERSION(version, 2, 0);
            break;
        case MemInfo::Properties:
            ANGLE_VALIDATE_VERSION(version, 3, 0);
            break;
        case MemInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    return CL_SUCCESS;
}

cl_int ValidateGetImageInfo(cl_mem image,
                            ImageInfo param_name,
                            size_t param_value_size,
                            const void *param_value,
                            const size_t *param_value_size_ret)
{
    // CL_INVALID_MEM_OBJECT if image is a not a valid image object.
    if (!Image::IsValid(image))
    {
        return CL_INVALID_MEM_OBJECT;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = image->cast<Image>().getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case ImageInfo::ArraySize:
        case ImageInfo::Buffer:
        case ImageInfo::NumMipLevels:
        case ImageInfo::NumSamples:
            ANGLE_VALIDATE_VERSION(version, 1, 2);
            break;
        case ImageInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainSampler(cl_sampler sampler)
{
    // CL_INVALID_SAMPLER if sampler is not a valid sampler object.
    return Sampler::IsValid(sampler) ? CL_SUCCESS : CL_INVALID_SAMPLER;
}

cl_int ValidateReleaseSampler(cl_sampler sampler)
{
    // CL_INVALID_SAMPLER if sampler is not a valid sampler object.
    return Sampler::IsValid(sampler) ? CL_SUCCESS : CL_INVALID_SAMPLER;
}

cl_int ValidateGetSamplerInfo(cl_sampler sampler,
                              SamplerInfo param_name,
                              size_t param_value_size,
                              const void *param_value,
                              const size_t *param_value_size_ret)
{
    // CL_INVALID_SAMPLER if sampler is a not a valid sampler object.
    if (!Sampler::IsValid(sampler))
    {
        return CL_INVALID_SAMPLER;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = sampler->cast<Sampler>().getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case SamplerInfo::Properties:
            ANGLE_VALIDATE_VERSION(version, 3, 0);
            break;
        case SamplerInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    return CL_SUCCESS;
}

cl_int ValidateCreateProgramWithSource(cl_context context,
                                       cl_uint count,
                                       const char **strings,
                                       const size_t *lengths)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValid(context))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_VALUE if count is zero or if strings or any entry in strings is NULL.
    if (count == 0u || strings == nullptr)
    {
        return CL_INVALID_VALUE;
    }
    while (count-- != 0u)
    {
        if (*strings++ == nullptr)
        {
            return CL_INVALID_VALUE;
        }
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValid(context))
    {
        return CL_INVALID_CONTEXT;
    }
    const Context &ctx = context->cast<Context>();

    // CL_INVALID_VALUE if device_list is NULL or num_devices is zero.
    // CL_INVALID_VALUE if lengths or binaries is NULL.
    if (device_list == nullptr || num_devices == 0u || lengths == nullptr || binaries == nullptr)
    {
        return CL_INVALID_VALUE;
    }
    while (num_devices-- != 0u)
    {
        // CL_INVALID_DEVICE if any device in device_list
        // is not in the list of devices associated with context.
        if (!ctx.hasDevice(*device_list++))
        {
            return CL_INVALID_DEVICE;
        }

        // CL_INVALID_VALUE if any entry in lengths[i] is zero or binaries[i] is NULL.
        if (*lengths++ == 0u || *binaries++ == nullptr)
        {
            return CL_INVALID_VALUE;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainProgram(cl_program program)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    return Program::IsValid(program) ? CL_SUCCESS : CL_INVALID_PROGRAM;
}

cl_int ValidateReleaseProgram(cl_program program)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    return Program::IsValid(program) ? CL_SUCCESS : CL_INVALID_PROGRAM;
}

cl_int 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)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    if (!Program::IsValid(program))
    {
        return CL_INVALID_PROGRAM;
    }
    const Program &prog = program->cast<Program>();

    // CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero,
    // or if device_list is not NULL and num_devices is zero.
    if ((device_list != nullptr) != (num_devices != 0u))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_DEVICE if any device in device_list
    // is not in the list of devices associated with program.
    while (num_devices-- != 0u)
    {
        if (!prog.hasDevice(*device_list++))
        {
            return CL_INVALID_DEVICE;
        }
    }

    // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
    if (pfn_notify == nullptr && user_data != nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_OPERATION if the build of a program executable for any of the devices listed
    // in device_list by a previous call to clBuildProgram for program has not completed.
    if (prog.isBuilding())
    {
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_OPERATION if there are kernel objects attached to program.
    if (prog.hasAttachedKernels())
    {
        return CL_INVALID_OPERATION;
    }

    // If program was created with clCreateProgramWithBinary and device does not have a valid
    // program binary loaded
    std::vector<size_t> binSizes{prog.getDevices().size()};
    std::vector<std::vector<unsigned char *>> bins{prog.getDevices().size()};
    if (IsError(prog.getInfo(ProgramInfo::BinarySizes, binSizes.size() * sizeof(size_t),
                             binSizes.data(), nullptr)))
    {
        return CL_INVALID_PROGRAM;
    }
    for (size_t i = 0; i < prog.getDevices().size(); ++i)
    {
        cl_program_binary_type binType;
        bins.at(i).resize(binSizes[i]);

        if (IsError(prog.getInfo(ProgramInfo::Binaries, sizeof(unsigned char *) * bins.size(),
                                 bins.data(), nullptr)))
        {
            return CL_INVALID_VALUE;
        }
        if (IsError(prog.getBuildInfo(prog.getDevices()[i]->getNative(),
                                      ProgramBuildInfo::BinaryType, sizeof(cl_program_binary_type),
                                      &binType, nullptr)))
        {
            return CL_INVALID_VALUE;
        }
        if ((binType != CL_PROGRAM_BINARY_TYPE_NONE) && bins[i].empty())
        {
            return CL_INVALID_BINARY;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateGetProgramInfo(cl_program program,
                              ProgramInfo param_name,
                              size_t param_value_size,
                              const void *param_value,
                              const size_t *param_value_size_ret)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    if (!Program::IsValid(program))
    {
        return CL_INVALID_PROGRAM;
    }
    const Program &prog = program->cast<Program>();

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = prog.getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case ProgramInfo::NumKernels:
        case ProgramInfo::KernelNames:
            ANGLE_VALIDATE_VERSION(version, 1, 2);
            break;
        case ProgramInfo::IL:
            ANGLE_VALIDATE_VERSION(version, 2, 1);
            break;
        case ProgramInfo::ScopeGlobalCtorsPresent:
        case ProgramInfo::ScopeGlobalDtorsPresent:
            ANGLE_VALIDATE_VERSION(version, 2, 2);
            break;
        case ProgramInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
    // as described in the Program Object Queries table and param_value is not NULL.
    if (param_value != nullptr)
    {
        size_t valueSizeRet = 0;
        if (IsError(prog.getInfo(param_name, 0, nullptr, &valueSizeRet)) ||
            param_value_size < valueSizeRet)
        {
            return CL_INVALID_VALUE;
        }
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    if (!Program::IsValid(program))
    {
        return CL_INVALID_PROGRAM;
    }
    const Program &prog = program->cast<Program>();

    // CL_INVALID_DEVICE if device is not in the list of devices associated with program.
    if (!prog.hasDevice(device))
    {
        return CL_INVALID_DEVICE;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = prog.getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case ProgramBuildInfo::BinaryType:
            ANGLE_VALIDATE_VERSION(version, 1, 2);
            break;
        case ProgramBuildInfo::GlobalVariableTotalSize:
            ANGLE_VALIDATE_VERSION(version, 2, 0);
            break;
        case ProgramBuildInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
    // as described in the Program Object Queries table and param_value is not NULL.
    if (param_value != nullptr)
    {
        size_t valueSizeRet = 0;
        if (IsError(prog.getBuildInfo(device, param_name, 0, nullptr, &valueSizeRet)) ||
            param_value_size < valueSizeRet)
        {
            return CL_INVALID_VALUE;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateCreateKernel(cl_program program, const char *kernel_name)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    if (!Program::IsValid(program))
    {
        return CL_INVALID_PROGRAM;
    }
    cl::Program &prog = program->cast<cl::Program>();

    // CL_INVALID_VALUE if kernel_name is NULL.
    if (kernel_name == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built executable for program.
    std::vector<cl_device_id> associatedDevices;
    size_t associatedDeviceCount = 0;
    bool isAnyDeviceProgramBuilt = false;
    if (IsError(prog.getInfo(ProgramInfo::Devices, 0, nullptr, &associatedDeviceCount)))
    {
        return CL_INVALID_PROGRAM;
    }
    associatedDevices.resize(associatedDeviceCount / sizeof(cl_device_id));
    if (IsError(prog.getInfo(ProgramInfo::Devices, associatedDeviceCount, associatedDevices.data(),
                             nullptr)))
    {
        return CL_INVALID_PROGRAM;
    }
    for (const cl_device_id &device : associatedDevices)
    {
        cl_build_status status = CL_BUILD_NONE;
        if (IsError(prog.getBuildInfo(device, ProgramBuildInfo::Status, sizeof(cl_build_status),
                                      &status, nullptr)))
        {
            return CL_INVALID_PROGRAM;
        }

        if (status == CL_BUILD_SUCCESS)
        {
            isAnyDeviceProgramBuilt = true;
            break;
        }
    }
    if (!isAnyDeviceProgramBuilt)
    {
        return CL_INVALID_PROGRAM_EXECUTABLE;
    }

    // CL_INVALID_KERNEL_NAME if kernel_name is not found in program.
    std::string kernelNames;
    size_t kernelNamesSize = 0;
    if (IsError(prog.getInfo(ProgramInfo::KernelNames, 0, nullptr, &kernelNamesSize)))
    {
        return CL_INVALID_PROGRAM;
    }
    kernelNames.resize(kernelNamesSize);
    if (IsError(
            prog.getInfo(ProgramInfo::KernelNames, kernelNamesSize, kernelNames.data(), nullptr)))
    {
        return CL_INVALID_PROGRAM;
    }
    std::vector<std::string> tokenizedKernelNames =
        angle::SplitString(kernelNames.c_str(), ";", angle::WhitespaceHandling::TRIM_WHITESPACE,
                           angle::SplitResult::SPLIT_WANT_NONEMPTY);
    if (std::find(tokenizedKernelNames.begin(), tokenizedKernelNames.end(), kernel_name) ==
        tokenizedKernelNames.end())
    {
        return CL_INVALID_KERNEL_NAME;
    }

    return CL_SUCCESS;
}

cl_int ValidateCreateKernelsInProgram(cl_program program,
                                      cl_uint num_kernels,
                                      const cl_kernel *kernels,
                                      const cl_uint *num_kernels_ret)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    if (!Program::IsValid(program))
    {
        return CL_INVALID_PROGRAM;
    }

    // CL_INVALID_VALUE if kernels is not NULL and num_kernels is less than the number of kernels in
    // program.
    size_t kernelCount = 0;
    cl::Program &prog  = program->cast<cl::Program>();
    if (IsError(prog.getInfo(ProgramInfo::NumKernels, sizeof(size_t), &prog, nullptr)))
    {
        return CL_INVALID_PROGRAM;
    }
    if (kernels != nullptr && num_kernels < kernelCount)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainKernel(cl_kernel kernel)
{
    // CL_INVALID_KERNEL if kernel is not a valid kernel object.
    return Kernel::IsValid(kernel) ? CL_SUCCESS : CL_INVALID_KERNEL;
}

cl_int ValidateReleaseKernel(cl_kernel kernel)
{
    // CL_INVALID_KERNEL if kernel is not a valid kernel object.
    return Kernel::IsValid(kernel) ? CL_SUCCESS : CL_INVALID_KERNEL;
}

cl_int ValidateSetKernelArg(cl_kernel kernel,
                            cl_uint arg_index,
                            size_t arg_size,
                            const void *arg_value)
{
    static_assert(sizeof(cl_mem) == sizeof(cl_sampler), "api object size check failed");
    static_assert(sizeof(cl_mem) == sizeof(cl_command_queue), "api object size check failed");

    // CL_INVALID_KERNEL if kernel is not a valid kernel object.
    if (!Kernel::IsValid(kernel))
    {
        return CL_INVALID_KERNEL;
    }

    const Kernel &krnl = kernel->cast<Kernel>();

    // CL_INVALID_ARG_INDEX if arg_index is not a valid argument index.
    if (arg_index >= krnl.getInfo().args.size())
    {
        return CL_INVALID_ARG_INDEX;
    }

    const std::string &typeName = krnl.getInfo().args[arg_index].typeName;

    // [1/6] Checking for special case for sampler type, on invalid sampler arguments possible error
    // codes are CL_INVALID_SAMPLER and CL_INVALID_ARG_SIZE.
    if (typeName == "sampler_t")
    {

        if (arg_size != sizeof(cl_sampler))
        {
            //  If the argument is of type sampler_t, the arg_size value must be equal to
            //  sizeof(cl_sampler)
            return CL_INVALID_ARG_SIZE;
        }

        if ((arg_value == nullptr) ||
            (!Sampler::IsValid(*static_cast<const cl_sampler *>(arg_value))))
        {
            // CL_INVALID_SAMPLER for an argument declared to be of type sampler_t when the
            // specified arg_value is not a valid sampler object.
            return CL_INVALID_SAMPLER;
        }
    }

    // [2/6] Checking for special case for queue type
    if (typeName == "queue_t")
    {

        if (arg_size != sizeof(cl_command_queue))
        {
            //  If the argument is of type queue_t, the arg_size value must be equal to
            //  sizeof(cl_command_queue)
            return CL_INVALID_ARG_SIZE;
        }

        const cl_command_queue queue = *static_cast<const cl_command_queue *>(arg_value);
        if (!CommandQueue::IsValid(queue) || !queue->cast<CommandQueue>().isOnDevice())
        {
            // CL_INVALID_DEVICE_QUEUE for an argument declared to be of type queue_t when the
            // specified arg_value is not a valid device queue object. This error code is missing
            // before version 2.0. For versions before, it will be CL_INVALID_ARG_VALUE if arg_value
            // specified is not a valid value.
            return krnl.getProgram().getContext().getPlatform().isVersionOrNewer(2u, 0u)
                       ? CL_INVALID_DEVICE_QUEUE
                       : CL_INVALID_ARG_VALUE;
        }
    }

    // [3/6] Checking for memory objects (image/buffer) types
    static constexpr std::pair<std::string_view, MemObjectType> imageTypes[] = {
        {"image1d_t", MemObjectType::Image1D},
        {"image2d_t", MemObjectType::Image2D},
        {"image3d_t", MemObjectType::Image3D},
        {"image1d_array_t", MemObjectType::Image1D_Array},
        {"image2d_array_t", MemObjectType::Image2D_Array},
        {"image1d_buffer_t", MemObjectType::Image1D_Buffer},
    };

    for (const auto &entry : imageTypes)
    {
        if (typeName == entry.first)
        {
            const cl_mem image = *static_cast<const cl_mem *>(arg_value);
            if (!Image::IsValid(image) || image->cast<Image>().getType() != entry.second)
            {
                // CL_INVALID_MEM_OBJECT for an argument declared to be a memory object
                // when the specified arg_value is not a valid memory object.
                return CL_INVALID_MEM_OBJECT;
            }

            if (arg_size != sizeof(cl_mem))
            {
                // if the argument is a memory object and arg_size != sizeof(cl_mem)
                return CL_INVALID_ARG_SIZE;
            }

            break;
        }
    }

    // [4/6] Now check when argument is declared with the local qualifier
    if (krnl.getInfo().args[arg_index].addressQualifier == CL_KERNEL_ARG_ADDRESS_LOCAL)
    {
        // CL_INVALID_ARG_SIZE if arg_size is zero and the argument is declared with the
        // local qualifier
        if (arg_size == 0)
        {
            return CL_INVALID_ARG_SIZE;
        }

        // the arg_value entry must be NULL
        if (arg_value != nullptr)
        {
            return CL_INVALID_ARG_VALUE;
        }

        // CL_MAX_SIZE_RESTRICTION_EXCEEDED if the size in bytes of the memory object (if the
        // argument is a memory object) or arg_size (if the argument is declared with local
        // qualifier) exceeds a language- specified maximum size restriction for this argument, such
        // as the MaxByteOffset SPIR-V decoration. This error code is missing before version 2.2.
        for (const auto &device : krnl.getProgram().getDevices())
        {
            cl_ulong maxLocalMemSize      = 0;
            cl_ulong compiledLocalMemSize = krnl.getImpl().getCompiledLocalMemSize(*device);
            if (ANGLE_UNLIKELY(IsError(device->getImpl<rx::CLDeviceImpl>().getInfoULong(
                    cl::DeviceInfo::LocalMemSize, &maxLocalMemSize))))
            {
                // The implementation shouldn't come this far if device query can report errors.
                ASSERT(false);
            }
            if (arg_size + compiledLocalMemSize > maxLocalMemSize)
            {
                if (krnl.getProgram().getContext().getPlatform().getVersion() >
                    CL_MAKE_VERSION(2, 1, 0))
                {
                    return CL_MAX_SIZE_RESTRICTION_EXCEEDED;
                }
                else
                {
                    return CL_OUT_OF_RESOURCES;
                }
            }
        }
    }
    else
    {
        // [5/6] If arg is not local qualifier, checking for pointer type
        if (typeName.ends_with('*'))
        {
            if (arg_size != sizeof(cl_mem *))
            {
                // The arg_size must be exactly the size of the host-side memory object reference,
                // which is the size of the cl_mem handle itself.
                return CL_INVALID_ARG_SIZE;
            }
        }
    }

    // [6/6] Finally check for non-memory objects, now only POD left.
    static constexpr std::pair<std::string_view, size_t> baseTypeSizes[] = {
        {"bool", sizeof(cl_bool)},   {"char", sizeof(cl_char)},     {"uchar", sizeof(cl_uchar)},
        {"short", sizeof(cl_short)}, {"ushort", sizeof(cl_ushort)}, {"int", sizeof(cl_int)},
        {"uint", sizeof(cl_uint)},   {"long", sizeof(cl_long)},     {"ulong", sizeof(cl_ulong)},
        {"half", sizeof(cl_half)},   {"float", sizeof(cl_float)},   {"double", sizeof(cl_double)},
    };

    // Parse vector suffix (e.g., float4)
    size_t vecWidth     = 1;
    std::string base    = typeName;
    size_t vecSuffixIdx = base.size();
    while (vecSuffixIdx > 0 && std::isdigit(base[vecSuffixIdx - 1]))
    {
        --vecSuffixIdx;
    }

    if (vecSuffixIdx < base.size())
    {
        vecWidth = std::stoul(base.substr(vecSuffixIdx));
        base.resize(vecSuffixIdx);
    }

    // Find the size of this basic data type
    const auto it =
        std::ranges::find_if(baseTypeSizes, [&](const auto &entry) { return entry.first == base; });

    if (it != std::end(baseTypeSizes))
    {
        size_t baseSize = it->second;

        // OpenCL vec3 is padded as vec4
        if (vecWidth == 3)
        {
            vecWidth = 4;
        }

        const size_t destStride = baseSize * vecWidth;

        if (arg_size != destStride)
        {
            // CL_INVALID_ARG_SIZE if arg_size does not match the size of the data type for
            // an argument that is not a memory object
            return CL_INVALID_ARG_SIZE;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateGetKernelInfo(cl_kernel kernel,
                             KernelInfo param_name,
                             size_t param_value_size,
                             const void *param_value,
                             const size_t *param_value_size_ret)
{
    // CL_INVALID_KERNEL if kernel is a not a valid kernel object.
    if (!Kernel::IsValid(kernel))
    {
        return CL_INVALID_KERNEL;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version =
        kernel->cast<Kernel>().getProgram().getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case KernelInfo::Attributes:
            ANGLE_VALIDATE_VERSION(version, 1, 2);
            break;
        case KernelInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_KERNEL if kernel is a not a valid kernel object.
    if (!Kernel::IsValid(kernel))
    {
        return CL_INVALID_KERNEL;
    }
    const Kernel &krnl = kernel->cast<Kernel>();

    const Device *dev = nullptr;
    if (device != nullptr)
    {
        // CL_INVALID_DEVICE if device is not in the list of devices associated with kernel ...
        if (krnl.getProgram().getContext().hasDevice(device))
        {
            dev = &device->cast<Device>();
        }
        else
        {
            return CL_INVALID_DEVICE;
        }
    }
    else
    {
        // or if device is NULL but there is more than one device associated with kernel.
        if (krnl.getProgram().getContext().getDevices().size() == 1u)
        {
            dev = krnl.getProgram().getContext().getDevices().front().get();
        }
        else
        {
            return CL_INVALID_DEVICE;
        }
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = krnl.getProgram().getContext().getPlatform().getInfo().version;
    switch (param_name)
    {
        case KernelWorkGroupInfo::GlobalWorkSize:
            ANGLE_VALIDATE_VERSION(version, 1, 2);
            // CL_INVALID_VALUE if param_name is CL_KERNEL_GLOBAL_WORK_SIZE and
            // device is not a custom device and kernel is not a built-in kernel.
            if (!dev->supportsBuiltInKernel(krnl.getInfo().functionName))
            {
                return CL_INVALID_VALUE;
            }
            break;
        case KernelWorkGroupInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    return CL_SUCCESS;
}

cl_int ValidateWaitForEvents(cl_uint num_events, const cl_event *event_list)
{
    // CL_INVALID_VALUE if num_events is zero or event_list is NULL.
    if (num_events == 0u || event_list == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    const Context *context = nullptr;
    while (num_events-- != 0u)
    {
        // CL_INVALID_EVENT if event objects specified in event_list are not valid event objects.
        if (!Event::IsValid(*event_list))
        {
            return CL_INVALID_EVENT;
        }

        // CL_INVALID_CONTEXT if events specified in event_list do not belong to the same context.
        const Context *eventContext = &(*event_list++)->cast<Event>().getContext();
        if (context == nullptr)
        {
            context = eventContext;
        }
        else if (context != eventContext)
        {
            return CL_INVALID_CONTEXT;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateGetEventInfo(cl_event event,
                            EventInfo param_name,
                            size_t param_value_size,
                            const void *param_value,
                            const size_t *param_value_size_ret)
{
    // CL_INVALID_EVENT if event is a not a valid event object.
    if (!Event::IsValid(event))
    {
        return CL_INVALID_EVENT;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = event->cast<Event>().getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case EventInfo::Context:
            ANGLE_VALIDATE_VERSION(version, 1, 1);
            break;
        case EventInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainEvent(cl_event event)
{
    // CL_INVALID_EVENT if event is not a valid event object.
    return Event::IsValid(event) ? CL_SUCCESS : CL_INVALID_EVENT;
}

cl_int ValidateReleaseEvent(cl_event event)
{
    // CL_INVALID_EVENT if event is not a valid event object.
    return Event::IsValid(event) ? CL_SUCCESS : CL_INVALID_EVENT;
}

cl_int ValidateGetEventProfilingInfo(cl_event event,
                                     ProfilingInfo param_name,
                                     size_t param_value_size,
                                     const void *param_value,
                                     const size_t *param_value_size_ret)
{
    // CL_INVALID_EVENT if event is a not a valid event object.
    if (!Event::IsValid(event))
    {
        return CL_INVALID_EVENT;
    }
    const Event &evt = event->cast<Event>();

    // CL_PROFILING_INFO_NOT_AVAILABLE if event is a user event object,
    if (evt.getCommandType() == CL_COMMAND_USER)
    {
        return CL_PROFILING_INFO_NOT_AVAILABLE;
    }
    // or if the CL_QUEUE_PROFILING_ENABLE flag is not set for the command-queue.
    if (evt.getCommandQueue()->getProperties().excludes(CL_QUEUE_PROFILING_ENABLE))
    {
        return CL_PROFILING_INFO_NOT_AVAILABLE;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    const cl_version version = evt.getContext().getPlatform().getVersion();
    switch (param_name)
    {
        case ProfilingInfo::CommandComplete:
            ANGLE_VALIDATE_VERSION(version, 2, 0);
            break;
        case ProfilingInfo::InvalidEnum:
            return CL_INVALID_VALUE;
        default:
            // All remaining possible values for param_name are valid for all versions.
            break;
    }

    return CL_SUCCESS;
}

cl_int ValidateFlush(cl_command_queue command_queue)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
    if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    return CL_SUCCESS;
}

cl_int ValidateFinish(cl_command_queue command_queue)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
    if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    ANGLE_VALIDATE(ValidateEnqueueBuffer(command_queue->cast<CommandQueue>(), buffer, true, false));

    // CL_INVALID_VALUE if the region being read or written specified
    // by (offset, size) is out of bounds or if ptr is a NULL value.
    if (!buffer->cast<Buffer>().isRegionValid(offset, size) || ptr == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    ANGLE_VALIDATE(ValidateEnqueueBuffer(command_queue->cast<CommandQueue>(), buffer, false, true));

    // CL_INVALID_VALUE if the region being read or written specified
    // by (offset, size) is out of bounds or if ptr is a NULL value.
    if (!buffer->cast<Buffer>().isRegionValid(offset, size) || ptr == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, src_buffer, false, false));
    const Buffer &src = src_buffer->cast<Buffer>();

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, dst_buffer, false, false));
    const Buffer &dst = dst_buffer->cast<Buffer>();

    // CL_INVALID_VALUE if src_offset, dst_offset, size, src_offset + size or dst_offset + size
    // require accessing elements outside the src_buffer and dst_buffer buffer objects respectively.
    if (!src.isRegionValid(src_offset, size) || !dst.isRegionValid(dst_offset, size))
    {
        return CL_INVALID_VALUE;
    }

    // CL_MEM_COPY_OVERLAP if src_buffer and dst_buffer are the same buffer or sub-buffer object
    // and the source and destination regions overlap or if src_buffer and dst_buffer are
    // different sub-buffers of the same associated buffer object and they overlap.
    if ((src.isSubBuffer() ? src.getParent().get() : &src) ==
        (dst.isSubBuffer() ? dst.getParent().get() : &dst))
    {
        // Only sub-buffers have offsets larger than zero
        src_offset += src.getOffset();
        dst_offset += dst.getOffset();

        if (OverlapRegions(src_offset, dst_offset, size))
        {
            return CL_MEM_COPY_OVERLAP;
        }
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    ANGLE_VALIDATE(ValidateEnqueueImage(queue, image, true, false));
    const Image &img = image->cast<Image>();

    ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));
    ANGLE_VALIDATE(ValidateHostRegionForImage(img, region, row_pitch, slice_pitch, ptr));

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    ANGLE_VALIDATE(ValidateEnqueueImage(queue, image, false, true));
    const Image &img = image->cast<Image>();

    ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));
    ANGLE_VALIDATE(
        ValidateHostRegionForImage(img, region, input_row_pitch, input_slice_pitch, ptr));

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    ANGLE_VALIDATE(ValidateEnqueueImage(queue, src_image, false, false));
    const Image &src = src_image->cast<Image>();

    ANGLE_VALIDATE(ValidateEnqueueImage(queue, dst_image, false, false));
    const Image &dst = dst_image->cast<Image>();

    // CL_IMAGE_FORMAT_MISMATCH if src_image and dst_image do not use the same image format.
    if (src.getFormat().image_channel_order != dst.getFormat().image_channel_order ||
        src.getFormat().image_channel_data_type != dst.getFormat().image_channel_data_type)
    {
        return CL_IMAGE_FORMAT_MISMATCH;
    }

    ANGLE_VALIDATE(ValidateImageForDevice(src, queue.getDevice(), src_origin, region));
    ANGLE_VALIDATE(ValidateImageForDevice(dst, queue.getDevice(), dst_origin, region));

    // CL_MEM_COPY_OVERLAP if src_image and dst_image are the same image object
    // and the source and destination regions overlap.
    if (&src == &dst)
    {
        const MemObjectType type = src.getType();
        // Check overlap in first dimension
        if (OverlapRegions(src_origin[0], dst_origin[0], region[0]))
        {
            if (type == MemObjectType::Image1D || type == MemObjectType::Image1D_Buffer)
            {
                return CL_MEM_COPY_OVERLAP;
            }

            // Check overlap in second dimension
            if (OverlapRegions(src_origin[1], dst_origin[1], region[1]))
            {
                if (type == MemObjectType::Image2D || type == MemObjectType::Image1D_Array)
                {
                    return CL_MEM_COPY_OVERLAP;
                }

                // Check overlap in third dimension
                if (OverlapRegions(src_origin[2], dst_origin[2], region[2]))
                {
                    return CL_MEM_COPY_OVERLAP;
                }
            }
        }
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    ANGLE_VALIDATE(ValidateEnqueueImage(queue, src_image, false, false));
    const Image &src = src_image->cast<Image>();

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, dst_buffer, false, false));
    const Buffer &dst = dst_buffer->cast<Buffer>();

    // CL_INVALID_MEM_OBJECT if src_image is a 1D image buffer object created from dst_buffer.
    if (src.getType() == MemObjectType::Image1D_Buffer && src.getParent() == &dst)
    {
        return CL_INVALID_MEM_OBJECT;
    }

    ANGLE_VALIDATE(ValidateImageForDevice(src, queue.getDevice(), src_origin, region));

    // CL_INVALID_VALUE if the region specified by dst_offset and dst_offset + dst_cb
    // refer to a region outside dst_buffer.
    const MemObjectType type = src.getType();
    size_t dst_cb            = src.getElementSize() * region[0];
    if (type != MemObjectType::Image1D && type != MemObjectType::Image1D_Buffer)
    {
        dst_cb *= region[1];
        if (type != MemObjectType::Image2D && type != MemObjectType::Image1D_Array)
        {
            dst_cb *= region[2];
        }
    }
    if (!dst.isRegionValid(dst_offset, dst_cb))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, src_buffer, false, false));
    const Buffer &src = src_buffer->cast<Buffer>();

    ANGLE_VALIDATE(ValidateEnqueueImage(queue, dst_image, false, false));
    const Image &dst = dst_image->cast<Image>();

    // CL_INVALID_MEM_OBJECT if dst_image is a 1D image buffer object created from src_buffer.
    if (dst.getType() == MemObjectType::Image1D_Buffer && dst.getParent() == &src)
    {
        return CL_INVALID_MEM_OBJECT;
    }

    ANGLE_VALIDATE(ValidateImageForDevice(dst, queue.getDevice(), dst_origin, region));

    // CL_INVALID_VALUE if the region specified by src_offset and src_offset + src_cb
    // refer to a region outside src_buffer.
    const MemObjectType type = dst.getType();
    size_t src_cb            = dst.getElementSize() * region[0];
    if (type != MemObjectType::Image1D && type != MemObjectType::Image1D_Buffer)
    {
        src_cb *= region[1];
        if (type != MemObjectType::Image2D && type != MemObjectType::Image1D_Array)
        {
            src_cb *= region[2];
        }
    }
    if (!src.isRegionValid(src_offset, src_cb))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    // CL_INVALID_OPERATION if buffer has been created with CL_MEM_HOST_WRITE_ONLY or
    // CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set in map_flags
    // or if buffer has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS
    // and CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is set in map_flags.
    ANGLE_VALIDATE(
        ValidateEnqueueBuffer(queue, buffer, map_flags.intersects(CL_MAP_READ),
                              map_flags.intersects(CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)));

    // CL_INVALID_VALUE if region being mapped given by (offset, size) is out of bounds
    // or if size is 0 or if values specified in map_flags are not valid.
    if (!buffer->cast<Buffer>().isRegionValid(offset, size) || size == 0u ||
        !ValidateMapFlags(map_flags, queue.getContext().getPlatform()))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    // CL_INVALID_OPERATION if image has been created with CL_MEM_HOST_WRITE_ONLY or
    // CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set in map_flags
    // or if image has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS
    // and CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is set in map_flags.
    ANGLE_VALIDATE(
        ValidateEnqueueImage(queue, image, map_flags.intersects(CL_MAP_READ),
                             map_flags.intersects(CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)));
    const Image &img = image->cast<Image>();

    ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));

    // CL_INVALID_VALUE if values specified in map_flags are not valid.
    if (!ValidateMapFlags(map_flags, queue.getContext().getPlatform()))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if image_row_pitch is NULL.
    if (image_row_pitch == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if image is a 3D image, 1D or 2D image array object
    // and image_slice_pitch is NULL.
    if ((img.getType() == MemObjectType::Image3D || img.getType() == MemObjectType::Image1D_Array ||
         img.getType() == MemObjectType::Image2D_Array) &&
        image_slice_pitch == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object or is a pipe object.
    if (!Memory::IsValid(memobj))
    {
        return CL_INVALID_MEM_OBJECT;
    }
    const Memory &memory = memobj->cast<Memory>();
    if (memory.getType() == MemObjectType::Pipe)
    {
        return CL_INVALID_MEM_OBJECT;
    }

    // CL_INVALID_CONTEXT if context associated with command_queue and memobj are not the same.
    if (&queue.getContext() != &memory.getContext())
    {
        return CL_INVALID_CONTEXT;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    const Device &device      = queue.getDevice();

    // CL_INVALID_KERNEL if kernel is not a valid kernel object.
    if (!Kernel::IsValid(kernel))
    {
        return CL_INVALID_KERNEL;
    }
    const Kernel &krnl = kernel->cast<Kernel>();

    // CL_INVALID_CONTEXT if context associated with command_queue and kernel are not the same.
    if (&queue.getContext() != &krnl.getProgram().getContext())
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_WORK_DIMENSION if work_dim is not a valid value.
    if (work_dim == 0u || work_dim > device.getInfo().maxWorkItemSizes.size())
    {
        return CL_INVALID_WORK_DIMENSION;
    }

    // CL_INVALID_GLOBAL_OFFSET if global_work_offset is non-NULL before version 1.1.
    if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u) && global_work_offset != nullptr)
    {
        return CL_INVALID_GLOBAL_OFFSET;
    }

    // CL_INVALID_KERNEL_ARGS if all the kernel arguments have not been set for the kernel
    if (!krnl.areAllArgsSet())
    {
        return CL_INVALID_KERNEL_ARGS;
    }

    size_t compileWorkGroupSize[3] = {0, 0, 0};
    if (IsError(krnl.getWorkGroupInfo(const_cast<cl_device_id>(device.getNative()),
                                      KernelWorkGroupInfo::CompileWorkGroupSize,
                                      sizeof(compileWorkGroupSize), compileWorkGroupSize, nullptr)))
    {
        return CL_INVALID_VALUE;
    }
    if (local_work_size != nullptr)
    {
        // CL_INVALID_WORK_GROUP_SIZE when non-uniform work-groups are not supported, the size of
        // each work-group must be uniform. If local_work_size is specified, the values specified in
        // global_work_size[0],...,global_work_size[work_dim - 1] must be evenly divisible by
        // the corresponding values specified in local_work_size[0],...,
        // local_work_size[work_dim-1].
        if (!device.supportsNonUniformWorkGroups())
        {
            for (cl_uint i = 0; i < work_dim; ++i)
            {
                if (global_work_size[i] % local_work_size[i] != 0)
                {
                    return CL_INVALID_WORK_GROUP_SIZE;
                }
            }
        }

        for (cl_uint i = 0; i < work_dim; ++i)
        {
            // CL_INVALID_WORK_GROUP_SIZE when non-uniform work-groups are not supported, the size
            // of each work-group must be uniform. If local_work_size is specified, the values
            // specified in global_work_size[0],..., global_work_size[work_dim - 1] must be
            // evenly divisible by the corresponding values specified in local_work_size[0],...,
            // local_work_size[work_dim-1].
            if (local_work_size[i] == 0)
            {
                return CL_INVALID_WORK_GROUP_SIZE;
            }

            // CL_INVALID_WORK_GROUP_SIZE if local_work_size is specified and does not match the
            // required work-group size for kernel in the program source.
            if (compileWorkGroupSize[i] != 0 && local_work_size[i] != compileWorkGroupSize[i])
            {
                return CL_INVALID_WORK_GROUP_SIZE;
            }
        }
    }

    // CL_INVALID_GLOBAL_WORK_SIZE if global_work_size is NULL or if any of the values
    // specified in global_work_size[0] ... global_work_size[work_dim - 1] are 0.
    // Returning this error code under these circumstances is deprecated by version 2.1.
    if (!queue.getContext().getPlatform().isVersionOrNewer(2u, 1u))
    {
        if (global_work_size == nullptr)
        {
            return CL_INVALID_GLOBAL_WORK_SIZE;
        }
        for (cl_uint dim = 0u; dim < work_dim; ++dim)
        {
            if (global_work_size[dim] == 0u)
            {
                return CL_INVALID_GLOBAL_WORK_SIZE;
            }
        }
    }

    // CL_INVALID_GLOBAL_WORK_SIZE if any of the values specified in global_work_size[0], ...
    // global_work_size[work_dim - 1] exceed the maximum value representable by size_t on the device
    // on which the kernel-instance will be enqueued.
    if (global_work_size != nullptr)
    {
        for (cl_uint dim = 0u; dim < work_dim; ++dim)
        {
            if (global_work_size[dim] > UINT32_MAX)
            {
                // Set hard limit in ANGLE to 2^32 for all backends (regardless of device support).
                return CL_INVALID_GLOBAL_WORK_SIZE;
            }
        }
    }

    // CL_INVALID_GLOBAL_OFFSET if the value specified in global_work_size + the corresponding
    // values in global_work_offset for any dimensions is greater than the maximum value
    // representable by size t on the device on which the kernel-instance will be enqueued
    if (global_work_offset != nullptr)
    {
        for (cl_uint dim = 0u; dim < work_dim; ++dim)
        {
            if (static_cast<uint32_t>((global_work_offset[dim] + global_work_size[dim])) <
                global_work_offset[dim])
            {
                // Set hard limit in ANGLE to 2^32 for all backends (regardless of device support).
                return CL_INVALID_GLOBAL_OFFSET;
            }
        }
    }

    if (local_work_size != nullptr)
    {
        size_t numWorkItems = 1u;  // Initialize with neutral element for multiplication

        // CL_INVALID_WORK_ITEM_SIZE if the number of work-items specified
        // in any of local_work_size[0] ... local_work_size[work_dim - 1]
        // is greater than the corresponding values specified by
        // CL_DEVICE_MAX_WORK_ITEM_SIZES[0] ... CL_DEVICE_MAX_WORK_ITEM_SIZES[work_dim - 1].
        for (cl_uint dim = 0u; dim < work_dim; ++dim)
        {
            if (local_work_size[dim] > device.getInfo().maxWorkItemSizes[dim])
            {
                return CL_INVALID_WORK_ITEM_SIZE;
            }
            numWorkItems *= local_work_size[dim];
        }

        // CL_INVALID_WORK_GROUP_SIZE if local_work_size is specified
        // and the total number of work-items in the work-group computed as
        // local_work_size[0] x ... local_work_size[work_dim - 1] is greater than the value
        // specified by CL_KERNEL_WORK_GROUP_SIZE in the Kernel Object Device Queries table.
        if (numWorkItems > krnl.getInfo().workGroups[queue.getDeviceIndex()].workGroupSize)
        {
            return CL_INVALID_WORK_GROUP_SIZE;
        }
    }

    cl_ulong localMemSize    = 0;
    cl_ulong maxLocalMemSize = 0;
    if (ANGLE_UNLIKELY(
            IsError(krnl.getWorkGroupInfo(const_cast<cl_device_id>(device.getNative()),
                                          cl::KernelWorkGroupInfo::LocalMemSize,
                                          sizeof(localMemSize), &localMemSize, nullptr)) ||
            IsError(device.getImpl<rx::CLDeviceImpl>().getInfoULong(cl::DeviceInfo::LocalMemSize,
                                                                    &maxLocalMemSize))))
    {
        // The implementation shouldn't come this far if device query can report errors.
        ASSERT(false);
    }
    if (localMemSize > maxLocalMemSize)
    {
        ERR() << "Kernel exceeds the maximum local mem size capability";
        return CL_OUT_OF_RESOURCES;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();

    // CL_INVALID_OPERATION if the device associated with command_queue
    // cannot execute the native kernel.
    if (queue.getDevice().getInfo().execCapabilities.excludes(CL_EXEC_NATIVE_KERNEL))
    {
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_VALUE if user_func is NULL.
    if (user_func == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    if (args == nullptr)
    {
        // CL_INVALID_VALUE if args is a NULL value and cb_args > 0 or num_mem_objects > 0.
        if (cb_args > 0u || num_mem_objects > 0u)
        {
            return CL_INVALID_VALUE;
        }
    }
    else
    {
        // CL_INVALID_VALUE if args is not NULL and cb_args is 0.
        if (cb_args == 0u)
        {
            return CL_INVALID_VALUE;
        }
    }

    if (num_mem_objects == 0u)
    {
        // CL_INVALID_VALUE if num_mem_objects = 0 and mem_list or args_mem_loc are not NULL.
        if (mem_list != nullptr || args_mem_loc != nullptr)
        {
            return CL_INVALID_VALUE;
        }
    }
    else
    {
        // CL_INVALID_VALUE if num_mem_objects > 0 and mem_list or args_mem_loc are NULL.
        if (mem_list == nullptr || args_mem_loc == nullptr)
        {
            return CL_INVALID_VALUE;
        }

        // CL_INVALID_MEM_OBJECT if one or more memory objects
        // specified in mem_list are not valid or are not buffer objects.
        while (num_mem_objects-- != 0u)
        {
            if (!Buffer::IsValid(*mem_list++))
            {
                return CL_INVALID_MEM_OBJECT;
            }
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateSetCommandQueueProperty(cl_command_queue command_queue,
                                       CommandQueueProperties properties,
                                       cl_bool enable,
                                       const cl_command_queue_properties *old_properties)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
    if (!CommandQueue::IsValid(command_queue))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    // CL_INVALID_VALUE if values specified in properties are not valid.
    if (properties.hasOtherBitsThan(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
                                    CL_QUEUE_PROFILING_ENABLE))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    const cl_image_desc desc = {CL_MEM_OBJECT_IMAGE2D, image_width, image_height, 0u, 0u,
                                image_row_pitch,       0u,          0u,           0u, {nullptr}};
    return ValidateCreateImage(context, flags, image_format, &desc, host_ptr);
}

cl_int 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)
{
    const cl_image_desc desc = {
        CL_MEM_OBJECT_IMAGE3D, image_width,       image_height, image_depth, 0u,
        image_row_pitch,       image_slice_pitch, 0u,           0u,          {nullptr}};
    return ValidateCreateImage(context, flags, image_format, &desc, host_ptr);
}

cl_int ValidateEnqueueMarker(cl_command_queue command_queue, const cl_event *event)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
    if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    // CL_INVALID_VALUE if event is NULL.
    if (event == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateEnqueueWaitForEvents(cl_command_queue command_queue,
                                    cl_uint num_events,
                                    const cl_event *event_list)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
    if (!CommandQueue::IsValid(command_queue))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    if (!queue.isOnHost())
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    // CL_INVALID_VALUE if num_events is 0 or event_list is NULL.
    if (num_events == 0u || event_list == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    while (num_events-- != 0u)
    {
        // The documentation for invalid events is missing.
        if (!Event::IsValid(*event_list))
        {
            return CL_INVALID_VALUE;
        }

        // CL_INVALID_CONTEXT if context associated with command_queue
        // and events in event_list are not the same.
        if (&queue.getContext() != &(*event_list++)->cast<Event>().getContext())
        {
            return CL_INVALID_CONTEXT;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateEnqueueBarrier(cl_command_queue command_queue)
{
    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid host command-queue.
    if (!CommandQueue::IsValid(command_queue) || !command_queue->cast<CommandQueue>().isOnHost())
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    return CL_SUCCESS;
}

cl_int ValidateUnloadCompiler()
{
    return CL_SUCCESS;
}

cl_int ValidateGetExtensionFunctionAddress(const char *func_name)
{
    return func_name != nullptr && *func_name != '\0' ? CL_SUCCESS : CL_INVALID_VALUE;
}

cl_int ValidateCreateCommandQueue(cl_context context,
                                  cl_device_id device,
                                  CommandQueueProperties properties)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValid(context))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_DEVICE if device is not a valid device or is not associated with context.
    if (!context->cast<Context>().hasDevice(device))
    {
        return CL_INVALID_DEVICE;
    }

    // CL_INVALID_VALUE if values specified in properties are not valid.
    if (properties.hasOtherBitsThan(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
                                    CL_QUEUE_PROFILING_ENABLE))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_QUEUE_PROPERTIES if values specified in properties are valid but are not supported
    // by the device.
    cl_command_queue_properties supportedQueueProperties;
    angle::Result getInfoResult = device->cast<Device>().getInfo(
        DeviceInfo::QueueOnHostProperties, sizeof(cl_command_queue_properties),
        &supportedQueueProperties, nullptr);
    ASSERT(!IsError(getInfoResult));

    if (properties.hasOtherBitsThan(supportedQueueProperties))
    {
        return CL_INVALID_QUEUE_PROPERTIES;
    }

    return CL_SUCCESS;
}

cl_int ValidateCreateSampler(cl_context context,
                             cl_bool normalized_coords,
                             AddressingMode addressing_mode,
                             FilterMode filter_mode)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValid(context))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_VALUE if addressing_mode, filter_mode, normalized_coords
    // or a combination of these arguements are not valid.
    if ((normalized_coords != CL_FALSE && normalized_coords != CL_TRUE) ||
        addressing_mode == AddressingMode::InvalidEnum || filter_mode == FilterMode::InvalidEnum)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_OPERATION if images are not supported by any device associated with context.
    if (!context->cast<Context>().supportsImages())
    {
        return CL_INVALID_OPERATION;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));

    // CL_INVALID_KERNEL if kernel is not a valid kernel object.
    if (!Kernel::IsValid(kernel))
    {
        return CL_INVALID_KERNEL;
    }

    // CL_INVALID_CONTEXT if context associated with command_queue and kernel are not the same.
    if (&command_queue->cast<CommandQueue>().getContext() !=
        &kernel->cast<Kernel>().getProgram().getContext())
    {
        return CL_INVALID_CONTEXT;
    }

    return CL_SUCCESS;
}

// CL 1.1
cl_int ValidateCreateSubBuffer(cl_mem buffer,
                               MemFlags flags,
                               cl_buffer_create_type buffer_create_type,
                               const void *buffer_create_info)
{
    // CL_INVALID_MEM_OBJECT if buffer is not a valid buffer object or is a sub-buffer object.
    if (!Buffer::IsValid(buffer))
    {
        return CL_INVALID_MEM_OBJECT;
    }
    const Buffer &buf = buffer->cast<Buffer>();
    if (buf.isSubBuffer() || !buf.getContext().getPlatform().isVersionOrNewer(1u, 1u))
    {
        return CL_INVALID_MEM_OBJECT;
    }

    if (!ValidateMemoryFlags(flags, buf.getContext().getPlatform()))
    {
        return CL_INVALID_VALUE;
    }

    const MemFlags bufFlags = buf.getFlags();
    // CL_INVALID_VALUE if buffer was created with CL_MEM_WRITE_ONLY
    // and flags specifies CL_MEM_READ_WRITE or CL_MEM_READ_ONLY,
    if ((bufFlags.intersects(CL_MEM_WRITE_ONLY) &&
         flags.intersects(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY)) ||
        // or if buffer was created with CL_MEM_READ_ONLY
        // and flags specifies CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY,
        (bufFlags.intersects(CL_MEM_READ_ONLY) &&
         flags.intersects(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY)) ||
        // or if flags specifies CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR or CL_MEM_COPY_HOST_PTR.
        flags.intersects(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if buffer was created with CL_MEM_HOST_WRITE_ONLY
    // and flags specify CL_MEM_HOST_READ_ONLY,
    if ((bufFlags.intersects(CL_MEM_HOST_WRITE_ONLY) && flags.intersects(CL_MEM_HOST_READ_ONLY)) ||
        // or if buffer was created with CL_MEM_HOST_READ_ONLY
        // and flags specify CL_MEM_HOST_WRITE_ONLY,
        (bufFlags.intersects(CL_MEM_HOST_READ_ONLY) && flags.intersects(CL_MEM_HOST_WRITE_ONLY)) ||
        // or if buffer was created with CL_MEM_HOST_NO_ACCESS
        // and flags specify CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_WRITE_ONLY.
        (bufFlags.intersects(CL_MEM_HOST_NO_ACCESS) &&
         flags.intersects(CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY)))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if the value specified in buffer_create_type is not valid.
    if (buffer_create_type != CL_BUFFER_CREATE_TYPE_REGION)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if value(s) specified in buffer_create_info
    // (for a given buffer_create_type) is not valid or if buffer_create_info is NULL.
    // CL_INVALID_VALUE if the region specified by the cl_buffer_region structure
    // passed in buffer_create_info is out of bounds in buffer.
    const cl_buffer_region *region = static_cast<const cl_buffer_region *>(buffer_create_info);
    if (region == nullptr || !buf.isRegionValid(*region))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_BUFFER_SIZE if the size field of the cl_buffer_region structure
    // passed in buffer_create_info is 0.
    if (region->size == 0u)
    {
        return CL_INVALID_BUFFER_SIZE;
    }

    // CL_MISALIGNED_SUB_BUFFER_OFFSET when the sub-buffer object is created with an offset that is
    // not aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value (which is in bits!) for devices associated
    // with the context.
    const Memory &memory = buffer->cast<Memory>();
    for (const DevicePtr &device : memory.getContext().getDevices())
    {
        if (region->origin % (device->getInfo().memBaseAddrAlign / CHAR_BIT) != 0)
        {
            return CL_MISALIGNED_SUB_BUFFER_OFFSET;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateSetMemObjectDestructorCallback(cl_mem memobj,
                                              void(CL_CALLBACK *pfn_notify)(cl_mem memobj,
                                                                            void *user_data),
                                              const void *user_data)
{
    // CL_INVALID_MEM_OBJECT if memobj is not a valid memory object.
    if (!Memory::IsValid(memobj))
    {
        return CL_INVALID_MEM_OBJECT;
    }

    // CL_INVALID_VALUE if pfn_notify is NULL.
    if (pfn_notify == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateCreateUserEvent(cl_context context)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    return Context::IsValidAndVersionOrNewer(context, 1u, 1u) ? CL_SUCCESS : CL_INVALID_CONTEXT;
}

cl_int ValidateSetUserEventStatus(cl_event event, cl_int execution_status)
{
    // CL_INVALID_EVENT if event is not a valid user event object.
    if (!Event::IsValid(event))
    {
        return CL_INVALID_EVENT;
    }
    const Event &evt = event->cast<Event>();
    if (!evt.getContext().getPlatform().isVersionOrNewer(1u, 1u) ||
        evt.getCommandType() != CL_COMMAND_USER)
    {
        return CL_INVALID_EVENT;
    }

    // CL_INVALID_VALUE if the execution_status is not CL_COMPLETE or a negative integer value.
    if (execution_status != CL_COMPLETE && execution_status >= 0)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_OPERATION if the execution_status for event has already been changed
    // by a previous call to clSetUserEventStatus.
    if (evt.wasStatusChanged())
    {
        return CL_INVALID_OPERATION;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_EVENT if event is not a valid event object.
    if (!Event::IsValid(event) ||
        !event->cast<Event>().getContext().getPlatform().isVersionOrNewer(1u, 1u))
    {
        return CL_INVALID_EVENT;
    }

    // CL_INVALID_VALUE if pfn_event_notify is NULL
    // or if command_exec_callback_type is not CL_SUBMITTED, CL_RUNNING, or CL_COMPLETE.
    if (pfn_notify == nullptr ||
        (command_exec_callback_type != CL_SUBMITTED && command_exec_callback_type != CL_RUNNING &&
         command_exec_callback_type != CL_COMPLETE))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, buffer, true, false));
    ANGLE_VALIDATE(ValidateBufferRect(buffer->cast<Buffer>(), buffer_origin, region,
                                      buffer_row_pitch, buffer_slice_pitch));
    ANGLE_VALIDATE(ValidateHostRect(host_origin, region, host_row_pitch, host_slice_pitch, ptr));

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, buffer, false, true));
    ANGLE_VALIDATE(ValidateBufferRect(buffer->cast<Buffer>(), buffer_origin, region,
                                      buffer_row_pitch, buffer_slice_pitch));
    ANGLE_VALIDATE(ValidateHostRect(host_origin, region, host_row_pitch, host_slice_pitch, ptr));

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 1u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, src_buffer, false, false));
    const Buffer &src = src_buffer->cast<Buffer>();

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, dst_buffer, false, false));
    const Buffer &dst = dst_buffer->cast<Buffer>();

    ANGLE_VALIDATE(ValidateBufferRect(src, src_origin, region, src_row_pitch, src_slice_pitch));
    ANGLE_VALIDATE(ValidateBufferRect(dst, dst_origin, region, dst_row_pitch, dst_slice_pitch));

    // CL_INVALID_VALUE if src_buffer and dst_buffer are the same buffer object and src_slice_pitch
    // is not equal to dst_slice_pitch or src_row_pitch is not equal to dst_row_pitch.
    if (&src == &dst && (src_slice_pitch != dst_slice_pitch || src_row_pitch != dst_row_pitch))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

// CL 1.2
cl_int 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)
{
    // CL_INVALID_DEVICE if in_device is not a valid device.
    if (!Device::IsValid(in_device))
    {
        return CL_INVALID_DEVICE;
    }
    const Device &device = in_device->cast<Device>();
    if (!device.isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_DEVICE;
    }

    // CL_INVALID_VALUE if values specified in properties are not valid
    // or if values specified in properties are valid but not supported by the device
    const std::vector<cl_device_partition_property> &devProps =
        device.getInfo().partitionProperties;
    if (properties == nullptr ||
        std::find(devProps.cbegin(), devProps.cend(), *properties) == devProps.cend())
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateRetainDevice(cl_device_id device)
{
    // CL_INVALID_DEVICE if device is not a valid device.
    if (!Device::IsValid(device) || !device->cast<Device>().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_DEVICE;
    }
    return CL_SUCCESS;
}

cl_int ValidateReleaseDevice(cl_device_id device)
{
    // CL_INVALID_DEVICE if device is not a valid device.
    if (!Device::IsValid(device) || !device->cast<Device>().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_DEVICE;
    }
    return CL_SUCCESS;
}

cl_int ValidateCreateImage(cl_context context,
                           MemFlags flags,
                           const cl_image_format *image_format,
                           const cl_image_desc *image_desc,
                           const void *host_ptr)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValidAndVersionOrNewer(context, 1u, 2u))
    {
        return CL_INVALID_CONTEXT;
    }
    const Context &ctx = context->cast<Context>();

    // CL_INVALID_OPERATION if there are no devices in context that support images.
    if (!ctx.supportsImages())
    {
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_VALUE if values specified in flags are not valid.
    if (!ValidateMemoryFlags(flags, ctx.getPlatform()))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if values specified in image_format are not valid
    // or if image_format is NULL.
    if (!IsValidImageFormat(image_format, ctx.getPlatform().getInfo()))
    {
        return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
    }

    // CL_INVALID_IMAGE_DESCRIPTOR if image_desc is NULL.
    if (image_desc == nullptr)
    {
        return CL_INVALID_IMAGE_DESCRIPTOR;
    }

    const size_t elemSize = GetElementSize(*image_format);
    if (elemSize == 0u)
    {
        ASSERT(false);
        ERR() << "Failed to calculate image element size";
        return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
    }
    const size_t rowPitch = image_desc->image_row_pitch != 0u ? image_desc->image_row_pitch
                                                              : image_desc->image_width * elemSize;
    const size_t imageHeight =
        image_desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY ? 1u : image_desc->image_height;
    const size_t sliceSize = imageHeight * rowPitch;

    // CL_INVALID_IMAGE_DESCRIPTOR if values specified in image_desc are not valid.
    const MemObjectType memObjectType = FromCLenum<MemObjectType>(image_desc->image_type);
    switch (memObjectType)
    {
        case MemObjectType::Image1D:
            if (image_desc->image_width == 0u)
            {
                return CL_INVALID_IMAGE_DESCRIPTOR;
            }
            break;
        case MemObjectType::Image2D:
            if (image_desc->image_width == 0u || image_desc->image_height == 0u)
            {
                return CL_INVALID_IMAGE_DESCRIPTOR;
            }
            break;
        case MemObjectType::Image3D:
            if (image_desc->image_width == 0u || image_desc->image_height == 0u ||
                image_desc->image_depth == 0u)
            {
                return CL_INVALID_IMAGE_DESCRIPTOR;
            }
            break;
        case MemObjectType::Image1D_Array:
            if (image_desc->image_width == 0u || image_desc->image_array_size == 0u)
            {
                return CL_INVALID_IMAGE_DESCRIPTOR;
            }
            break;
        case MemObjectType::Image2D_Array:
            if (image_desc->image_width == 0u || image_desc->image_height == 0u ||
                image_desc->image_array_size == 0u)
            {
                return CL_INVALID_IMAGE_DESCRIPTOR;
            }
            break;
        case MemObjectType::Image1D_Buffer:
            if (image_desc->image_width == 0u)
            {
                return CL_INVALID_IMAGE_DESCRIPTOR;
            }
            break;
        default:
            return CL_INVALID_IMAGE_DESCRIPTOR;
    }

    // CL_INVALID_IMAGE_SIZE if image dimensions specified in image_desc exceed the maximum
    // image dimensions described in the Device Queries table for all devices in context.
    const DevicePtrs &devices = ctx.getDevices();
    if (std::find_if(devices.cbegin(), devices.cend(), [&](const DevicePtr &ptr) {
            return ptr->supportsNativeImageDimensions(*image_desc);
        }) == devices.cend())
    {
        return CL_INVALID_IMAGE_SIZE;
    }
    unsigned int maxDeviceImagePitchAlignment = 0u;
    for (const DevicePtr &device : devices)
    {
        maxDeviceImagePitchAlignment =
            std::max(maxDeviceImagePitchAlignment, device->getInfo().imagePitchAlignment);
    }

    // CL_INVALID_OPERATION if no devices in context support creating a 2D image from a
    // buffer.
    const bool isImage2dFromBuffer = image_desc->image_type == CL_MEM_OBJECT_IMAGE2D &&
                                     image_desc->buffer != NULL &&
                                     Buffer::IsValid(image_desc->buffer);
    if (isImage2dFromBuffer && !ctx.supportsImage2DFromBuffer())
    {
        return CL_INVALID_OPERATION;
    }

    if (image_desc->image_row_pitch != 0u)
    {
        // image_row_pitch must be 0 if host_ptr is NULL, and the image is not a 2D image created
        // from a buffer
        if (host_ptr == nullptr && image_desc->buffer == nullptr)
        {
            return CL_INVALID_IMAGE_DESCRIPTOR;
        }
        // image_row_pitch can be either 0
        // or >= image_width * size of element in bytes if host_ptr is not NULL.
        if (image_desc->image_row_pitch < image_desc->image_width * elemSize)
        {
            return CL_INVALID_IMAGE_DESCRIPTOR;
        }
        // If image_row_pitch is not 0, it must be a multiple of the image element size in bytes.
        if ((image_desc->image_row_pitch % elemSize) != 0u)
        {
            return CL_INVALID_IMAGE_DESCRIPTOR;
        }
        // CL_INVALID_IMAGE_FORMAT_DESCRIPTOR
        // if image is being created from buffer, image_row_pitch
        // must be a multiple of the maximum of the CL_DEVICE_IMAGE_PITCH_ALIGNMENT value of all
        // devices in the context that supports images.
        if (isImage2dFromBuffer && image_desc->image_row_pitch % maxDeviceImagePitchAlignment != 0u)
        {
            return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
        }
    }
    if (image_desc->image_slice_pitch != 0u)
    {
        // image_slice_pitch must be 0 if host_ptr is NULL.
        if (host_ptr == nullptr)
        {
            return CL_INVALID_IMAGE_DESCRIPTOR;
        }
        // If host_ptr is not NULL, image_slice_pitch can be either 0
        // or >= image_row_pitch * image_height for a 2D image array or 3D image
        // and can be either 0 or >= image_row_pitch for a 1D image array.
        if (image_desc->image_slice_pitch < sliceSize)
        {
            return CL_INVALID_IMAGE_DESCRIPTOR;
        }
        // If image_slice_pitch is not 0, it must be a multiple of the image_row_pitch.
        if ((image_desc->image_slice_pitch % rowPitch) != 0u)
        {
            return CL_INVALID_IMAGE_DESCRIPTOR;
        }
    }
    // num_mip_levels and num_samples must be 0.
    if (image_desc->num_mip_levels != 0u || image_desc->num_samples != 0u)
    {
        return CL_INVALID_IMAGE_DESCRIPTOR;
    }
    // buffer can be a buffer memory object if image_type is CL_MEM_OBJECT_IMAGE1D_BUFFER or
    // CL_MEM_OBJECT_IMAGE2D. buffer can be an image object if image_type is CL_MEM_OBJECT_IMAGE2D.
    // Otherwise it must be NULL.
    if (image_desc->buffer != nullptr &&
        (!Buffer::IsValid(image_desc->buffer) ||
         (image_desc->image_type != CL_MEM_OBJECT_IMAGE1D_BUFFER &&
          image_desc->image_type != CL_MEM_OBJECT_IMAGE2D)) &&
        (!Image::IsValid(image_desc->buffer) || image_desc->image_type != CL_MEM_OBJECT_IMAGE2D))
    {
        return CL_INVALID_IMAGE_DESCRIPTOR;
    }

    // CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if a 2D image is created from a buffer and the row pitch
    // and base address alignment does not follow the rules described for creating a 2D image from a
    // buffer.
    if (isImage2dFromBuffer && (image_desc->image_row_pitch * image_desc->image_height) >
                                   Buffer::Cast(image_desc->buffer)->getSize())
    {
        return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
    }

    // CL_INVALID_IMAGE_DESCRIPTOR
    // if 2D image created from another image object, the values in
    // image descriptor except for mem_object must match the image descriptor information associated
    // with mem_object
    if (image_desc->mem_object != nullptr && Image::IsValid(image_desc->mem_object))
    {
        const ImageDescriptor imageDesc = {FromCLenum<MemObjectType>(image_desc->image_type),
                                           image_desc->image_width,
                                           image_desc->image_height,
                                           image_desc->image_depth,
                                           image_desc->image_array_size,
                                           image_desc->image_row_pitch,
                                           image_desc->image_slice_pitch,
                                           image_desc->num_mip_levels,
                                           image_desc->num_samples};
        if (imageDesc != Image::Cast(image_desc->mem_object)->getDescriptor())
        {
            return CL_INVALID_IMAGE_DESCRIPTOR;
        }
    }

    // CL_INVALID_HOST_PTR
    // if host_ptr is NULL and CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR are set in flags or
    // if host_ptr is not NULL but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in flags.
    if ((host_ptr != nullptr) != flags.intersects(CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))
    {
        return CL_INVALID_HOST_PTR;
    }

    // CL_IMAGE_FORMAT_NOT_SUPPORTED
    // if there are no devices in context that support image_format
    cl_uint memObjectTypeFormatCount = 0;
    if (IsError(ctx.getSupportedImageFormats(flags, memObjectType, 0, nullptr,
                                             &memObjectTypeFormatCount)))
    {
        return CL_IMAGE_FORMAT_NOT_SUPPORTED;
    }
    std::vector<cl_image_format> supportedFormats;
    supportedFormats.resize(memObjectTypeFormatCount);
    if (ANGLE_UNLIKELY(IsError(ctx.getSupportedImageFormats(
            flags, memObjectType, memObjectTypeFormatCount, supportedFormats.data(), nullptr))))
    {
        return CL_OUT_OF_RESOURCES;
    }
    cl_image_format formatOfInterest = *image_format;
    if (std::find_if(
            supportedFormats.begin(), supportedFormats.end(),
            [&formatOfInterest](const auto &format) {
                return formatOfInterest.image_channel_order == format.image_channel_order &&
                       formatOfInterest.image_channel_data_type == format.image_channel_data_type;
            }) == supportedFormats.end())
    {
        return CL_IMAGE_FORMAT_NOT_SUPPORTED;
    }
    return CL_SUCCESS;
}

cl_int ValidateCreateProgramWithBuiltInKernels(cl_context context,
                                               cl_uint num_devices,
                                               const cl_device_id *device_list,
                                               const char *kernel_names)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValidAndVersionOrNewer(context, 1u, 2u))
    {
        return CL_INVALID_CONTEXT;
    }
    const Context &ctx = context->cast<Context>();

    // CL_INVALID_VALUE if device_list is NULL or num_devices is zero or if kernel_names is NULL.
    if (device_list == nullptr || num_devices == 0u || kernel_names == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_DEVICE if any device in device_list
    // is not in the list of devices associated with context.
    for (size_t index = 0u; index < num_devices; ++index)
    {
        if (!ctx.hasDevice(device_list[index]))
        {
            return CL_INVALID_DEVICE;
        }
    }

    // CL_INVALID_VALUE if kernel_names contains a kernel name
    // that is not supported by any of the devices in device_list.
    const char *start = kernel_names;
    do
    {
        const char *end = start;
        while (*end != '\0' && *end != ';')
        {
            ++end;
        }
        const size_t length = end - start;
        if (length != 0u && !ctx.supportsBuiltInKernel(std::string(start, length)))
        {
            return CL_INVALID_VALUE;
        }
        start = end;
    } while (*start++ != '\0');

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_PROGRAM if program is not a valid program object.
    if (!Program::IsValid(program))
    {
        return CL_INVALID_PROGRAM;
    }
    const Program &prog = program->cast<Program>();
    if (!prog.getContext().getPlatform().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_PROGRAM;
    }

    // CL_INVALID_OPERATION if we do not have source code.
    if (prog.getSource().empty())
    {
        ERR() << "No OpenCL C source available from program object (" << &prog << ")!";
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero,
    // or if device_list is not NULL and num_devices is zero.
    if ((device_list != nullptr) != (num_devices != 0u))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_DEVICE if any device in device_list
    // is not in the list of devices associated with program.
    while (num_devices-- != 0u)
    {
        if (!prog.hasDevice(*device_list++))
        {
            return CL_INVALID_DEVICE;
        }
    }

    // CL_INVALID_VALUE if num_input_headers is zero and header_include_names
    // or input_headers are not NULL
    // or if num_input_headers is not zero and header_include_names or input_headers are NULL.
    if ((num_input_headers != 0u) != (header_include_names != nullptr) ||
        (num_input_headers != 0u) != (input_headers != nullptr))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
    if (pfn_notify == nullptr && user_data != nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_OPERATION if the build of a program executable for any of the devices listed
    // in device_list by a previous call to clBuildProgram for program has not completed.
    if (prog.isBuilding())
    {
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_OPERATION if there are kernel objects attached to program.
    if (prog.hasAttachedKernels())
    {
        return CL_INVALID_OPERATION;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValidAndVersionOrNewer(context, 1u, 2u))
    {
        return CL_INVALID_CONTEXT;
    }
    const Context &ctx = context->cast<Context>();

    // CL_INVALID_OPERATION if the compilation or build of a program executable for any of the
    // devices listed in device_list by a previous call to clCompileProgram or clBuildProgram for
    // program has not completed.
    for (size_t i = 0; i < num_devices; ++i)
    {
        Device &device = device_list[i]->cast<Device>();
        for (size_t j = 0; j < num_input_programs; ++j)
        {
            cl_build_status buildStatus = CL_BUILD_NONE;
            Program &program            = input_programs[j]->cast<Program>();
            if (IsError(program.getBuildInfo(device.getNative(), ProgramBuildInfo::Status,
                                             sizeof(cl_build_status), &buildStatus, nullptr)))
            {
                return CL_INVALID_PROGRAM;
            }

            if (buildStatus != CL_BUILD_SUCCESS)
            {
                return CL_INVALID_OPERATION;
            }
        }
    }

    // CL_INVALID_OPERATION if the rules for devices containing compiled binaries or libraries as
    // described in input_programs argument below are not followed.
    //
    // All programs specified by input_programs contain a compiled binary or library for the device.
    // In this case, a link is performed to generate a program executable for this device.
    //
    // None of the programs contain a compiled binary or library for that device. In this case, no
    // link is performed and there will be no program executable generated for this device.
    //
    // All other cases will return a CL_INVALID_OPERATION error.
    BitField libraryOrObject(CL_PROGRAM_BINARY_TYPE_LIBRARY |
                             CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT);
    for (size_t i = 0; i < num_devices; ++i)
    {
        bool foundAnyLibraryOrObject = false;
        Device &device               = device_list[i]->cast<Device>();
        for (size_t j = 0; j < num_input_programs; ++j)
        {
            cl_program_binary_type binaryType = CL_PROGRAM_BINARY_TYPE_NONE;
            Program &program                  = input_programs[j]->cast<Program>();
            if (IsError(program.getBuildInfo(device.getNative(), ProgramBuildInfo::BinaryType,
                                             sizeof(cl_program_binary_type), &binaryType, nullptr)))
            {
                return CL_INVALID_PROGRAM;
            }

            if (libraryOrObject.excludes(binaryType))
            {
                if (foundAnyLibraryOrObject)
                {
                    return CL_INVALID_OPERATION;
                }
            }
            else
            {
                foundAnyLibraryOrObject = true;
            }
        }
    }

    // CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero,
    // or if device_list is not NULL and num_devices is zero.
    if ((device_list != nullptr) != (num_devices != 0u))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_DEVICE if any device in device_list
    // is not in the list of devices associated with context.
    while (num_devices-- != 0u)
    {
        if (!ctx.hasDevice(*device_list++))
        {
            return CL_INVALID_DEVICE;
        }
    }

    // CL_INVALID_VALUE if num_input_programs is zero or input_programs is NULL.
    if (num_input_programs == 0u || input_programs == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_PROGRAM if programs specified in input_programs are not valid program objects.
    while (num_input_programs-- != 0u)
    {
        if (!Program::IsValid(*input_programs++))
        {
            return CL_INVALID_PROGRAM;
        }
    }

    // CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
    if (pfn_notify == nullptr && user_data != nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateUnloadPlatformCompiler(cl_platform_id platform)
{
    // CL_INVALID_PLATFORM if platform is not a valid platform.
    if (!Platform::IsValid(platform) || !platform->cast<Platform>().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_PLATFORM;
    }
    return CL_SUCCESS;
}

cl_int 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)
{
    // CL_INVALID_KERNEL if kernel is a not a valid kernel object.
    if (!Kernel::IsValid(kernel))
    {
        return CL_INVALID_KERNEL;
    }
    const Kernel &krnl = kernel->cast<Kernel>();
    if (!krnl.getProgram().getContext().getPlatform().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_KERNEL;
    }

    // CL_INVALID_ARG_INDEX if arg_index is not a valid argument index.
    if (arg_index >= krnl.getInfo().args.size())
    {
        return CL_INVALID_ARG_INDEX;
    }

    // CL_KERNEL_ARG_INFO_NOT_AVAILABLE if the argument information is not available for kernel.
    if (!krnl.getInfo().args[arg_index].isAvailable())
    {
        return CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
    }

    // CL_INVALID_VALUE if param_name is not valid.
    if (param_name == KernelArgInfo::InvalidEnum)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    ANGLE_VALIDATE(ValidateEnqueueBuffer(queue, buffer, false, false));

    // CL_INVALID_VALUE if offset or offset + size require accessing
    // elements outside the buffer object respectively.
    if (!buffer->cast<Buffer>().isRegionValid(offset, size))
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if pattern is NULL or if pattern_size is 0 or
    // if pattern_size is not one of { 1, 2, 4, 8, 16, 32, 64, 128 }.
    if (pattern == nullptr || pattern_size == 0u || pattern_size > 128u ||
        (pattern_size & (pattern_size - 1u)) != 0u)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_VALUE if offset and size are not a multiple of pattern_size.
    if ((offset % pattern_size) != 0u || (size % pattern_size) != 0u)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, true,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    ANGLE_VALIDATE(ValidateEnqueueImage(queue, image, false, false));
    const Image &img = image->cast<Image>();

    ANGLE_VALIDATE(ValidateImageForDevice(img, queue.getDevice(), origin, region));

    // CL_INVALID_VALUE if fill_color is NULL.
    if (fill_color == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    const CommandQueue &queue = command_queue->cast<CommandQueue>();
    if (!queue.getContext().getPlatform().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    // CL_INVALID_VALUE if num_mem_objects is zero or if mem_objects is NULL.
    if (num_mem_objects == 0u || mem_objects == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    while (num_mem_objects-- != 0u)
    {
        // CL_INVALID_MEM_OBJECT if any of the memory objects
        // in mem_objects is not a valid memory object.
        if (!Memory::IsValid(*mem_objects))
        {
            return CL_INVALID_MEM_OBJECT;
        }

        // CL_INVALID_CONTEXT if the context associated with command_queue
        // and memory objects in mem_objects are not the same.
        if (&queue.getContext() != &(*mem_objects++)->cast<Memory>().getContext())
        {
            return CL_INVALID_CONTEXT;
        }
    }

    // CL_INVALID_VALUE if flags is not 0 or is not any of the values described in the table.
    const MemMigrationFlags allowedFlags(CL_MIGRATE_MEM_OBJECT_HOST |
                                         CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED);
    if (flags.hasOtherBitsThan(allowedFlags))
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateEnqueueMarkerWithWaitList(cl_command_queue command_queue,
                                         cl_uint num_events_in_wait_list,
                                         const cl_event *event_wait_list,
                                         const cl_event *event)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    if (!command_queue->cast<CommandQueue>().getContext().getPlatform().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    return CL_SUCCESS;
}

cl_int ValidateEnqueueBarrierWithWaitList(cl_command_queue command_queue,
                                          cl_uint num_events_in_wait_list,
                                          const cl_event *event_wait_list,
                                          const cl_event *event)
{
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    if (!command_queue->cast<CommandQueue>().getContext().getPlatform().isVersionOrNewer(1u, 2u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }
    return CL_SUCCESS;
}

cl_int ValidateGetExtensionFunctionAddressForPlatform(cl_platform_id platform,
                                                      const char *func_name)
{
    if (!Platform::IsValid(platform) || func_name == nullptr || *func_name == '\0')
    {
        return CL_INVALID_VALUE;
    }
    return CL_SUCCESS;
}

// CL 2.0
cl_int ValidateCreateCommandQueueWithProperties(cl_context context,
                                                cl_device_id device,
                                                const cl_queue_properties *properties)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValidAndVersionOrNewer(context, 2u, 0u))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_DEVICE if device is not a valid device or is not associated with context.
    if (!context->cast<Context>().hasDevice(device) ||
        !device->cast<Device>().isVersionOrNewer(2u, 0u))
    {
        return CL_INVALID_DEVICE;
    }

    // CL_INVALID_VALUE if values specified in properties are not valid.
    if (properties != nullptr)
    {
        cl_command_queue_properties supportedQueueProperties;
        angle::Result getInfoResult = device->cast<Device>().getInfo(
            DeviceInfo::QueueOnHostProperties, sizeof(cl_command_queue_properties),
            &supportedQueueProperties, nullptr);
        ASSERT(!IsError(getInfoResult));

        bool isQueueOnDevice  = false;
        bool hasQueueSize     = false;
        bool hasQueuePriority = false;
        while (*properties != 0)
        {
            switch (*properties++)
            {
                case CL_QUEUE_PROPERTIES:
                {
                    const CommandQueueProperties props(*properties++);
                    const CommandQueueProperties validProps(
                        CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE |
                        CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT);
                    if (props.hasOtherBitsThan(validProps) ||
                        // If CL_QUEUE_ON_DEVICE is set, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
                        // must also be set.
                        (props.intersects(CL_QUEUE_ON_DEVICE) &&
                         !props.intersects(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)) ||
                        // CL_QUEUE_ON_DEVICE_DEFAULT can only be used with CL_QUEUE_ON_DEVICE.
                        (props.intersects(CL_QUEUE_ON_DEVICE_DEFAULT) &&
                         !props.intersects(CL_QUEUE_ON_DEVICE)))
                    {
                        return CL_INVALID_VALUE;
                    }

                    // CL_INVALID_QUEUE_PROPERTIES if values specified in properties are valid but
                    // are not supported by the device.
                    if (props.hasOtherBitsThan(supportedQueueProperties))
                    {
                        return CL_INVALID_QUEUE_PROPERTIES;
                    }

                    isQueueOnDevice = props.intersects(CL_QUEUE_ON_DEVICE);
                    break;
                }
                case CL_QUEUE_SIZE:
                {
                    // CL_QUEUE_SIZE must be a value <= CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE.
                    if (*properties++ > device->cast<Device>().getInfo().queueOnDeviceMaxSize)
                    {
                        return CL_INVALID_VALUE;
                    }
                    hasQueueSize = true;
                    break;
                }
                case CL_QUEUE_PRIORITY_KHR:
                {
                    if (*properties != CL_QUEUE_PRIORITY_HIGH_KHR &&
                        *properties != CL_QUEUE_PRIORITY_MED_KHR &&
                        *properties != CL_QUEUE_PRIORITY_LOW_KHR)
                    {
                        return CL_INVALID_VALUE;
                    }
                    hasQueuePriority = true;
                    properties++;
                    break;
                }
                default:
                    return CL_INVALID_VALUE;
            }
        }

        // CL_QUEUE_SIZE can only be specified if CL_QUEUE_ON_DEVICE is set in CL_QUEUE_PROPERTIES.
        if (hasQueueSize && !isQueueOnDevice)
        {
            return CL_INVALID_VALUE;
        }

        // CL_INVALID_QUEUE_PROPERTIES if the cl_khr_priority_hints extension is supported, the
        // CL_QUEUE_PRIORITY_KHR property is specified, and the queue is a CL_QUEUE_ON_DEVICE.
        if (device->cast<Device>().getInfo().khrPriorityHints && hasQueuePriority &&
            isQueueOnDevice)
        {
            return CL_INVALID_QUEUE_PROPERTIES;
        }
    }

    return CL_SUCCESS;
}

cl_int ValidateCreatePipe(cl_context context,
                          MemFlags flags,
                          cl_uint pipe_packet_size,
                          cl_uint pipe_max_packets,
                          const cl_pipe_properties *properties)
{
    return CL_SUCCESS;
}

cl_int ValidateGetPipeInfo(cl_mem pipe,
                           PipeInfo param_name,
                           size_t param_value_size,
                           const void *param_value,
                           const size_t *param_value_size_ret)
{
    return CL_SUCCESS;
}

cl_int ValidateSVMAlloc(cl_context context, SVM_MemFlags flags, size_t size, cl_uint alignment)
{
    return CL_SUCCESS;
}

cl_int ValidateSVMFree(cl_context context, const void *svm_pointer)
{
    return CL_SUCCESS;
}

cl_int ValidateCreateSamplerWithProperties(cl_context context,
                                           const cl_sampler_properties *sampler_properties)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValidAndVersionOrNewer(context, 2u, 0u))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_VALUE if the property name in sampler_properties is not a supported property name,
    // if the value specified for a supported property name is not valid,
    // or if the same property name is specified more than once.
    if (sampler_properties != nullptr)
    {
        bool hasNormalizedCoords            = false;
        bool hasAddressingMode              = false;
        bool hasFilterMode                  = false;
        const cl_sampler_properties *propIt = sampler_properties;
        while (*propIt != 0)
        {
            switch (*propIt++)
            {
                case CL_SAMPLER_NORMALIZED_COORDS:
                    if (hasNormalizedCoords || (*propIt != CL_FALSE && *propIt != CL_TRUE))
                    {
                        return CL_INVALID_VALUE;
                    }
                    hasNormalizedCoords = true;
                    ++propIt;
                    break;
                case CL_SAMPLER_ADDRESSING_MODE:
                    if (hasAddressingMode || FromCLenum<AddressingMode>(static_cast<CLenum>(
                                                 *propIt++)) == AddressingMode::InvalidEnum)
                    {
                        return CL_INVALID_VALUE;
                    }
                    hasAddressingMode = true;
                    break;
                case CL_SAMPLER_FILTER_MODE:
                    if (hasFilterMode || FromCLenum<FilterMode>(static_cast<CLenum>(*propIt++)) ==
                                             FilterMode::InvalidEnum)
                    {
                        return CL_INVALID_VALUE;
                    }
                    hasFilterMode = true;
                    break;
                default:
                    return CL_INVALID_VALUE;
            }
        }
    }

    // CL_INVALID_OPERATION if images are not supported by any device associated with context.
    if (!context->cast<Context>().supportsImages())
    {
        return CL_INVALID_OPERATION;
    }

    return CL_SUCCESS;
}

cl_int ValidateSetKernelArgSVMPointer(cl_kernel kernel, cl_uint arg_index, const void *arg_value)
{
    return CL_SUCCESS;
}

cl_int ValidateSetKernelExecInfo(cl_kernel kernel,
                                 KernelExecInfo param_name,
                                 size_t param_value_size,
                                 const void *param_value)
{
    return CL_SUCCESS;
}

cl_int 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)
{
    return CL_SUCCESS;
}

cl_int 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)
{
    return CL_SUCCESS;
}

cl_int 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)
{
    return CL_SUCCESS;
}

cl_int 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)
{
    return CL_SUCCESS;
}

cl_int 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)
{
    return CL_SUCCESS;
}

// CL 2.1
cl_int ValidateSetDefaultDeviceCommandQueue(cl_context context,
                                            cl_device_id device,
                                            cl_command_queue command_queue)
{
    return CL_SUCCESS;
}

cl_int ValidateGetDeviceAndHostTimer(cl_device_id device,
                                     const cl_ulong *device_timestamp,
                                     const cl_ulong *host_timestamp)
{
    return CL_SUCCESS;
}

cl_int ValidateGetHostTimer(cl_device_id device, const cl_ulong *host_timestamp)
{
    return CL_SUCCESS;
}

cl_int ValidateCreateProgramWithIL(cl_context context, const void *il, size_t length)
{
    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!Context::IsValidAndVersionOrNewer(context, 2u, 1u))
    {
        return CL_INVALID_CONTEXT;
    }
    const Context &ctx = context->cast<Context>();

    // CL_INVALID_OPERATION if no devices in context support intermediate language programs.
    if (!ctx.supportsIL())
    {
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_VALUE if il is NULL or if length is zero.
    if (il == nullptr || length == 0u)
    {
        return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int ValidateCloneKernel(cl_kernel source_kernel)
{
    if (!Kernel::IsValid(source_kernel))
    {
        return CL_INVALID_KERNEL;
    }
    return CL_SUCCESS;
}

cl_int 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)
{
    if (!Kernel::IsValid(kernel))
    {
        // CL_INVALID_KERNEL if kernel is a not a valid kernel object.
        return CL_INVALID_KERNEL;
    }
    const Kernel &krnl = kernel->cast<Kernel>();

    if (!krnl.getProgram().hasDevice(device) ||
        (device == nullptr && krnl.getProgram().getDevices().size() > 1))
    {
        // CL_INVALID_DEVICE if device is not in the list of devices associated with kernel or if
        // device is NULL but there is more than one device associated with kernel.
        return CL_INVALID_DEVICE;
    }

    if (Device::IsValid(device) && !device->cast<Device>().getInfo().khrSubgroups)
    {
        // CL_INVALID_OPERATION if device does not support sub-groups.
        return CL_INVALID_OPERATION;
    }

    // CL_INVALID_VALUE if the size in bytes specified by param_value_size is less than
    // size of the return type specified in the Kernel Object Sub-group Queries table
    // and param_value is not NULL.
    size_t maxWorkItemDimensions = 0;
    angle::Result getInfoResult  = device->cast<Device>().getInfo(
        DeviceInfo::MaxWorkItemDimensions, sizeof(size_t), &maxWorkItemDimensions, nullptr);
    ASSERT(!IsError(getInfoResult));  // MaxWorkItemDimensions is always handled
    switch (param_name)
    {
        case KernelSubGroupInfo::SubGroupCountForNdrange:
        case KernelSubGroupInfo::MaxSubGroupSizeForNdrange:
            if (param_value_size < sizeof(size_t))
            {
                return CL_INVALID_VALUE;
            }
            break;
        case KernelSubGroupInfo::LocalSizeForSubGroupCount:
        {
            const size_t dims     = param_value_size / sizeof(size_t);
            const bool isMultiple = (param_value_size % sizeof(size_t) == 0);
            if (!param_value || !isMultiple || dims > maxWorkItemDimensions)
            {
                return CL_INVALID_VALUE;
            }
            break;
        }
        default:
            break;
    }

    switch (param_name)
    {
        case KernelSubGroupInfo::SubGroupCountForNdrange:
        case KernelSubGroupInfo::LocalSizeForSubGroupCount:
        case KernelSubGroupInfo::MaxSubGroupSizeForNdrange:
            if (input_value == nullptr)
            {
                // CL_INVALID_VALUE if input_value is NULL
                return CL_INVALID_VALUE;
            }

            if (param_name == KernelSubGroupInfo::LocalSizeForSubGroupCount)
            {
                if (input_value_size != sizeof(size_t))
                {
                    // CL_INVALID_VALUE if param_name is CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT
                    // and the size in bytes specified by input_value_size is not valid
                    return CL_INVALID_VALUE;
                }
            }
            else
            {
                const size_t dims     = input_value_size / sizeof(size_t);
                const bool isMultiple = (input_value_size % sizeof(size_t) == 0);
                if (!isMultiple || dims == 0 || dims > maxWorkItemDimensions)
                {
                    // CL_INVALID_VALUE if param_name is CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE,
                    // CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE and the size in bytes specified by
                    // input_value_size is not valid
                    return CL_INVALID_VALUE;
                }
            }
            break;
        default:
            // CL_INVALID_VALUE if param_name is not one of the supported values
            return CL_INVALID_VALUE;
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    return CL_SUCCESS;
}

// CL 2.2
cl_int ValidateSetProgramReleaseCallback(cl_program program,
                                         void(CL_CALLBACK *pfn_notify)(cl_program program,
                                                                       void *user_data),
                                         const void *user_data)
{
    return CL_SUCCESS;
}

cl_int ValidateSetProgramSpecializationConstant(cl_program program,
                                                cl_uint spec_id,
                                                size_t spec_size,
                                                const void *spec_value)
{
    return CL_SUCCESS;
}

// CL 3.0
cl_int ValidateSetContextDestructorCallback(cl_context context,
                                            void(CL_CALLBACK *pfn_notify)(cl_context context,
                                                                          void *user_data),
                                            const void *user_data)
{
    return CL_SUCCESS;
}

cl_int ValidateCreateBufferWithProperties(cl_context context,
                                          const cl_mem_properties *properties,
                                          MemFlags flags,
                                          size_t size,
                                          const void *host_ptr)
{
    ANGLE_VALIDATE(ValidateCreateBuffer(context, flags, size, host_ptr));

    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!context->cast<Context>().getPlatform().isVersionOrNewer(3u, 0u))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_PROPERTY if a property name in properties is not a supported property name,
    // if the value specified for a supported property name is not valid,
    // or if the same property name is specified more than once.
    if ((properties != nullptr) && (properties[0] != 0))
    {
        return ValidateMemoryProperties(context, flags, properties, host_ptr);
    }

    return CL_SUCCESS;
}

cl_int 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)
{
    ANGLE_VALIDATE(ValidateCreateImage(context, flags, image_format, image_desc, host_ptr));

    // CL_INVALID_CONTEXT if context is not a valid context.
    if (!context->cast<Context>().getPlatform().isVersionOrNewer(3u, 0u))
    {
        return CL_INVALID_CONTEXT;
    }

    // CL_INVALID_PROPERTY if a property name in properties is not a supported property name,
    // if the value specified for a supported property name is not valid,
    // or if the same property name is specified more than once.
    if ((properties != nullptr) && (properties[0] != 0))
    {
        return ValidateMemoryProperties(context, flags, properties, host_ptr);
    }

    return CL_SUCCESS;
}

// cl_khr_external_memory
cl_int ValidateExternalMemObjectsKHR(cl_command_queue command_queue,
                                     cl_uint num_mem_objects,
                                     const cl_mem *mem_objects,
                                     cl_uint num_events_in_wait_list,
                                     const cl_event *event_wait_list)
{
    // CL_INVALID_VALUE if num_mem_objects is zero and mem_objects is not a NULL value,
    // or if num_mem_objects is greater than 0 and mem_objects is NULL.
    if ((num_mem_objects == 0u && mem_objects != nullptr) ||
        (num_mem_objects > 0u && mem_objects == nullptr))
    {
        return CL_INVALID_VALUE;
    }

    for (cl_uint i = 0u; i < num_mem_objects; ++i)
    {
        // CL_INVALID_MEM_OBJECT if any of the memory objects
        // in mem_objects is not a valid memory object.
        if (!Memory::IsValid(mem_objects[i]))
        {
            return CL_INVALID_MEM_OBJECT;
        }
    }

    // CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue
    ANGLE_VALIDATE(ValidateCommandQueueAndEventWaitList(command_queue, false,
                                                        num_events_in_wait_list, event_wait_list));
    if (!command_queue->cast<CommandQueue>().getContext().getPlatform().isVersionOrNewer(3u, 0u))
    {
        return CL_INVALID_COMMAND_QUEUE;
    }

    // CL_INVALID_COMMAND_QUEUE if device associated with command_queue is not one of the devices
    // specified by CL_MEM_DEVICE_HANDLE_LIST_KHR at the time of creating one or more of
    // mem_objects,
    const CommandQueue &queue       = command_queue->cast<CommandQueue>();
    const cl_device_id devFromQueue = const_cast<cl_device_id>(queue.getDevice().getNative());
    bool isCmdQueueDevAssociatedWithMemObj = false;
    bool isDevHandleMentionedInProp        = false;
    for (cl_uint i = 0u; i < num_mem_objects; ++i)
    {
        const cl_mem_properties *properties = mem_objects[i]->cast<Memory>().getProperties().data();
        const NameValueProperty *propertiesIterator =
            reinterpret_cast<const NameValueProperty *>(properties);
        // Process all NameValueProperty, [name, value] in properties
        while (propertiesIterator->name != 0)
        {
            if (propertiesIterator->name == CL_MEM_DEVICE_HANDLE_LIST_KHR)
            {
                isDevHandleMentionedInProp = true;
                cl_device_id devFromProp =
                    reinterpret_cast<cl_device_id>(propertiesIterator->value);
                if (devFromProp == devFromQueue)
                {
                    isCmdQueueDevAssociatedWithMemObj = true;
                    break;
                }
            }
            propertiesIterator++;
        }

        if (isDevHandleMentionedInProp && !isCmdQueueDevAssociatedWithMemObj)
        {
            return CL_INVALID_COMMAND_QUEUE;
        }
    }

    // CL_INVALID_COMMAND_QUEUE if one or more of mem_objects belong to a context
    // that does not contain a device associated with command_queue
    for (cl_uint i = 0u; i < num_mem_objects; ++i)
    {
        const Context &ctx = mem_objects[i]->cast<Memory>().getContext();
        if (!ctx.hasDevice(devFromQueue))
        {
            return CL_INVALID_COMMAND_QUEUE;
        }
    }

    return CL_SUCCESS;
}

// cl_arm_import_memory
cl_int ValidateImportMemoryARM(cl_context context,
                               MemFlags flags,
                               const cl_import_properties_arm *properties,
                               const void *memory,
                               size_t size)
{
    // CL_INVALID_VALUE if memory is NULL.
    if (memory == nullptr)
    {
        return CL_INVALID_VALUE;
    }

    // CL_INVALID_PROPERTY when invalid properties or combination of properties are passed.
    const NameValueProperty *propertiesIterator =
        reinterpret_cast<const NameValueProperty *>(properties);
    bool foundImportType = false;
    if (propertiesIterator != nullptr)
    {
        for (; propertiesIterator->name != 0; ++propertiesIterator)
        {
            if (propertiesIterator->name == CL_IMPORT_TYPE_ARM)
            {
                foundImportType = true;
                if (propertiesIterator->value != CL_IMPORT_TYPE_HOST_ARM &&
                    propertiesIterator->value != CL_IMPORT_TYPE_DMA_BUF_ARM &&
                    propertiesIterator->value != CL_IMPORT_TYPE_ANDROID_HARDWARE_BUFFER_ARM)
                {
                    return CL_INVALID_PROPERTY;
                }
            }
            else if (propertiesIterator->name == CL_IMPORT_TYPE_PROTECTED_ARM)
            {
                if (propertiesIterator->value == CL_TRUE)
                {
                    // we can allow non-protected memory, throw error otherwise
                    // (until cl_khr_external_memory can support this in some way)
                    WARN()
                        << "CL_IMPORT_TYPE_PROTECTED_ARM not supported since cl_arm_import_memory "
                           "is layered on cl_khr_external_memory (currently no equivalent)";
                    return CL_INVALID_OPERATION;
                }
            }
        }
        if (!foundImportType)
        {
            return CL_INVALID_PROPERTY;
        }
    }

    // Redirect to ValidateCreateBufferWithProperties as it is implemented on top of
    // cl_khr_external_memory
    Memory::PropArray convertedProperties = Context::ConvertArmMemPropToMemProp(properties, memory);
    return ValidateCreateBufferWithProperties(context, convertedProperties.data(), flags, size,
                                              nullptr);
}

cl_int ValidateEnqueueAcquireExternalMemObjectsKHR(cl_command_queue command_queue,
                                                   cl_uint num_mem_objects,
                                                   const cl_mem *mem_objects,
                                                   cl_uint num_events_in_wait_list,
                                                   const cl_event *event_wait_list,
                                                   const cl_event *event)
{
    return ValidateExternalMemObjectsKHR(command_queue, num_mem_objects, mem_objects,
                                         num_events_in_wait_list, event_wait_list);
}

cl_int ValidateEnqueueReleaseExternalMemObjectsKHR(cl_command_queue command_queue,
                                                   cl_uint num_mem_objects,
                                                   const cl_mem *mem_objects,
                                                   cl_uint num_events_in_wait_list,
                                                   const cl_event *event_wait_list,
                                                   const cl_event *event)
{
    return ValidateExternalMemObjectsKHR(command_queue, num_mem_objects, mem_objects,
                                         num_events_in_wait_list, event_wait_list);
}

// cl_khr_icd
cl_int ValidateIcdGetPlatformIDsKHR(cl_uint num_entries,
                                    const cl_platform_id *platforms,
                                    const cl_uint *num_platforms)
{
    if ((num_entries == 0u && platforms != nullptr) ||
        (platforms == nullptr && num_platforms == nullptr))
    {
        return CL_INVALID_VALUE;
    }
    return CL_SUCCESS;
}

cl_int ValidateIcdGetFunctionAddressForPlatformKHR(cl_platform_id platform, const char *func_name)
{
    return CL_SUCCESS;
}

cl_int ValidateIcdSetPlatformDispatchDataKHR(cl_platform_id platform, const void *dispatch_data)
{
    return CL_SUCCESS;
}

cl_int ValidateGetKernelSubGroupInfoKHR(cl_kernel kernel,
                                        cl_device_id device,
                                        KernelSubGroupInfo param_namePacked,
                                        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)
{
    return ValidateGetKernelSubGroupInfo(kernel, device, param_namePacked, input_value_size,
                                         input_value, param_value_size, param_value,
                                         param_value_size_ret);
}

}  // namespace cl
