// GENERATED FILE - DO NOT EDIT.
// Generated by gen_packed_gl_enums.py using data from packed_cl_enums.json.
//
// Copyright 2017 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.
//
// PackedCLEnums_autogen.cpp:
//   Implements ANGLE-specific enums classes for CLenums and functions operating
//   on them.

#include "common/PackedCLEnums_autogen.h"
#include "common/debug.h"

namespace cl
{

template <>
AddressingMode FromCLenum<AddressingMode>(CLenum from)
{
    switch (from)
    {
        case CL_ADDRESS_NONE:
            return AddressingMode::None;
        case CL_ADDRESS_CLAMP_TO_EDGE:
            return AddressingMode::ClampToEdge;
        case CL_ADDRESS_CLAMP:
            return AddressingMode::Clamp;
        case CL_ADDRESS_REPEAT:
            return AddressingMode::Repeat;
        case CL_ADDRESS_MIRRORED_REPEAT:
            return AddressingMode::MirroredRepeat;
        default:
            return AddressingMode::InvalidEnum;
    }
}

CLenum ToCLenum(AddressingMode from)
{
    switch (from)
    {
        case AddressingMode::None:
            return CL_ADDRESS_NONE;
        case AddressingMode::ClampToEdge:
            return CL_ADDRESS_CLAMP_TO_EDGE;
        case AddressingMode::Clamp:
            return CL_ADDRESS_CLAMP;
        case AddressingMode::Repeat:
            return CL_ADDRESS_REPEAT;
        case AddressingMode::MirroredRepeat:
            return CL_ADDRESS_MIRRORED_REPEAT;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, AddressingMode value)
{
    switch (value)
    {
        case AddressingMode::None:
            os << "CL_ADDRESS_NONE";
            break;
        case AddressingMode::ClampToEdge:
            os << "CL_ADDRESS_CLAMP_TO_EDGE";
            break;
        case AddressingMode::Clamp:
            os << "CL_ADDRESS_CLAMP";
            break;
        case AddressingMode::Repeat:
            os << "CL_ADDRESS_REPEAT";
            break;
        case AddressingMode::MirroredRepeat:
            os << "CL_ADDRESS_MIRRORED_REPEAT";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
CommandQueueInfo FromCLenum<CommandQueueInfo>(CLenum from)
{
    switch (from)
    {
        case CL_QUEUE_CONTEXT:
            return CommandQueueInfo::Context;
        case CL_QUEUE_DEVICE:
            return CommandQueueInfo::Device;
        case CL_QUEUE_REFERENCE_COUNT:
            return CommandQueueInfo::ReferenceCount;
        case CL_QUEUE_PROPERTIES:
            return CommandQueueInfo::Properties;
        case CL_QUEUE_SIZE:
            return CommandQueueInfo::Size;
        case CL_QUEUE_DEVICE_DEFAULT:
            return CommandQueueInfo::DeviceDefault;
        case CL_QUEUE_PROPERTIES_ARRAY:
            return CommandQueueInfo::PropertiesArray;
        default:
            return CommandQueueInfo::InvalidEnum;
    }
}

CLenum ToCLenum(CommandQueueInfo from)
{
    switch (from)
    {
        case CommandQueueInfo::Context:
            return CL_QUEUE_CONTEXT;
        case CommandQueueInfo::Device:
            return CL_QUEUE_DEVICE;
        case CommandQueueInfo::ReferenceCount:
            return CL_QUEUE_REFERENCE_COUNT;
        case CommandQueueInfo::Properties:
            return CL_QUEUE_PROPERTIES;
        case CommandQueueInfo::Size:
            return CL_QUEUE_SIZE;
        case CommandQueueInfo::DeviceDefault:
            return CL_QUEUE_DEVICE_DEFAULT;
        case CommandQueueInfo::PropertiesArray:
            return CL_QUEUE_PROPERTIES_ARRAY;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, CommandQueueInfo value)
{
    switch (value)
    {
        case CommandQueueInfo::Context:
            os << "CL_QUEUE_CONTEXT";
            break;
        case CommandQueueInfo::Device:
            os << "CL_QUEUE_DEVICE";
            break;
        case CommandQueueInfo::ReferenceCount:
            os << "CL_QUEUE_REFERENCE_COUNT";
            break;
        case CommandQueueInfo::Properties:
            os << "CL_QUEUE_PROPERTIES";
            break;
        case CommandQueueInfo::Size:
            os << "CL_QUEUE_SIZE";
            break;
        case CommandQueueInfo::DeviceDefault:
            os << "CL_QUEUE_DEVICE_DEFAULT";
            break;
        case CommandQueueInfo::PropertiesArray:
            os << "CL_QUEUE_PROPERTIES_ARRAY";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ContextInfo FromCLenum<ContextInfo>(CLenum from)
{
    switch (from)
    {
        case CL_CONTEXT_REFERENCE_COUNT:
            return ContextInfo::ReferenceCount;
        case CL_CONTEXT_DEVICES:
            return ContextInfo::Devices;
        case CL_CONTEXT_PROPERTIES:
            return ContextInfo::Properties;
        case CL_CONTEXT_NUM_DEVICES:
            return ContextInfo::NumDevices;
        default:
            return ContextInfo::InvalidEnum;
    }
}

CLenum ToCLenum(ContextInfo from)
{
    switch (from)
    {
        case ContextInfo::ReferenceCount:
            return CL_CONTEXT_REFERENCE_COUNT;
        case ContextInfo::Devices:
            return CL_CONTEXT_DEVICES;
        case ContextInfo::Properties:
            return CL_CONTEXT_PROPERTIES;
        case ContextInfo::NumDevices:
            return CL_CONTEXT_NUM_DEVICES;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ContextInfo value)
{
    switch (value)
    {
        case ContextInfo::ReferenceCount:
            os << "CL_CONTEXT_REFERENCE_COUNT";
            break;
        case ContextInfo::Devices:
            os << "CL_CONTEXT_DEVICES";
            break;
        case ContextInfo::Properties:
            os << "CL_CONTEXT_PROPERTIES";
            break;
        case ContextInfo::NumDevices:
            os << "CL_CONTEXT_NUM_DEVICES";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
DeviceInfo FromCLenum<DeviceInfo>(CLenum from)
{
    switch (from)
    {
        case CL_DEVICE_TYPE:
            return DeviceInfo::Type;
        case CL_DEVICE_VENDOR_ID:
            return DeviceInfo::VendorID;
        case CL_DEVICE_MAX_COMPUTE_UNITS:
            return DeviceInfo::MaxComputeUnits;
        case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
            return DeviceInfo::MaxWorkItemDimensions;
        case CL_DEVICE_MAX_WORK_GROUP_SIZE:
            return DeviceInfo::MaxWorkGroupSize;
        case CL_DEVICE_MAX_WORK_ITEM_SIZES:
            return DeviceInfo::MaxWorkItemSizes;
        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
            return DeviceInfo::PreferredVectorWidthChar;
        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
            return DeviceInfo::PreferredVectorWidthShort;
        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:
            return DeviceInfo::PreferredVectorWidthInt;
        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:
            return DeviceInfo::PreferredVectorWidthLong;
        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:
            return DeviceInfo::PreferredVectorWidthFloat;
        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:
            return DeviceInfo::PreferredVectorWidthDouble;
        case CL_DEVICE_MAX_CLOCK_FREQUENCY:
            return DeviceInfo::MaxClockFrequency;
        case CL_DEVICE_ADDRESS_BITS:
            return DeviceInfo::AddressBits;
        case CL_DEVICE_MAX_READ_IMAGE_ARGS:
            return DeviceInfo::MaxReadImageArgs;
        case CL_DEVICE_MAX_WRITE_IMAGE_ARGS:
            return DeviceInfo::MaxWriteImageArgs;
        case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
            return DeviceInfo::MaxMemAllocSize;
        case CL_DEVICE_IMAGE2D_MAX_WIDTH:
            return DeviceInfo::Image2D_MaxWidth;
        case CL_DEVICE_IMAGE2D_MAX_HEIGHT:
            return DeviceInfo::Image2D_MaxHeight;
        case CL_DEVICE_IMAGE3D_MAX_WIDTH:
            return DeviceInfo::Image3D_MaxWidth;
        case CL_DEVICE_IMAGE3D_MAX_HEIGHT:
            return DeviceInfo::Image3D_MaxHeight;
        case CL_DEVICE_IMAGE3D_MAX_DEPTH:
            return DeviceInfo::Image3D_MaxDepth;
        case CL_DEVICE_IMAGE_SUPPORT:
            return DeviceInfo::ImageSupport;
        case CL_DEVICE_MAX_PARAMETER_SIZE:
            return DeviceInfo::MaxParameterSize;
        case CL_DEVICE_MAX_SAMPLERS:
            return DeviceInfo::MaxSamplers;
        case CL_DEVICE_MEM_BASE_ADDR_ALIGN:
            return DeviceInfo::MemBaseAddrAlign;
        case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:
            return DeviceInfo::MinDataTypeAlignSize;
        case CL_DEVICE_SINGLE_FP_CONFIG:
            return DeviceInfo::SingleFpConfig;
        case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:
            return DeviceInfo::GlobalMemCacheType;
        case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:
            return DeviceInfo::GlobalMemCachelineSize;
        case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:
            return DeviceInfo::GlobalMemCacheSize;
        case CL_DEVICE_GLOBAL_MEM_SIZE:
            return DeviceInfo::GlobalMemSize;
        case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
            return DeviceInfo::MaxConstantBufferSize;
        case CL_DEVICE_MAX_CONSTANT_ARGS:
            return DeviceInfo::MaxConstantArgs;
        case CL_DEVICE_LOCAL_MEM_TYPE:
            return DeviceInfo::LocalMemType;
        case CL_DEVICE_LOCAL_MEM_SIZE:
            return DeviceInfo::LocalMemSize;
        case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
            return DeviceInfo::ErrorCorrectionSupport;
        case CL_DEVICE_PROFILING_TIMER_RESOLUTION:
            return DeviceInfo::ProfilingTimerResolution;
        case CL_DEVICE_ENDIAN_LITTLE:
            return DeviceInfo::EndianLittle;
        case CL_DEVICE_AVAILABLE:
            return DeviceInfo::Available;
        case CL_DEVICE_COMPILER_AVAILABLE:
            return DeviceInfo::CompilerAvailable;
        case CL_DEVICE_EXECUTION_CAPABILITIES:
            return DeviceInfo::ExecutionCapabilities;
        case CL_DEVICE_QUEUE_ON_HOST_PROPERTIES:
            return DeviceInfo::QueueOnHostProperties;
        case CL_DEVICE_NAME:
            return DeviceInfo::Name;
        case CL_DEVICE_VENDOR:
            return DeviceInfo::Vendor;
        case CL_DRIVER_VERSION:
            return DeviceInfo::DriverVersion;
        case CL_DEVICE_PROFILE:
            return DeviceInfo::Profile;
        case CL_DEVICE_VERSION:
            return DeviceInfo::Version;
        case CL_DEVICE_EXTENSIONS:
            return DeviceInfo::Extensions;
        case CL_DEVICE_PLATFORM:
            return DeviceInfo::Platform;
        case CL_DEVICE_DOUBLE_FP_CONFIG:
            return DeviceInfo::DoubleFpConfig;
        case CL_DEVICE_HALF_FP_CONFIG:
            return DeviceInfo::HalfFpConfig;
        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:
            return DeviceInfo::PreferredVectorWidthHalf;
        case CL_DEVICE_HOST_UNIFIED_MEMORY:
            return DeviceInfo::HostUnifiedMemory;
        case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
            return DeviceInfo::NativeVectorWidthChar;
        case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:
            return DeviceInfo::NativeVectorWidthShort;
        case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:
            return DeviceInfo::NativeVectorWidthInt;
        case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:
            return DeviceInfo::NativeVectorWidthLong;
        case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:
            return DeviceInfo::NativeVectorWidthFloat;
        case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:
            return DeviceInfo::NativeVectorWidthDouble;
        case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:
            return DeviceInfo::NativeVectorWidthHalf;
        case CL_DEVICE_OPENCL_C_VERSION:
            return DeviceInfo::OpenCL_C_Version;
        case CL_DEVICE_LINKER_AVAILABLE:
            return DeviceInfo::LinkerAvailable;
        case CL_DEVICE_BUILT_IN_KERNELS:
            return DeviceInfo::BuiltInKernels;
        case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE:
            return DeviceInfo::ImageMaxBufferSize;
        case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE:
            return DeviceInfo::ImageMaxArraySize;
        case CL_DEVICE_PARENT_DEVICE:
            return DeviceInfo::ParentDevice;
        case CL_DEVICE_PARTITION_MAX_SUB_DEVICES:
            return DeviceInfo::PartitionMaxSubDevices;
        case CL_DEVICE_PARTITION_PROPERTIES:
            return DeviceInfo::PartitionProperties;
        case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
            return DeviceInfo::PartitionAffinityDomain;
        case CL_DEVICE_PARTITION_TYPE:
            return DeviceInfo::PartitionType;
        case CL_DEVICE_REFERENCE_COUNT:
            return DeviceInfo::ReferenceCount;
        case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC:
            return DeviceInfo::PreferredInteropUserSync;
        case CL_DEVICE_PRINTF_BUFFER_SIZE:
            return DeviceInfo::PrintfBufferSize;
        case CL_DEVICE_IMAGE_PITCH_ALIGNMENT:
            return DeviceInfo::ImagePitchAlignment;
        case CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT:
            return DeviceInfo::ImageBaseAddressAlignment;
        case CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS:
            return DeviceInfo::MaxReadWriteImageArgs;
        case CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE:
            return DeviceInfo::MaxGlobalVariableSize;
        case CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES:
            return DeviceInfo::QueueOnDeviceProperties;
        case CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE:
            return DeviceInfo::QueueOnDevicePreferredSize;
        case CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE:
            return DeviceInfo::QueueOnDeviceMaxSize;
        case CL_DEVICE_MAX_ON_DEVICE_QUEUES:
            return DeviceInfo::MaxOnDeviceQueues;
        case CL_DEVICE_MAX_ON_DEVICE_EVENTS:
            return DeviceInfo::MaxOnDeviceEvents;
        case CL_DEVICE_SVM_CAPABILITIES:
            return DeviceInfo::SVM_Capabilities;
        case CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE:
            return DeviceInfo::GlobalVariablePreferredTotalSize;
        case CL_DEVICE_MAX_PIPE_ARGS:
            return DeviceInfo::MaxPipeArgs;
        case CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS:
            return DeviceInfo::PipeMaxActiveReservations;
        case CL_DEVICE_PIPE_MAX_PACKET_SIZE:
            return DeviceInfo::PipeMaxPacketSize;
        case CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT:
            return DeviceInfo::PreferredPlatformAtomicAlignment;
        case CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT:
            return DeviceInfo::PreferredGlobalAtomicAlignment;
        case CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT:
            return DeviceInfo::PreferredLocalAtomicAlignment;
        case CL_DEVICE_IL_VERSION:
            return DeviceInfo::IL_Version;
        case CL_DEVICE_MAX_NUM_SUB_GROUPS:
            return DeviceInfo::MaxNumSubGroups;
        case CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS:
            return DeviceInfo::SubGroupIndependentForwardProgress;
        case CL_DEVICE_NUMERIC_VERSION:
            return DeviceInfo::NumericVersion;
        case CL_DEVICE_EXTENSIONS_WITH_VERSION:
            return DeviceInfo::ExtensionsWithVersion;
        case CL_DEVICE_ILS_WITH_VERSION:
            return DeviceInfo::ILsWithVersion;
        case CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION:
            return DeviceInfo::BuiltInKernelsWithVersion;
        case CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES:
            return DeviceInfo::AtomicMemoryCapabilities;
        case CL_DEVICE_ATOMIC_FENCE_CAPABILITIES:
            return DeviceInfo::AtomicFenceCapabilities;
        case CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT:
            return DeviceInfo::NonUniformWorkGroupSupport;
        case CL_DEVICE_OPENCL_C_ALL_VERSIONS:
            return DeviceInfo::OpenCL_C_AllVersions;
        case CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE:
            return DeviceInfo::PreferredWorkGroupSizeMultiple;
        case CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT:
            return DeviceInfo::WorkGroupCollectiveFunctionsSupport;
        case CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT:
            return DeviceInfo::GenericAddressSpaceSupport;
        case CL_DEVICE_OPENCL_C_FEATURES:
            return DeviceInfo::OpenCL_C_Features;
        case CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES:
            return DeviceInfo::DeviceEnqueueCapabilities;
        case CL_DEVICE_PIPE_SUPPORT:
            return DeviceInfo::PipeSupport;
        case CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED:
            return DeviceInfo::LatestConformanceVersionPassed;
        case CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR:
            return DeviceInfo::IntegerDotProductCapabilities;
        case CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR:
            return DeviceInfo::IntegerDotProductAccelerationProperties8bit;
        case CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR:
            return DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked;
        case CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR:
            return DeviceInfo::ExternalMemoryImportHandleTypes;
        case CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR:
            return DeviceInfo::ExternalMemoryLinearImagesHandleTypes;
        default:
            return DeviceInfo::InvalidEnum;
    }
}

CLenum ToCLenum(DeviceInfo from)
{
    switch (from)
    {
        case DeviceInfo::Type:
            return CL_DEVICE_TYPE;
        case DeviceInfo::VendorID:
            return CL_DEVICE_VENDOR_ID;
        case DeviceInfo::MaxComputeUnits:
            return CL_DEVICE_MAX_COMPUTE_UNITS;
        case DeviceInfo::MaxWorkItemDimensions:
            return CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS;
        case DeviceInfo::MaxWorkGroupSize:
            return CL_DEVICE_MAX_WORK_GROUP_SIZE;
        case DeviceInfo::MaxWorkItemSizes:
            return CL_DEVICE_MAX_WORK_ITEM_SIZES;
        case DeviceInfo::PreferredVectorWidthChar:
            return CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR;
        case DeviceInfo::PreferredVectorWidthShort:
            return CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT;
        case DeviceInfo::PreferredVectorWidthInt:
            return CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT;
        case DeviceInfo::PreferredVectorWidthLong:
            return CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG;
        case DeviceInfo::PreferredVectorWidthFloat:
            return CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT;
        case DeviceInfo::PreferredVectorWidthDouble:
            return CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE;
        case DeviceInfo::MaxClockFrequency:
            return CL_DEVICE_MAX_CLOCK_FREQUENCY;
        case DeviceInfo::AddressBits:
            return CL_DEVICE_ADDRESS_BITS;
        case DeviceInfo::MaxReadImageArgs:
            return CL_DEVICE_MAX_READ_IMAGE_ARGS;
        case DeviceInfo::MaxWriteImageArgs:
            return CL_DEVICE_MAX_WRITE_IMAGE_ARGS;
        case DeviceInfo::MaxMemAllocSize:
            return CL_DEVICE_MAX_MEM_ALLOC_SIZE;
        case DeviceInfo::Image2D_MaxWidth:
            return CL_DEVICE_IMAGE2D_MAX_WIDTH;
        case DeviceInfo::Image2D_MaxHeight:
            return CL_DEVICE_IMAGE2D_MAX_HEIGHT;
        case DeviceInfo::Image3D_MaxWidth:
            return CL_DEVICE_IMAGE3D_MAX_WIDTH;
        case DeviceInfo::Image3D_MaxHeight:
            return CL_DEVICE_IMAGE3D_MAX_HEIGHT;
        case DeviceInfo::Image3D_MaxDepth:
            return CL_DEVICE_IMAGE3D_MAX_DEPTH;
        case DeviceInfo::ImageSupport:
            return CL_DEVICE_IMAGE_SUPPORT;
        case DeviceInfo::MaxParameterSize:
            return CL_DEVICE_MAX_PARAMETER_SIZE;
        case DeviceInfo::MaxSamplers:
            return CL_DEVICE_MAX_SAMPLERS;
        case DeviceInfo::MemBaseAddrAlign:
            return CL_DEVICE_MEM_BASE_ADDR_ALIGN;
        case DeviceInfo::MinDataTypeAlignSize:
            return CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE;
        case DeviceInfo::SingleFpConfig:
            return CL_DEVICE_SINGLE_FP_CONFIG;
        case DeviceInfo::GlobalMemCacheType:
            return CL_DEVICE_GLOBAL_MEM_CACHE_TYPE;
        case DeviceInfo::GlobalMemCachelineSize:
            return CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE;
        case DeviceInfo::GlobalMemCacheSize:
            return CL_DEVICE_GLOBAL_MEM_CACHE_SIZE;
        case DeviceInfo::GlobalMemSize:
            return CL_DEVICE_GLOBAL_MEM_SIZE;
        case DeviceInfo::MaxConstantBufferSize:
            return CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE;
        case DeviceInfo::MaxConstantArgs:
            return CL_DEVICE_MAX_CONSTANT_ARGS;
        case DeviceInfo::LocalMemType:
            return CL_DEVICE_LOCAL_MEM_TYPE;
        case DeviceInfo::LocalMemSize:
            return CL_DEVICE_LOCAL_MEM_SIZE;
        case DeviceInfo::ErrorCorrectionSupport:
            return CL_DEVICE_ERROR_CORRECTION_SUPPORT;
        case DeviceInfo::ProfilingTimerResolution:
            return CL_DEVICE_PROFILING_TIMER_RESOLUTION;
        case DeviceInfo::EndianLittle:
            return CL_DEVICE_ENDIAN_LITTLE;
        case DeviceInfo::Available:
            return CL_DEVICE_AVAILABLE;
        case DeviceInfo::CompilerAvailable:
            return CL_DEVICE_COMPILER_AVAILABLE;
        case DeviceInfo::ExecutionCapabilities:
            return CL_DEVICE_EXECUTION_CAPABILITIES;
        case DeviceInfo::QueueOnHostProperties:
            return CL_DEVICE_QUEUE_ON_HOST_PROPERTIES;
        case DeviceInfo::Name:
            return CL_DEVICE_NAME;
        case DeviceInfo::Vendor:
            return CL_DEVICE_VENDOR;
        case DeviceInfo::DriverVersion:
            return CL_DRIVER_VERSION;
        case DeviceInfo::Profile:
            return CL_DEVICE_PROFILE;
        case DeviceInfo::Version:
            return CL_DEVICE_VERSION;
        case DeviceInfo::Extensions:
            return CL_DEVICE_EXTENSIONS;
        case DeviceInfo::Platform:
            return CL_DEVICE_PLATFORM;
        case DeviceInfo::DoubleFpConfig:
            return CL_DEVICE_DOUBLE_FP_CONFIG;
        case DeviceInfo::HalfFpConfig:
            return CL_DEVICE_HALF_FP_CONFIG;
        case DeviceInfo::PreferredVectorWidthHalf:
            return CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF;
        case DeviceInfo::HostUnifiedMemory:
            return CL_DEVICE_HOST_UNIFIED_MEMORY;
        case DeviceInfo::NativeVectorWidthChar:
            return CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR;
        case DeviceInfo::NativeVectorWidthShort:
            return CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT;
        case DeviceInfo::NativeVectorWidthInt:
            return CL_DEVICE_NATIVE_VECTOR_WIDTH_INT;
        case DeviceInfo::NativeVectorWidthLong:
            return CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG;
        case DeviceInfo::NativeVectorWidthFloat:
            return CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT;
        case DeviceInfo::NativeVectorWidthDouble:
            return CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE;
        case DeviceInfo::NativeVectorWidthHalf:
            return CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF;
        case DeviceInfo::OpenCL_C_Version:
            return CL_DEVICE_OPENCL_C_VERSION;
        case DeviceInfo::LinkerAvailable:
            return CL_DEVICE_LINKER_AVAILABLE;
        case DeviceInfo::BuiltInKernels:
            return CL_DEVICE_BUILT_IN_KERNELS;
        case DeviceInfo::ImageMaxBufferSize:
            return CL_DEVICE_IMAGE_MAX_BUFFER_SIZE;
        case DeviceInfo::ImageMaxArraySize:
            return CL_DEVICE_IMAGE_MAX_ARRAY_SIZE;
        case DeviceInfo::ParentDevice:
            return CL_DEVICE_PARENT_DEVICE;
        case DeviceInfo::PartitionMaxSubDevices:
            return CL_DEVICE_PARTITION_MAX_SUB_DEVICES;
        case DeviceInfo::PartitionProperties:
            return CL_DEVICE_PARTITION_PROPERTIES;
        case DeviceInfo::PartitionAffinityDomain:
            return CL_DEVICE_PARTITION_AFFINITY_DOMAIN;
        case DeviceInfo::PartitionType:
            return CL_DEVICE_PARTITION_TYPE;
        case DeviceInfo::ReferenceCount:
            return CL_DEVICE_REFERENCE_COUNT;
        case DeviceInfo::PreferredInteropUserSync:
            return CL_DEVICE_PREFERRED_INTEROP_USER_SYNC;
        case DeviceInfo::PrintfBufferSize:
            return CL_DEVICE_PRINTF_BUFFER_SIZE;
        case DeviceInfo::ImagePitchAlignment:
            return CL_DEVICE_IMAGE_PITCH_ALIGNMENT;
        case DeviceInfo::ImageBaseAddressAlignment:
            return CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT;
        case DeviceInfo::MaxReadWriteImageArgs:
            return CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS;
        case DeviceInfo::MaxGlobalVariableSize:
            return CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE;
        case DeviceInfo::QueueOnDeviceProperties:
            return CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES;
        case DeviceInfo::QueueOnDevicePreferredSize:
            return CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE;
        case DeviceInfo::QueueOnDeviceMaxSize:
            return CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE;
        case DeviceInfo::MaxOnDeviceQueues:
            return CL_DEVICE_MAX_ON_DEVICE_QUEUES;
        case DeviceInfo::MaxOnDeviceEvents:
            return CL_DEVICE_MAX_ON_DEVICE_EVENTS;
        case DeviceInfo::SVM_Capabilities:
            return CL_DEVICE_SVM_CAPABILITIES;
        case DeviceInfo::GlobalVariablePreferredTotalSize:
            return CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE;
        case DeviceInfo::MaxPipeArgs:
            return CL_DEVICE_MAX_PIPE_ARGS;
        case DeviceInfo::PipeMaxActiveReservations:
            return CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS;
        case DeviceInfo::PipeMaxPacketSize:
            return CL_DEVICE_PIPE_MAX_PACKET_SIZE;
        case DeviceInfo::PreferredPlatformAtomicAlignment:
            return CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT;
        case DeviceInfo::PreferredGlobalAtomicAlignment:
            return CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT;
        case DeviceInfo::PreferredLocalAtomicAlignment:
            return CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT;
        case DeviceInfo::IL_Version:
            return CL_DEVICE_IL_VERSION;
        case DeviceInfo::MaxNumSubGroups:
            return CL_DEVICE_MAX_NUM_SUB_GROUPS;
        case DeviceInfo::SubGroupIndependentForwardProgress:
            return CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS;
        case DeviceInfo::NumericVersion:
            return CL_DEVICE_NUMERIC_VERSION;
        case DeviceInfo::ExtensionsWithVersion:
            return CL_DEVICE_EXTENSIONS_WITH_VERSION;
        case DeviceInfo::ILsWithVersion:
            return CL_DEVICE_ILS_WITH_VERSION;
        case DeviceInfo::BuiltInKernelsWithVersion:
            return CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION;
        case DeviceInfo::AtomicMemoryCapabilities:
            return CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES;
        case DeviceInfo::AtomicFenceCapabilities:
            return CL_DEVICE_ATOMIC_FENCE_CAPABILITIES;
        case DeviceInfo::NonUniformWorkGroupSupport:
            return CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT;
        case DeviceInfo::OpenCL_C_AllVersions:
            return CL_DEVICE_OPENCL_C_ALL_VERSIONS;
        case DeviceInfo::PreferredWorkGroupSizeMultiple:
            return CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE;
        case DeviceInfo::WorkGroupCollectiveFunctionsSupport:
            return CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT;
        case DeviceInfo::GenericAddressSpaceSupport:
            return CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT;
        case DeviceInfo::OpenCL_C_Features:
            return CL_DEVICE_OPENCL_C_FEATURES;
        case DeviceInfo::DeviceEnqueueCapabilities:
            return CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES;
        case DeviceInfo::PipeSupport:
            return CL_DEVICE_PIPE_SUPPORT;
        case DeviceInfo::LatestConformanceVersionPassed:
            return CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED;
        case DeviceInfo::IntegerDotProductCapabilities:
            return CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR;
        case DeviceInfo::IntegerDotProductAccelerationProperties8bit:
            return CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR;
        case DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked:
            return CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR;
        case DeviceInfo::ExternalMemoryImportHandleTypes:
            return CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR;
        case DeviceInfo::ExternalMemoryLinearImagesHandleTypes:
            return CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, DeviceInfo value)
{
    switch (value)
    {
        case DeviceInfo::Type:
            os << "CL_DEVICE_TYPE";
            break;
        case DeviceInfo::VendorID:
            os << "CL_DEVICE_VENDOR_ID";
            break;
        case DeviceInfo::MaxComputeUnits:
            os << "CL_DEVICE_MAX_COMPUTE_UNITS";
            break;
        case DeviceInfo::MaxWorkItemDimensions:
            os << "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS";
            break;
        case DeviceInfo::MaxWorkGroupSize:
            os << "CL_DEVICE_MAX_WORK_GROUP_SIZE";
            break;
        case DeviceInfo::MaxWorkItemSizes:
            os << "CL_DEVICE_MAX_WORK_ITEM_SIZES";
            break;
        case DeviceInfo::PreferredVectorWidthChar:
            os << "CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR";
            break;
        case DeviceInfo::PreferredVectorWidthShort:
            os << "CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT";
            break;
        case DeviceInfo::PreferredVectorWidthInt:
            os << "CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT";
            break;
        case DeviceInfo::PreferredVectorWidthLong:
            os << "CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG";
            break;
        case DeviceInfo::PreferredVectorWidthFloat:
            os << "CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT";
            break;
        case DeviceInfo::PreferredVectorWidthDouble:
            os << "CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE";
            break;
        case DeviceInfo::MaxClockFrequency:
            os << "CL_DEVICE_MAX_CLOCK_FREQUENCY";
            break;
        case DeviceInfo::AddressBits:
            os << "CL_DEVICE_ADDRESS_BITS";
            break;
        case DeviceInfo::MaxReadImageArgs:
            os << "CL_DEVICE_MAX_READ_IMAGE_ARGS";
            break;
        case DeviceInfo::MaxWriteImageArgs:
            os << "CL_DEVICE_MAX_WRITE_IMAGE_ARGS";
            break;
        case DeviceInfo::MaxMemAllocSize:
            os << "CL_DEVICE_MAX_MEM_ALLOC_SIZE";
            break;
        case DeviceInfo::Image2D_MaxWidth:
            os << "CL_DEVICE_IMAGE2D_MAX_WIDTH";
            break;
        case DeviceInfo::Image2D_MaxHeight:
            os << "CL_DEVICE_IMAGE2D_MAX_HEIGHT";
            break;
        case DeviceInfo::Image3D_MaxWidth:
            os << "CL_DEVICE_IMAGE3D_MAX_WIDTH";
            break;
        case DeviceInfo::Image3D_MaxHeight:
            os << "CL_DEVICE_IMAGE3D_MAX_HEIGHT";
            break;
        case DeviceInfo::Image3D_MaxDepth:
            os << "CL_DEVICE_IMAGE3D_MAX_DEPTH";
            break;
        case DeviceInfo::ImageSupport:
            os << "CL_DEVICE_IMAGE_SUPPORT";
            break;
        case DeviceInfo::MaxParameterSize:
            os << "CL_DEVICE_MAX_PARAMETER_SIZE";
            break;
        case DeviceInfo::MaxSamplers:
            os << "CL_DEVICE_MAX_SAMPLERS";
            break;
        case DeviceInfo::MemBaseAddrAlign:
            os << "CL_DEVICE_MEM_BASE_ADDR_ALIGN";
            break;
        case DeviceInfo::MinDataTypeAlignSize:
            os << "CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE";
            break;
        case DeviceInfo::SingleFpConfig:
            os << "CL_DEVICE_SINGLE_FP_CONFIG";
            break;
        case DeviceInfo::GlobalMemCacheType:
            os << "CL_DEVICE_GLOBAL_MEM_CACHE_TYPE";
            break;
        case DeviceInfo::GlobalMemCachelineSize:
            os << "CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE";
            break;
        case DeviceInfo::GlobalMemCacheSize:
            os << "CL_DEVICE_GLOBAL_MEM_CACHE_SIZE";
            break;
        case DeviceInfo::GlobalMemSize:
            os << "CL_DEVICE_GLOBAL_MEM_SIZE";
            break;
        case DeviceInfo::MaxConstantBufferSize:
            os << "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE";
            break;
        case DeviceInfo::MaxConstantArgs:
            os << "CL_DEVICE_MAX_CONSTANT_ARGS";
            break;
        case DeviceInfo::LocalMemType:
            os << "CL_DEVICE_LOCAL_MEM_TYPE";
            break;
        case DeviceInfo::LocalMemSize:
            os << "CL_DEVICE_LOCAL_MEM_SIZE";
            break;
        case DeviceInfo::ErrorCorrectionSupport:
            os << "CL_DEVICE_ERROR_CORRECTION_SUPPORT";
            break;
        case DeviceInfo::ProfilingTimerResolution:
            os << "CL_DEVICE_PROFILING_TIMER_RESOLUTION";
            break;
        case DeviceInfo::EndianLittle:
            os << "CL_DEVICE_ENDIAN_LITTLE";
            break;
        case DeviceInfo::Available:
            os << "CL_DEVICE_AVAILABLE";
            break;
        case DeviceInfo::CompilerAvailable:
            os << "CL_DEVICE_COMPILER_AVAILABLE";
            break;
        case DeviceInfo::ExecutionCapabilities:
            os << "CL_DEVICE_EXECUTION_CAPABILITIES";
            break;
        case DeviceInfo::QueueOnHostProperties:
            os << "CL_DEVICE_QUEUE_ON_HOST_PROPERTIES";
            break;
        case DeviceInfo::Name:
            os << "CL_DEVICE_NAME";
            break;
        case DeviceInfo::Vendor:
            os << "CL_DEVICE_VENDOR";
            break;
        case DeviceInfo::DriverVersion:
            os << "CL_DRIVER_VERSION";
            break;
        case DeviceInfo::Profile:
            os << "CL_DEVICE_PROFILE";
            break;
        case DeviceInfo::Version:
            os << "CL_DEVICE_VERSION";
            break;
        case DeviceInfo::Extensions:
            os << "CL_DEVICE_EXTENSIONS";
            break;
        case DeviceInfo::Platform:
            os << "CL_DEVICE_PLATFORM";
            break;
        case DeviceInfo::DoubleFpConfig:
            os << "CL_DEVICE_DOUBLE_FP_CONFIG";
            break;
        case DeviceInfo::HalfFpConfig:
            os << "CL_DEVICE_HALF_FP_CONFIG";
            break;
        case DeviceInfo::PreferredVectorWidthHalf:
            os << "CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF";
            break;
        case DeviceInfo::HostUnifiedMemory:
            os << "CL_DEVICE_HOST_UNIFIED_MEMORY";
            break;
        case DeviceInfo::NativeVectorWidthChar:
            os << "CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR";
            break;
        case DeviceInfo::NativeVectorWidthShort:
            os << "CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT";
            break;
        case DeviceInfo::NativeVectorWidthInt:
            os << "CL_DEVICE_NATIVE_VECTOR_WIDTH_INT";
            break;
        case DeviceInfo::NativeVectorWidthLong:
            os << "CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG";
            break;
        case DeviceInfo::NativeVectorWidthFloat:
            os << "CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT";
            break;
        case DeviceInfo::NativeVectorWidthDouble:
            os << "CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE";
            break;
        case DeviceInfo::NativeVectorWidthHalf:
            os << "CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF";
            break;
        case DeviceInfo::OpenCL_C_Version:
            os << "CL_DEVICE_OPENCL_C_VERSION";
            break;
        case DeviceInfo::LinkerAvailable:
            os << "CL_DEVICE_LINKER_AVAILABLE";
            break;
        case DeviceInfo::BuiltInKernels:
            os << "CL_DEVICE_BUILT_IN_KERNELS";
            break;
        case DeviceInfo::ImageMaxBufferSize:
            os << "CL_DEVICE_IMAGE_MAX_BUFFER_SIZE";
            break;
        case DeviceInfo::ImageMaxArraySize:
            os << "CL_DEVICE_IMAGE_MAX_ARRAY_SIZE";
            break;
        case DeviceInfo::ParentDevice:
            os << "CL_DEVICE_PARENT_DEVICE";
            break;
        case DeviceInfo::PartitionMaxSubDevices:
            os << "CL_DEVICE_PARTITION_MAX_SUB_DEVICES";
            break;
        case DeviceInfo::PartitionProperties:
            os << "CL_DEVICE_PARTITION_PROPERTIES";
            break;
        case DeviceInfo::PartitionAffinityDomain:
            os << "CL_DEVICE_PARTITION_AFFINITY_DOMAIN";
            break;
        case DeviceInfo::PartitionType:
            os << "CL_DEVICE_PARTITION_TYPE";
            break;
        case DeviceInfo::ReferenceCount:
            os << "CL_DEVICE_REFERENCE_COUNT";
            break;
        case DeviceInfo::PreferredInteropUserSync:
            os << "CL_DEVICE_PREFERRED_INTEROP_USER_SYNC";
            break;
        case DeviceInfo::PrintfBufferSize:
            os << "CL_DEVICE_PRINTF_BUFFER_SIZE";
            break;
        case DeviceInfo::ImagePitchAlignment:
            os << "CL_DEVICE_IMAGE_PITCH_ALIGNMENT";
            break;
        case DeviceInfo::ImageBaseAddressAlignment:
            os << "CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT";
            break;
        case DeviceInfo::MaxReadWriteImageArgs:
            os << "CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS";
            break;
        case DeviceInfo::MaxGlobalVariableSize:
            os << "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE";
            break;
        case DeviceInfo::QueueOnDeviceProperties:
            os << "CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES";
            break;
        case DeviceInfo::QueueOnDevicePreferredSize:
            os << "CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE";
            break;
        case DeviceInfo::QueueOnDeviceMaxSize:
            os << "CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE";
            break;
        case DeviceInfo::MaxOnDeviceQueues:
            os << "CL_DEVICE_MAX_ON_DEVICE_QUEUES";
            break;
        case DeviceInfo::MaxOnDeviceEvents:
            os << "CL_DEVICE_MAX_ON_DEVICE_EVENTS";
            break;
        case DeviceInfo::SVM_Capabilities:
            os << "CL_DEVICE_SVM_CAPABILITIES";
            break;
        case DeviceInfo::GlobalVariablePreferredTotalSize:
            os << "CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE";
            break;
        case DeviceInfo::MaxPipeArgs:
            os << "CL_DEVICE_MAX_PIPE_ARGS";
            break;
        case DeviceInfo::PipeMaxActiveReservations:
            os << "CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS";
            break;
        case DeviceInfo::PipeMaxPacketSize:
            os << "CL_DEVICE_PIPE_MAX_PACKET_SIZE";
            break;
        case DeviceInfo::PreferredPlatformAtomicAlignment:
            os << "CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT";
            break;
        case DeviceInfo::PreferredGlobalAtomicAlignment:
            os << "CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT";
            break;
        case DeviceInfo::PreferredLocalAtomicAlignment:
            os << "CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT";
            break;
        case DeviceInfo::IL_Version:
            os << "CL_DEVICE_IL_VERSION";
            break;
        case DeviceInfo::MaxNumSubGroups:
            os << "CL_DEVICE_MAX_NUM_SUB_GROUPS";
            break;
        case DeviceInfo::SubGroupIndependentForwardProgress:
            os << "CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS";
            break;
        case DeviceInfo::NumericVersion:
            os << "CL_DEVICE_NUMERIC_VERSION";
            break;
        case DeviceInfo::ExtensionsWithVersion:
            os << "CL_DEVICE_EXTENSIONS_WITH_VERSION";
            break;
        case DeviceInfo::ILsWithVersion:
            os << "CL_DEVICE_ILS_WITH_VERSION";
            break;
        case DeviceInfo::BuiltInKernelsWithVersion:
            os << "CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION";
            break;
        case DeviceInfo::AtomicMemoryCapabilities:
            os << "CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES";
            break;
        case DeviceInfo::AtomicFenceCapabilities:
            os << "CL_DEVICE_ATOMIC_FENCE_CAPABILITIES";
            break;
        case DeviceInfo::NonUniformWorkGroupSupport:
            os << "CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT";
            break;
        case DeviceInfo::OpenCL_C_AllVersions:
            os << "CL_DEVICE_OPENCL_C_ALL_VERSIONS";
            break;
        case DeviceInfo::PreferredWorkGroupSizeMultiple:
            os << "CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE";
            break;
        case DeviceInfo::WorkGroupCollectiveFunctionsSupport:
            os << "CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT";
            break;
        case DeviceInfo::GenericAddressSpaceSupport:
            os << "CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT";
            break;
        case DeviceInfo::OpenCL_C_Features:
            os << "CL_DEVICE_OPENCL_C_FEATURES";
            break;
        case DeviceInfo::DeviceEnqueueCapabilities:
            os << "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES";
            break;
        case DeviceInfo::PipeSupport:
            os << "CL_DEVICE_PIPE_SUPPORT";
            break;
        case DeviceInfo::LatestConformanceVersionPassed:
            os << "CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED";
            break;
        case DeviceInfo::IntegerDotProductCapabilities:
            os << "CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR";
            break;
        case DeviceInfo::IntegerDotProductAccelerationProperties8bit:
            os << "CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR";
            break;
        case DeviceInfo::IntegerDotProductAccelerationProperties4x8bitPacked:
            os << "CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR";
            break;
        case DeviceInfo::ExternalMemoryImportHandleTypes:
            os << "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR";
            break;
        case DeviceInfo::ExternalMemoryLinearImagesHandleTypes:
            os << "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
EventInfo FromCLenum<EventInfo>(CLenum from)
{
    switch (from)
    {
        case CL_EVENT_COMMAND_QUEUE:
            return EventInfo::CommandQueue;
        case CL_EVENT_COMMAND_TYPE:
            return EventInfo::CommandType;
        case CL_EVENT_REFERENCE_COUNT:
            return EventInfo::ReferenceCount;
        case CL_EVENT_COMMAND_EXECUTION_STATUS:
            return EventInfo::CommandExecutionStatus;
        case CL_EVENT_CONTEXT:
            return EventInfo::Context;
        default:
            return EventInfo::InvalidEnum;
    }
}

CLenum ToCLenum(EventInfo from)
{
    switch (from)
    {
        case EventInfo::CommandQueue:
            return CL_EVENT_COMMAND_QUEUE;
        case EventInfo::CommandType:
            return CL_EVENT_COMMAND_TYPE;
        case EventInfo::ReferenceCount:
            return CL_EVENT_REFERENCE_COUNT;
        case EventInfo::CommandExecutionStatus:
            return CL_EVENT_COMMAND_EXECUTION_STATUS;
        case EventInfo::Context:
            return CL_EVENT_CONTEXT;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, EventInfo value)
{
    switch (value)
    {
        case EventInfo::CommandQueue:
            os << "CL_EVENT_COMMAND_QUEUE";
            break;
        case EventInfo::CommandType:
            os << "CL_EVENT_COMMAND_TYPE";
            break;
        case EventInfo::ReferenceCount:
            os << "CL_EVENT_REFERENCE_COUNT";
            break;
        case EventInfo::CommandExecutionStatus:
            os << "CL_EVENT_COMMAND_EXECUTION_STATUS";
            break;
        case EventInfo::Context:
            os << "CL_EVENT_CONTEXT";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ExecutionStatus FromCLenum<ExecutionStatus>(CLenum from)
{
    switch (from)
    {
        case CL_COMPLETE:
            return ExecutionStatus::Complete;
        case CL_RUNNING:
            return ExecutionStatus::Running;
        case CL_SUBMITTED:
            return ExecutionStatus::Submitted;
        case CL_QUEUED:
            return ExecutionStatus::Queued;
        default:
            return ExecutionStatus::InvalidEnum;
    }
}

CLenum ToCLenum(ExecutionStatus from)
{
    switch (from)
    {
        case ExecutionStatus::Complete:
            return CL_COMPLETE;
        case ExecutionStatus::Running:
            return CL_RUNNING;
        case ExecutionStatus::Submitted:
            return CL_SUBMITTED;
        case ExecutionStatus::Queued:
            return CL_QUEUED;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ExecutionStatus value)
{
    switch (value)
    {
        case ExecutionStatus::Complete:
            os << "CL_COMPLETE";
            break;
        case ExecutionStatus::Running:
            os << "CL_RUNNING";
            break;
        case ExecutionStatus::Submitted:
            os << "CL_SUBMITTED";
            break;
        case ExecutionStatus::Queued:
            os << "CL_QUEUED";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ExternalMemoryHandle FromCLenum<ExternalMemoryHandle>(CLenum from)
{
    switch (from)
    {
        case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR:
            return ExternalMemoryHandle::OpaqueFd;
        case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR:
            return ExternalMemoryHandle::OpaqueWin32;
        case CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR:
            return ExternalMemoryHandle::OpaqueWin32Kmt;
        case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR:
            return ExternalMemoryHandle::DmaBuf;
        default:
            return ExternalMemoryHandle::InvalidEnum;
    }
}

CLenum ToCLenum(ExternalMemoryHandle from)
{
    switch (from)
    {
        case ExternalMemoryHandle::OpaqueFd:
            return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR;
        case ExternalMemoryHandle::OpaqueWin32:
            return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR;
        case ExternalMemoryHandle::OpaqueWin32Kmt:
            return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR;
        case ExternalMemoryHandle::DmaBuf:
            return CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ExternalMemoryHandle value)
{
    switch (value)
    {
        case ExternalMemoryHandle::OpaqueFd:
            os << "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR";
            break;
        case ExternalMemoryHandle::OpaqueWin32:
            os << "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR";
            break;
        case ExternalMemoryHandle::OpaqueWin32Kmt:
            os << "CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR";
            break;
        case ExternalMemoryHandle::DmaBuf:
            os << "CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
FilterMode FromCLenum<FilterMode>(CLenum from)
{
    switch (from)
    {
        case CL_FILTER_NEAREST:
            return FilterMode::Nearest;
        case CL_FILTER_LINEAR:
            return FilterMode::Linear;
        default:
            return FilterMode::InvalidEnum;
    }
}

CLenum ToCLenum(FilterMode from)
{
    switch (from)
    {
        case FilterMode::Nearest:
            return CL_FILTER_NEAREST;
        case FilterMode::Linear:
            return CL_FILTER_LINEAR;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, FilterMode value)
{
    switch (value)
    {
        case FilterMode::Nearest:
            os << "CL_FILTER_NEAREST";
            break;
        case FilterMode::Linear:
            os << "CL_FILTER_LINEAR";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ImageChannelOrder FromCLenum<ImageChannelOrder>(CLenum from)
{
    switch (from)
    {
        case CL_R:
            return ImageChannelOrder::R;
        case CL_A:
            return ImageChannelOrder::A;
        case CL_RG:
            return ImageChannelOrder::RG;
        case CL_RA:
            return ImageChannelOrder::RA;
        case CL_RGB:
            return ImageChannelOrder::RGB;
        case CL_RGBA:
            return ImageChannelOrder::RGBA;
        case CL_BGRA:
            return ImageChannelOrder::BGRA;
        case CL_ARGB:
            return ImageChannelOrder::ARGB;
        case CL_INTENSITY:
            return ImageChannelOrder::Intensity;
        case CL_LUMINANCE:
            return ImageChannelOrder::Luminance;
        case CL_Rx:
            return ImageChannelOrder::Rx;
        case CL_RGx:
            return ImageChannelOrder::RGx;
        case CL_RGBx:
            return ImageChannelOrder::RGBx;
        case CL_DEPTH:
            return ImageChannelOrder::Depth;
        case CL_sRGB:
            return ImageChannelOrder::sRGB;
        case CL_sRGBx:
            return ImageChannelOrder::sRGBx;
        case CL_sRGBA:
            return ImageChannelOrder::sRGBA;
        case CL_sBGRA:
            return ImageChannelOrder::sBGRA;
        case CL_ABGR:
            return ImageChannelOrder::ABGR;
        default:
            return ImageChannelOrder::InvalidEnum;
    }
}

CLenum ToCLenum(ImageChannelOrder from)
{
    switch (from)
    {
        case ImageChannelOrder::R:
            return CL_R;
        case ImageChannelOrder::A:
            return CL_A;
        case ImageChannelOrder::RG:
            return CL_RG;
        case ImageChannelOrder::RA:
            return CL_RA;
        case ImageChannelOrder::RGB:
            return CL_RGB;
        case ImageChannelOrder::RGBA:
            return CL_RGBA;
        case ImageChannelOrder::BGRA:
            return CL_BGRA;
        case ImageChannelOrder::ARGB:
            return CL_ARGB;
        case ImageChannelOrder::Intensity:
            return CL_INTENSITY;
        case ImageChannelOrder::Luminance:
            return CL_LUMINANCE;
        case ImageChannelOrder::Rx:
            return CL_Rx;
        case ImageChannelOrder::RGx:
            return CL_RGx;
        case ImageChannelOrder::RGBx:
            return CL_RGBx;
        case ImageChannelOrder::Depth:
            return CL_DEPTH;
        case ImageChannelOrder::sRGB:
            return CL_sRGB;
        case ImageChannelOrder::sRGBx:
            return CL_sRGBx;
        case ImageChannelOrder::sRGBA:
            return CL_sRGBA;
        case ImageChannelOrder::sBGRA:
            return CL_sBGRA;
        case ImageChannelOrder::ABGR:
            return CL_ABGR;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ImageChannelOrder value)
{
    switch (value)
    {
        case ImageChannelOrder::R:
            os << "CL_R";
            break;
        case ImageChannelOrder::A:
            os << "CL_A";
            break;
        case ImageChannelOrder::RG:
            os << "CL_RG";
            break;
        case ImageChannelOrder::RA:
            os << "CL_RA";
            break;
        case ImageChannelOrder::RGB:
            os << "CL_RGB";
            break;
        case ImageChannelOrder::RGBA:
            os << "CL_RGBA";
            break;
        case ImageChannelOrder::BGRA:
            os << "CL_BGRA";
            break;
        case ImageChannelOrder::ARGB:
            os << "CL_ARGB";
            break;
        case ImageChannelOrder::Intensity:
            os << "CL_INTENSITY";
            break;
        case ImageChannelOrder::Luminance:
            os << "CL_LUMINANCE";
            break;
        case ImageChannelOrder::Rx:
            os << "CL_Rx";
            break;
        case ImageChannelOrder::RGx:
            os << "CL_RGx";
            break;
        case ImageChannelOrder::RGBx:
            os << "CL_RGBx";
            break;
        case ImageChannelOrder::Depth:
            os << "CL_DEPTH";
            break;
        case ImageChannelOrder::sRGB:
            os << "CL_sRGB";
            break;
        case ImageChannelOrder::sRGBx:
            os << "CL_sRGBx";
            break;
        case ImageChannelOrder::sRGBA:
            os << "CL_sRGBA";
            break;
        case ImageChannelOrder::sBGRA:
            os << "CL_sBGRA";
            break;
        case ImageChannelOrder::ABGR:
            os << "CL_ABGR";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ImageChannelType FromCLenum<ImageChannelType>(CLenum from)
{
    switch (from)
    {
        case CL_SNORM_INT8:
            return ImageChannelType::SnormInt8;
        case CL_SNORM_INT16:
            return ImageChannelType::SnormInt16;
        case CL_UNORM_INT8:
            return ImageChannelType::UnormInt8;
        case CL_UNORM_INT16:
            return ImageChannelType::UnormInt16;
        case CL_UNORM_SHORT_565:
            return ImageChannelType::UnormShort565;
        case CL_UNORM_SHORT_555:
            return ImageChannelType::UnormShort555;
        case CL_UNORM_INT_101010:
            return ImageChannelType::UnormInt101010;
        case CL_SIGNED_INT8:
            return ImageChannelType::SignedInt8;
        case CL_SIGNED_INT16:
            return ImageChannelType::SignedInt16;
        case CL_SIGNED_INT32:
            return ImageChannelType::SignedInt32;
        case CL_UNSIGNED_INT8:
            return ImageChannelType::UnsignedInt8;
        case CL_UNSIGNED_INT16:
            return ImageChannelType::UnsignedInt16;
        case CL_UNSIGNED_INT32:
            return ImageChannelType::UnsignedInt32;
        case CL_HALF_FLOAT:
            return ImageChannelType::HalfFloat;
        case CL_FLOAT:
            return ImageChannelType::Float;
        case CL_UNORM_INT_101010_2:
            return ImageChannelType::UnormInt101010_2;
        default:
            return ImageChannelType::InvalidEnum;
    }
}

CLenum ToCLenum(ImageChannelType from)
{
    switch (from)
    {
        case ImageChannelType::SnormInt8:
            return CL_SNORM_INT8;
        case ImageChannelType::SnormInt16:
            return CL_SNORM_INT16;
        case ImageChannelType::UnormInt8:
            return CL_UNORM_INT8;
        case ImageChannelType::UnormInt16:
            return CL_UNORM_INT16;
        case ImageChannelType::UnormShort565:
            return CL_UNORM_SHORT_565;
        case ImageChannelType::UnormShort555:
            return CL_UNORM_SHORT_555;
        case ImageChannelType::UnormInt101010:
            return CL_UNORM_INT_101010;
        case ImageChannelType::SignedInt8:
            return CL_SIGNED_INT8;
        case ImageChannelType::SignedInt16:
            return CL_SIGNED_INT16;
        case ImageChannelType::SignedInt32:
            return CL_SIGNED_INT32;
        case ImageChannelType::UnsignedInt8:
            return CL_UNSIGNED_INT8;
        case ImageChannelType::UnsignedInt16:
            return CL_UNSIGNED_INT16;
        case ImageChannelType::UnsignedInt32:
            return CL_UNSIGNED_INT32;
        case ImageChannelType::HalfFloat:
            return CL_HALF_FLOAT;
        case ImageChannelType::Float:
            return CL_FLOAT;
        case ImageChannelType::UnormInt101010_2:
            return CL_UNORM_INT_101010_2;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ImageChannelType value)
{
    switch (value)
    {
        case ImageChannelType::SnormInt8:
            os << "CL_SNORM_INT8";
            break;
        case ImageChannelType::SnormInt16:
            os << "CL_SNORM_INT16";
            break;
        case ImageChannelType::UnormInt8:
            os << "CL_UNORM_INT8";
            break;
        case ImageChannelType::UnormInt16:
            os << "CL_UNORM_INT16";
            break;
        case ImageChannelType::UnormShort565:
            os << "CL_UNORM_SHORT_565";
            break;
        case ImageChannelType::UnormShort555:
            os << "CL_UNORM_SHORT_555";
            break;
        case ImageChannelType::UnormInt101010:
            os << "CL_UNORM_INT_101010";
            break;
        case ImageChannelType::SignedInt8:
            os << "CL_SIGNED_INT8";
            break;
        case ImageChannelType::SignedInt16:
            os << "CL_SIGNED_INT16";
            break;
        case ImageChannelType::SignedInt32:
            os << "CL_SIGNED_INT32";
            break;
        case ImageChannelType::UnsignedInt8:
            os << "CL_UNSIGNED_INT8";
            break;
        case ImageChannelType::UnsignedInt16:
            os << "CL_UNSIGNED_INT16";
            break;
        case ImageChannelType::UnsignedInt32:
            os << "CL_UNSIGNED_INT32";
            break;
        case ImageChannelType::HalfFloat:
            os << "CL_HALF_FLOAT";
            break;
        case ImageChannelType::Float:
            os << "CL_FLOAT";
            break;
        case ImageChannelType::UnormInt101010_2:
            os << "CL_UNORM_INT_101010_2";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ImageInfo FromCLenum<ImageInfo>(CLenum from)
{
    switch (from)
    {
        case CL_IMAGE_FORMAT:
            return ImageInfo::Format;
        case CL_IMAGE_ELEMENT_SIZE:
            return ImageInfo::ElementSize;
        case CL_IMAGE_ROW_PITCH:
            return ImageInfo::RowPitch;
        case CL_IMAGE_SLICE_PITCH:
            return ImageInfo::SlicePitch;
        case CL_IMAGE_WIDTH:
            return ImageInfo::Width;
        case CL_IMAGE_HEIGHT:
            return ImageInfo::Height;
        case CL_IMAGE_DEPTH:
            return ImageInfo::Depth;
        case CL_IMAGE_ARRAY_SIZE:
            return ImageInfo::ArraySize;
        case CL_IMAGE_BUFFER:
            return ImageInfo::Buffer;
        case CL_IMAGE_NUM_MIP_LEVELS:
            return ImageInfo::NumMipLevels;
        case CL_IMAGE_NUM_SAMPLES:
            return ImageInfo::NumSamples;
        default:
            return ImageInfo::InvalidEnum;
    }
}

CLenum ToCLenum(ImageInfo from)
{
    switch (from)
    {
        case ImageInfo::Format:
            return CL_IMAGE_FORMAT;
        case ImageInfo::ElementSize:
            return CL_IMAGE_ELEMENT_SIZE;
        case ImageInfo::RowPitch:
            return CL_IMAGE_ROW_PITCH;
        case ImageInfo::SlicePitch:
            return CL_IMAGE_SLICE_PITCH;
        case ImageInfo::Width:
            return CL_IMAGE_WIDTH;
        case ImageInfo::Height:
            return CL_IMAGE_HEIGHT;
        case ImageInfo::Depth:
            return CL_IMAGE_DEPTH;
        case ImageInfo::ArraySize:
            return CL_IMAGE_ARRAY_SIZE;
        case ImageInfo::Buffer:
            return CL_IMAGE_BUFFER;
        case ImageInfo::NumMipLevels:
            return CL_IMAGE_NUM_MIP_LEVELS;
        case ImageInfo::NumSamples:
            return CL_IMAGE_NUM_SAMPLES;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ImageInfo value)
{
    switch (value)
    {
        case ImageInfo::Format:
            os << "CL_IMAGE_FORMAT";
            break;
        case ImageInfo::ElementSize:
            os << "CL_IMAGE_ELEMENT_SIZE";
            break;
        case ImageInfo::RowPitch:
            os << "CL_IMAGE_ROW_PITCH";
            break;
        case ImageInfo::SlicePitch:
            os << "CL_IMAGE_SLICE_PITCH";
            break;
        case ImageInfo::Width:
            os << "CL_IMAGE_WIDTH";
            break;
        case ImageInfo::Height:
            os << "CL_IMAGE_HEIGHT";
            break;
        case ImageInfo::Depth:
            os << "CL_IMAGE_DEPTH";
            break;
        case ImageInfo::ArraySize:
            os << "CL_IMAGE_ARRAY_SIZE";
            break;
        case ImageInfo::Buffer:
            os << "CL_IMAGE_BUFFER";
            break;
        case ImageInfo::NumMipLevels:
            os << "CL_IMAGE_NUM_MIP_LEVELS";
            break;
        case ImageInfo::NumSamples:
            os << "CL_IMAGE_NUM_SAMPLES";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
KernelArgInfo FromCLenum<KernelArgInfo>(CLenum from)
{
    switch (from)
    {
        case CL_KERNEL_ARG_ADDRESS_QUALIFIER:
            return KernelArgInfo::AddressQualifier;
        case CL_KERNEL_ARG_ACCESS_QUALIFIER:
            return KernelArgInfo::AccessQualifier;
        case CL_KERNEL_ARG_TYPE_NAME:
            return KernelArgInfo::TypeName;
        case CL_KERNEL_ARG_TYPE_QUALIFIER:
            return KernelArgInfo::TypeQualifier;
        case CL_KERNEL_ARG_NAME:
            return KernelArgInfo::Name;
        default:
            return KernelArgInfo::InvalidEnum;
    }
}

CLenum ToCLenum(KernelArgInfo from)
{
    switch (from)
    {
        case KernelArgInfo::AddressQualifier:
            return CL_KERNEL_ARG_ADDRESS_QUALIFIER;
        case KernelArgInfo::AccessQualifier:
            return CL_KERNEL_ARG_ACCESS_QUALIFIER;
        case KernelArgInfo::TypeName:
            return CL_KERNEL_ARG_TYPE_NAME;
        case KernelArgInfo::TypeQualifier:
            return CL_KERNEL_ARG_TYPE_QUALIFIER;
        case KernelArgInfo::Name:
            return CL_KERNEL_ARG_NAME;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, KernelArgInfo value)
{
    switch (value)
    {
        case KernelArgInfo::AddressQualifier:
            os << "CL_KERNEL_ARG_ADDRESS_QUALIFIER";
            break;
        case KernelArgInfo::AccessQualifier:
            os << "CL_KERNEL_ARG_ACCESS_QUALIFIER";
            break;
        case KernelArgInfo::TypeName:
            os << "CL_KERNEL_ARG_TYPE_NAME";
            break;
        case KernelArgInfo::TypeQualifier:
            os << "CL_KERNEL_ARG_TYPE_QUALIFIER";
            break;
        case KernelArgInfo::Name:
            os << "CL_KERNEL_ARG_NAME";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
KernelExecInfo FromCLenum<KernelExecInfo>(CLenum from)
{
    switch (from)
    {
        case CL_KERNEL_EXEC_INFO_SVM_PTRS:
            return KernelExecInfo::SVM_Ptrs;
        case CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM:
            return KernelExecInfo::SVM_FineGrainSystem;
        default:
            return KernelExecInfo::InvalidEnum;
    }
}

CLenum ToCLenum(KernelExecInfo from)
{
    switch (from)
    {
        case KernelExecInfo::SVM_Ptrs:
            return CL_KERNEL_EXEC_INFO_SVM_PTRS;
        case KernelExecInfo::SVM_FineGrainSystem:
            return CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, KernelExecInfo value)
{
    switch (value)
    {
        case KernelExecInfo::SVM_Ptrs:
            os << "CL_KERNEL_EXEC_INFO_SVM_PTRS";
            break;
        case KernelExecInfo::SVM_FineGrainSystem:
            os << "CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
KernelInfo FromCLenum<KernelInfo>(CLenum from)
{
    switch (from)
    {
        case CL_KERNEL_FUNCTION_NAME:
            return KernelInfo::FunctionName;
        case CL_KERNEL_NUM_ARGS:
            return KernelInfo::NumArgs;
        case CL_KERNEL_REFERENCE_COUNT:
            return KernelInfo::ReferenceCount;
        case CL_KERNEL_CONTEXT:
            return KernelInfo::Context;
        case CL_KERNEL_PROGRAM:
            return KernelInfo::Program;
        case CL_KERNEL_ATTRIBUTES:
            return KernelInfo::Attributes;
        default:
            return KernelInfo::InvalidEnum;
    }
}

CLenum ToCLenum(KernelInfo from)
{
    switch (from)
    {
        case KernelInfo::FunctionName:
            return CL_KERNEL_FUNCTION_NAME;
        case KernelInfo::NumArgs:
            return CL_KERNEL_NUM_ARGS;
        case KernelInfo::ReferenceCount:
            return CL_KERNEL_REFERENCE_COUNT;
        case KernelInfo::Context:
            return CL_KERNEL_CONTEXT;
        case KernelInfo::Program:
            return CL_KERNEL_PROGRAM;
        case KernelInfo::Attributes:
            return CL_KERNEL_ATTRIBUTES;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, KernelInfo value)
{
    switch (value)
    {
        case KernelInfo::FunctionName:
            os << "CL_KERNEL_FUNCTION_NAME";
            break;
        case KernelInfo::NumArgs:
            os << "CL_KERNEL_NUM_ARGS";
            break;
        case KernelInfo::ReferenceCount:
            os << "CL_KERNEL_REFERENCE_COUNT";
            break;
        case KernelInfo::Context:
            os << "CL_KERNEL_CONTEXT";
            break;
        case KernelInfo::Program:
            os << "CL_KERNEL_PROGRAM";
            break;
        case KernelInfo::Attributes:
            os << "CL_KERNEL_ATTRIBUTES";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
KernelSubGroupInfo FromCLenum<KernelSubGroupInfo>(CLenum from)
{
    switch (from)
    {
        case CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE:
            return KernelSubGroupInfo::MaxSubGroupSizeForNdrange;
        case CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE:
            return KernelSubGroupInfo::SubGroupCountForNdrange;
        case CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT:
            return KernelSubGroupInfo::LocalSizeForSubGroupCount;
        case CL_KERNEL_MAX_NUM_SUB_GROUPS:
            return KernelSubGroupInfo::MaxNumSubGroups;
        case CL_KERNEL_COMPILE_NUM_SUB_GROUPS:
            return KernelSubGroupInfo::CompileNumSubGroups;
        default:
            return KernelSubGroupInfo::InvalidEnum;
    }
}

CLenum ToCLenum(KernelSubGroupInfo from)
{
    switch (from)
    {
        case KernelSubGroupInfo::MaxSubGroupSizeForNdrange:
            return CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE;
        case KernelSubGroupInfo::SubGroupCountForNdrange:
            return CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE;
        case KernelSubGroupInfo::LocalSizeForSubGroupCount:
            return CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT;
        case KernelSubGroupInfo::MaxNumSubGroups:
            return CL_KERNEL_MAX_NUM_SUB_GROUPS;
        case KernelSubGroupInfo::CompileNumSubGroups:
            return CL_KERNEL_COMPILE_NUM_SUB_GROUPS;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, KernelSubGroupInfo value)
{
    switch (value)
    {
        case KernelSubGroupInfo::MaxSubGroupSizeForNdrange:
            os << "CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE";
            break;
        case KernelSubGroupInfo::SubGroupCountForNdrange:
            os << "CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE";
            break;
        case KernelSubGroupInfo::LocalSizeForSubGroupCount:
            os << "CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT";
            break;
        case KernelSubGroupInfo::MaxNumSubGroups:
            os << "CL_KERNEL_MAX_NUM_SUB_GROUPS";
            break;
        case KernelSubGroupInfo::CompileNumSubGroups:
            os << "CL_KERNEL_COMPILE_NUM_SUB_GROUPS";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
KernelWorkGroupInfo FromCLenum<KernelWorkGroupInfo>(CLenum from)
{
    switch (from)
    {
        case CL_KERNEL_WORK_GROUP_SIZE:
            return KernelWorkGroupInfo::WorkGroupSize;
        case CL_KERNEL_COMPILE_WORK_GROUP_SIZE:
            return KernelWorkGroupInfo::CompileWorkGroupSize;
        case CL_KERNEL_LOCAL_MEM_SIZE:
            return KernelWorkGroupInfo::LocalMemSize;
        case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE:
            return KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple;
        case CL_KERNEL_PRIVATE_MEM_SIZE:
            return KernelWorkGroupInfo::PrivateMemSize;
        case CL_KERNEL_GLOBAL_WORK_SIZE:
            return KernelWorkGroupInfo::GlobalWorkSize;
        default:
            return KernelWorkGroupInfo::InvalidEnum;
    }
}

CLenum ToCLenum(KernelWorkGroupInfo from)
{
    switch (from)
    {
        case KernelWorkGroupInfo::WorkGroupSize:
            return CL_KERNEL_WORK_GROUP_SIZE;
        case KernelWorkGroupInfo::CompileWorkGroupSize:
            return CL_KERNEL_COMPILE_WORK_GROUP_SIZE;
        case KernelWorkGroupInfo::LocalMemSize:
            return CL_KERNEL_LOCAL_MEM_SIZE;
        case KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple:
            return CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE;
        case KernelWorkGroupInfo::PrivateMemSize:
            return CL_KERNEL_PRIVATE_MEM_SIZE;
        case KernelWorkGroupInfo::GlobalWorkSize:
            return CL_KERNEL_GLOBAL_WORK_SIZE;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, KernelWorkGroupInfo value)
{
    switch (value)
    {
        case KernelWorkGroupInfo::WorkGroupSize:
            os << "CL_KERNEL_WORK_GROUP_SIZE";
            break;
        case KernelWorkGroupInfo::CompileWorkGroupSize:
            os << "CL_KERNEL_COMPILE_WORK_GROUP_SIZE";
            break;
        case KernelWorkGroupInfo::LocalMemSize:
            os << "CL_KERNEL_LOCAL_MEM_SIZE";
            break;
        case KernelWorkGroupInfo::PreferredWorkGroupSizeMultiple:
            os << "CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE";
            break;
        case KernelWorkGroupInfo::PrivateMemSize:
            os << "CL_KERNEL_PRIVATE_MEM_SIZE";
            break;
        case KernelWorkGroupInfo::GlobalWorkSize:
            os << "CL_KERNEL_GLOBAL_WORK_SIZE";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
MemInfo FromCLenum<MemInfo>(CLenum from)
{
    switch (from)
    {
        case CL_MEM_TYPE:
            return MemInfo::Type;
        case CL_MEM_FLAGS:
            return MemInfo::Flags;
        case CL_MEM_SIZE:
            return MemInfo::Size;
        case CL_MEM_HOST_PTR:
            return MemInfo::HostPtr;
        case CL_MEM_MAP_COUNT:
            return MemInfo::MapCount;
        case CL_MEM_REFERENCE_COUNT:
            return MemInfo::ReferenceCount;
        case CL_MEM_CONTEXT:
            return MemInfo::Context;
        case CL_MEM_ASSOCIATED_MEMOBJECT:
            return MemInfo::AssociatedMemObject;
        case CL_MEM_OFFSET:
            return MemInfo::Offset;
        case CL_MEM_USES_SVM_POINTER:
            return MemInfo::UsesSVM_Pointer;
        case CL_MEM_PROPERTIES:
            return MemInfo::Properties;
        default:
            return MemInfo::InvalidEnum;
    }
}

CLenum ToCLenum(MemInfo from)
{
    switch (from)
    {
        case MemInfo::Type:
            return CL_MEM_TYPE;
        case MemInfo::Flags:
            return CL_MEM_FLAGS;
        case MemInfo::Size:
            return CL_MEM_SIZE;
        case MemInfo::HostPtr:
            return CL_MEM_HOST_PTR;
        case MemInfo::MapCount:
            return CL_MEM_MAP_COUNT;
        case MemInfo::ReferenceCount:
            return CL_MEM_REFERENCE_COUNT;
        case MemInfo::Context:
            return CL_MEM_CONTEXT;
        case MemInfo::AssociatedMemObject:
            return CL_MEM_ASSOCIATED_MEMOBJECT;
        case MemInfo::Offset:
            return CL_MEM_OFFSET;
        case MemInfo::UsesSVM_Pointer:
            return CL_MEM_USES_SVM_POINTER;
        case MemInfo::Properties:
            return CL_MEM_PROPERTIES;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, MemInfo value)
{
    switch (value)
    {
        case MemInfo::Type:
            os << "CL_MEM_TYPE";
            break;
        case MemInfo::Flags:
            os << "CL_MEM_FLAGS";
            break;
        case MemInfo::Size:
            os << "CL_MEM_SIZE";
            break;
        case MemInfo::HostPtr:
            os << "CL_MEM_HOST_PTR";
            break;
        case MemInfo::MapCount:
            os << "CL_MEM_MAP_COUNT";
            break;
        case MemInfo::ReferenceCount:
            os << "CL_MEM_REFERENCE_COUNT";
            break;
        case MemInfo::Context:
            os << "CL_MEM_CONTEXT";
            break;
        case MemInfo::AssociatedMemObject:
            os << "CL_MEM_ASSOCIATED_MEMOBJECT";
            break;
        case MemInfo::Offset:
            os << "CL_MEM_OFFSET";
            break;
        case MemInfo::UsesSVM_Pointer:
            os << "CL_MEM_USES_SVM_POINTER";
            break;
        case MemInfo::Properties:
            os << "CL_MEM_PROPERTIES";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
MemObjectType FromCLenum<MemObjectType>(CLenum from)
{
    switch (from)
    {
        case CL_MEM_OBJECT_BUFFER:
            return MemObjectType::Buffer;
        case CL_MEM_OBJECT_IMAGE2D:
            return MemObjectType::Image2D;
        case CL_MEM_OBJECT_IMAGE3D:
            return MemObjectType::Image3D;
        case CL_MEM_OBJECT_IMAGE2D_ARRAY:
            return MemObjectType::Image2D_Array;
        case CL_MEM_OBJECT_IMAGE1D:
            return MemObjectType::Image1D;
        case CL_MEM_OBJECT_IMAGE1D_ARRAY:
            return MemObjectType::Image1D_Array;
        case CL_MEM_OBJECT_IMAGE1D_BUFFER:
            return MemObjectType::Image1D_Buffer;
        case CL_MEM_OBJECT_PIPE:
            return MemObjectType::Pipe;
        default:
            return MemObjectType::InvalidEnum;
    }
}

CLenum ToCLenum(MemObjectType from)
{
    switch (from)
    {
        case MemObjectType::Buffer:
            return CL_MEM_OBJECT_BUFFER;
        case MemObjectType::Image2D:
            return CL_MEM_OBJECT_IMAGE2D;
        case MemObjectType::Image3D:
            return CL_MEM_OBJECT_IMAGE3D;
        case MemObjectType::Image2D_Array:
            return CL_MEM_OBJECT_IMAGE2D_ARRAY;
        case MemObjectType::Image1D:
            return CL_MEM_OBJECT_IMAGE1D;
        case MemObjectType::Image1D_Array:
            return CL_MEM_OBJECT_IMAGE1D_ARRAY;
        case MemObjectType::Image1D_Buffer:
            return CL_MEM_OBJECT_IMAGE1D_BUFFER;
        case MemObjectType::Pipe:
            return CL_MEM_OBJECT_PIPE;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, MemObjectType value)
{
    switch (value)
    {
        case MemObjectType::Buffer:
            os << "CL_MEM_OBJECT_BUFFER";
            break;
        case MemObjectType::Image2D:
            os << "CL_MEM_OBJECT_IMAGE2D";
            break;
        case MemObjectType::Image3D:
            os << "CL_MEM_OBJECT_IMAGE3D";
            break;
        case MemObjectType::Image2D_Array:
            os << "CL_MEM_OBJECT_IMAGE2D_ARRAY";
            break;
        case MemObjectType::Image1D:
            os << "CL_MEM_OBJECT_IMAGE1D";
            break;
        case MemObjectType::Image1D_Array:
            os << "CL_MEM_OBJECT_IMAGE1D_ARRAY";
            break;
        case MemObjectType::Image1D_Buffer:
            os << "CL_MEM_OBJECT_IMAGE1D_BUFFER";
            break;
        case MemObjectType::Pipe:
            os << "CL_MEM_OBJECT_PIPE";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
MemProperties FromCLenum<MemProperties>(CLenum from)
{
    switch (from)
    {
        case CL_MEM_DEVICE_HANDLE_LIST_KHR:
            return MemProperties::ExternalMemoryHandleListStart;
        case CL_MEM_DEVICE_HANDLE_LIST_END_KHR:
            return MemProperties::ExternalMemoryHandleListEnd;
        default:
            return MemProperties::InvalidEnum;
    }
}

CLenum ToCLenum(MemProperties from)
{
    switch (from)
    {
        case MemProperties::ExternalMemoryHandleListStart:
            return CL_MEM_DEVICE_HANDLE_LIST_KHR;
        case MemProperties::ExternalMemoryHandleListEnd:
            return CL_MEM_DEVICE_HANDLE_LIST_END_KHR;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, MemProperties value)
{
    switch (value)
    {
        case MemProperties::ExternalMemoryHandleListStart:
            os << "CL_MEM_DEVICE_HANDLE_LIST_KHR";
            break;
        case MemProperties::ExternalMemoryHandleListEnd:
            os << "CL_MEM_DEVICE_HANDLE_LIST_END_KHR";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
PipeInfo FromCLenum<PipeInfo>(CLenum from)
{
    switch (from)
    {
        case CL_PIPE_PACKET_SIZE:
            return PipeInfo::PacketSize;
        case CL_PIPE_MAX_PACKETS:
            return PipeInfo::MaxPackets;
        case CL_PIPE_PROPERTIES:
            return PipeInfo::Properties;
        default:
            return PipeInfo::InvalidEnum;
    }
}

CLenum ToCLenum(PipeInfo from)
{
    switch (from)
    {
        case PipeInfo::PacketSize:
            return CL_PIPE_PACKET_SIZE;
        case PipeInfo::MaxPackets:
            return CL_PIPE_MAX_PACKETS;
        case PipeInfo::Properties:
            return CL_PIPE_PROPERTIES;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, PipeInfo value)
{
    switch (value)
    {
        case PipeInfo::PacketSize:
            os << "CL_PIPE_PACKET_SIZE";
            break;
        case PipeInfo::MaxPackets:
            os << "CL_PIPE_MAX_PACKETS";
            break;
        case PipeInfo::Properties:
            os << "CL_PIPE_PROPERTIES";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
PlatformInfo FromCLenum<PlatformInfo>(CLenum from)
{
    switch (from)
    {
        case CL_PLATFORM_PROFILE:
            return PlatformInfo::Profile;
        case CL_PLATFORM_VERSION:
            return PlatformInfo::Version;
        case CL_PLATFORM_NAME:
            return PlatformInfo::Name;
        case CL_PLATFORM_VENDOR:
            return PlatformInfo::Vendor;
        case CL_PLATFORM_EXTENSIONS:
            return PlatformInfo::Extensions;
        case CL_PLATFORM_HOST_TIMER_RESOLUTION:
            return PlatformInfo::HostTimerResolution;
        case CL_PLATFORM_NUMERIC_VERSION:
            return PlatformInfo::NumericVersion;
        case CL_PLATFORM_EXTENSIONS_WITH_VERSION:
            return PlatformInfo::ExtensionsWithVersion;
        case CL_PLATFORM_ICD_SUFFIX_KHR:
            return PlatformInfo::IcdSuffix;
        case CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR:
            return PlatformInfo::ExternalMemory;
        default:
            return PlatformInfo::InvalidEnum;
    }
}

CLenum ToCLenum(PlatformInfo from)
{
    switch (from)
    {
        case PlatformInfo::Profile:
            return CL_PLATFORM_PROFILE;
        case PlatformInfo::Version:
            return CL_PLATFORM_VERSION;
        case PlatformInfo::Name:
            return CL_PLATFORM_NAME;
        case PlatformInfo::Vendor:
            return CL_PLATFORM_VENDOR;
        case PlatformInfo::Extensions:
            return CL_PLATFORM_EXTENSIONS;
        case PlatformInfo::HostTimerResolution:
            return CL_PLATFORM_HOST_TIMER_RESOLUTION;
        case PlatformInfo::NumericVersion:
            return CL_PLATFORM_NUMERIC_VERSION;
        case PlatformInfo::ExtensionsWithVersion:
            return CL_PLATFORM_EXTENSIONS_WITH_VERSION;
        case PlatformInfo::IcdSuffix:
            return CL_PLATFORM_ICD_SUFFIX_KHR;
        case PlatformInfo::ExternalMemory:
            return CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, PlatformInfo value)
{
    switch (value)
    {
        case PlatformInfo::Profile:
            os << "CL_PLATFORM_PROFILE";
            break;
        case PlatformInfo::Version:
            os << "CL_PLATFORM_VERSION";
            break;
        case PlatformInfo::Name:
            os << "CL_PLATFORM_NAME";
            break;
        case PlatformInfo::Vendor:
            os << "CL_PLATFORM_VENDOR";
            break;
        case PlatformInfo::Extensions:
            os << "CL_PLATFORM_EXTENSIONS";
            break;
        case PlatformInfo::HostTimerResolution:
            os << "CL_PLATFORM_HOST_TIMER_RESOLUTION";
            break;
        case PlatformInfo::NumericVersion:
            os << "CL_PLATFORM_NUMERIC_VERSION";
            break;
        case PlatformInfo::ExtensionsWithVersion:
            os << "CL_PLATFORM_EXTENSIONS_WITH_VERSION";
            break;
        case PlatformInfo::IcdSuffix:
            os << "CL_PLATFORM_ICD_SUFFIX_KHR";
            break;
        case PlatformInfo::ExternalMemory:
            os << "CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ProfilingInfo FromCLenum<ProfilingInfo>(CLenum from)
{
    switch (from)
    {
        case CL_PROFILING_COMMAND_QUEUED:
            return ProfilingInfo::CommandQueued;
        case CL_PROFILING_COMMAND_SUBMIT:
            return ProfilingInfo::CommandSubmit;
        case CL_PROFILING_COMMAND_START:
            return ProfilingInfo::CommandStart;
        case CL_PROFILING_COMMAND_END:
            return ProfilingInfo::CommandEnd;
        case CL_PROFILING_COMMAND_COMPLETE:
            return ProfilingInfo::CommandComplete;
        default:
            return ProfilingInfo::InvalidEnum;
    }
}

CLenum ToCLenum(ProfilingInfo from)
{
    switch (from)
    {
        case ProfilingInfo::CommandQueued:
            return CL_PROFILING_COMMAND_QUEUED;
        case ProfilingInfo::CommandSubmit:
            return CL_PROFILING_COMMAND_SUBMIT;
        case ProfilingInfo::CommandStart:
            return CL_PROFILING_COMMAND_START;
        case ProfilingInfo::CommandEnd:
            return CL_PROFILING_COMMAND_END;
        case ProfilingInfo::CommandComplete:
            return CL_PROFILING_COMMAND_COMPLETE;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ProfilingInfo value)
{
    switch (value)
    {
        case ProfilingInfo::CommandQueued:
            os << "CL_PROFILING_COMMAND_QUEUED";
            break;
        case ProfilingInfo::CommandSubmit:
            os << "CL_PROFILING_COMMAND_SUBMIT";
            break;
        case ProfilingInfo::CommandStart:
            os << "CL_PROFILING_COMMAND_START";
            break;
        case ProfilingInfo::CommandEnd:
            os << "CL_PROFILING_COMMAND_END";
            break;
        case ProfilingInfo::CommandComplete:
            os << "CL_PROFILING_COMMAND_COMPLETE";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ProgramBuildInfo FromCLenum<ProgramBuildInfo>(CLenum from)
{
    switch (from)
    {
        case CL_PROGRAM_BUILD_STATUS:
            return ProgramBuildInfo::Status;
        case CL_PROGRAM_BUILD_OPTIONS:
            return ProgramBuildInfo::Options;
        case CL_PROGRAM_BUILD_LOG:
            return ProgramBuildInfo::Log;
        case CL_PROGRAM_BINARY_TYPE:
            return ProgramBuildInfo::BinaryType;
        case CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE:
            return ProgramBuildInfo::GlobalVariableTotalSize;
        default:
            return ProgramBuildInfo::InvalidEnum;
    }
}

CLenum ToCLenum(ProgramBuildInfo from)
{
    switch (from)
    {
        case ProgramBuildInfo::Status:
            return CL_PROGRAM_BUILD_STATUS;
        case ProgramBuildInfo::Options:
            return CL_PROGRAM_BUILD_OPTIONS;
        case ProgramBuildInfo::Log:
            return CL_PROGRAM_BUILD_LOG;
        case ProgramBuildInfo::BinaryType:
            return CL_PROGRAM_BINARY_TYPE;
        case ProgramBuildInfo::GlobalVariableTotalSize:
            return CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ProgramBuildInfo value)
{
    switch (value)
    {
        case ProgramBuildInfo::Status:
            os << "CL_PROGRAM_BUILD_STATUS";
            break;
        case ProgramBuildInfo::Options:
            os << "CL_PROGRAM_BUILD_OPTIONS";
            break;
        case ProgramBuildInfo::Log:
            os << "CL_PROGRAM_BUILD_LOG";
            break;
        case ProgramBuildInfo::BinaryType:
            os << "CL_PROGRAM_BINARY_TYPE";
            break;
        case ProgramBuildInfo::GlobalVariableTotalSize:
            os << "CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
ProgramInfo FromCLenum<ProgramInfo>(CLenum from)
{
    switch (from)
    {
        case CL_PROGRAM_REFERENCE_COUNT:
            return ProgramInfo::ReferenceCount;
        case CL_PROGRAM_CONTEXT:
            return ProgramInfo::Context;
        case CL_PROGRAM_NUM_DEVICES:
            return ProgramInfo::NumDevices;
        case CL_PROGRAM_DEVICES:
            return ProgramInfo::Devices;
        case CL_PROGRAM_SOURCE:
            return ProgramInfo::Source;
        case CL_PROGRAM_BINARY_SIZES:
            return ProgramInfo::BinarySizes;
        case CL_PROGRAM_BINARIES:
            return ProgramInfo::Binaries;
        case CL_PROGRAM_NUM_KERNELS:
            return ProgramInfo::NumKernels;
        case CL_PROGRAM_KERNEL_NAMES:
            return ProgramInfo::KernelNames;
        case CL_PROGRAM_IL:
            return ProgramInfo::IL;
        case CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT:
            return ProgramInfo::ScopeGlobalCtorsPresent;
        case CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT:
            return ProgramInfo::ScopeGlobalDtorsPresent;
        default:
            return ProgramInfo::InvalidEnum;
    }
}

CLenum ToCLenum(ProgramInfo from)
{
    switch (from)
    {
        case ProgramInfo::ReferenceCount:
            return CL_PROGRAM_REFERENCE_COUNT;
        case ProgramInfo::Context:
            return CL_PROGRAM_CONTEXT;
        case ProgramInfo::NumDevices:
            return CL_PROGRAM_NUM_DEVICES;
        case ProgramInfo::Devices:
            return CL_PROGRAM_DEVICES;
        case ProgramInfo::Source:
            return CL_PROGRAM_SOURCE;
        case ProgramInfo::BinarySizes:
            return CL_PROGRAM_BINARY_SIZES;
        case ProgramInfo::Binaries:
            return CL_PROGRAM_BINARIES;
        case ProgramInfo::NumKernels:
            return CL_PROGRAM_NUM_KERNELS;
        case ProgramInfo::KernelNames:
            return CL_PROGRAM_KERNEL_NAMES;
        case ProgramInfo::IL:
            return CL_PROGRAM_IL;
        case ProgramInfo::ScopeGlobalCtorsPresent:
            return CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT;
        case ProgramInfo::ScopeGlobalDtorsPresent:
            return CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, ProgramInfo value)
{
    switch (value)
    {
        case ProgramInfo::ReferenceCount:
            os << "CL_PROGRAM_REFERENCE_COUNT";
            break;
        case ProgramInfo::Context:
            os << "CL_PROGRAM_CONTEXT";
            break;
        case ProgramInfo::NumDevices:
            os << "CL_PROGRAM_NUM_DEVICES";
            break;
        case ProgramInfo::Devices:
            os << "CL_PROGRAM_DEVICES";
            break;
        case ProgramInfo::Source:
            os << "CL_PROGRAM_SOURCE";
            break;
        case ProgramInfo::BinarySizes:
            os << "CL_PROGRAM_BINARY_SIZES";
            break;
        case ProgramInfo::Binaries:
            os << "CL_PROGRAM_BINARIES";
            break;
        case ProgramInfo::NumKernels:
            os << "CL_PROGRAM_NUM_KERNELS";
            break;
        case ProgramInfo::KernelNames:
            os << "CL_PROGRAM_KERNEL_NAMES";
            break;
        case ProgramInfo::IL:
            os << "CL_PROGRAM_IL";
            break;
        case ProgramInfo::ScopeGlobalCtorsPresent:
            os << "CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT";
            break;
        case ProgramInfo::ScopeGlobalDtorsPresent:
            os << "CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

template <>
SamplerInfo FromCLenum<SamplerInfo>(CLenum from)
{
    switch (from)
    {
        case CL_SAMPLER_REFERENCE_COUNT:
            return SamplerInfo::ReferenceCount;
        case CL_SAMPLER_CONTEXT:
            return SamplerInfo::Context;
        case CL_SAMPLER_NORMALIZED_COORDS:
            return SamplerInfo::NormalizedCoords;
        case CL_SAMPLER_ADDRESSING_MODE:
            return SamplerInfo::AddressingMode;
        case CL_SAMPLER_FILTER_MODE:
            return SamplerInfo::FilterMode;
        case CL_SAMPLER_PROPERTIES:
            return SamplerInfo::Properties;
        default:
            return SamplerInfo::InvalidEnum;
    }
}

CLenum ToCLenum(SamplerInfo from)
{
    switch (from)
    {
        case SamplerInfo::ReferenceCount:
            return CL_SAMPLER_REFERENCE_COUNT;
        case SamplerInfo::Context:
            return CL_SAMPLER_CONTEXT;
        case SamplerInfo::NormalizedCoords:
            return CL_SAMPLER_NORMALIZED_COORDS;
        case SamplerInfo::AddressingMode:
            return CL_SAMPLER_ADDRESSING_MODE;
        case SamplerInfo::FilterMode:
            return CL_SAMPLER_FILTER_MODE;
        case SamplerInfo::Properties:
            return CL_SAMPLER_PROPERTIES;
        default:
            UNREACHABLE();
            return 0;
    }
}

std::ostream &operator<<(std::ostream &os, SamplerInfo value)
{
    switch (value)
    {
        case SamplerInfo::ReferenceCount:
            os << "CL_SAMPLER_REFERENCE_COUNT";
            break;
        case SamplerInfo::Context:
            os << "CL_SAMPLER_CONTEXT";
            break;
        case SamplerInfo::NormalizedCoords:
            os << "CL_SAMPLER_NORMALIZED_COORDS";
            break;
        case SamplerInfo::AddressingMode:
            os << "CL_SAMPLER_ADDRESSING_MODE";
            break;
        case SamplerInfo::FilterMode:
            os << "CL_SAMPLER_FILTER_MODE";
            break;
        case SamplerInfo::Properties:
            os << "CL_SAMPLER_PROPERTIES";
            break;
        default:
            os << "GL_INVALID_ENUM";
            break;
    }
    return os;
}

}  // namespace cl
