Edit

kc3-lang/angle/src/libGLESv2/cl_stubs.cpp

Branch :

  • Show log

    Commit

  • Author : John Plate
    Date : 2021-06-09 16:09:35
    Hash : 2c8d9a9a
    Message : CL: Remaining functions for OpenCL 1.2 Add support for the remaining functions for OpenCL 1.2 for the front end and pass-through back end. Also fix several bugs discovered by the conformance tests. Bug: angleproject:6015 Change-Id: I1dca1c3f4c1d9aea7f0501094c171116ea01381f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2954259 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Cody Northrop <cnorthrop@google.com> Commit-Queue: John Plate <jplate@google.com>

  • src/libGLESv2/cl_stubs.cpp
  • //
    // Copyright 2021 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // cl_stubs.cpp: Stubs for CL entry points.
    
    #include "libGLESv2/cl_stubs_autogen.h"
    
    #include "libGLESv2/proc_table_cl.h"
    
    #include "libANGLE/CLBuffer.h"
    #include "libANGLE/CLCommandQueue.h"
    #include "libANGLE/CLContext.h"
    #include "libANGLE/CLDevice.h"
    #include "libANGLE/CLEvent.h"
    #include "libANGLE/CLImage.h"
    #include "libANGLE/CLKernel.h"
    #include "libANGLE/CLMemory.h"
    #include "libANGLE/CLPlatform.h"
    #include "libANGLE/CLProgram.h"
    #include "libANGLE/CLSampler.h"
    
    #define WARN_NOT_SUPPORTED(command)                                         \
        do                                                                      \
        {                                                                       \
            static bool sWarned = false;                                        \
            if (!sWarned)                                                       \
            {                                                                   \
                sWarned = true;                                                 \
                WARN() << "OpenCL command " #command " is not (yet) supported"; \
            }                                                                   \
        } while (0)
    
    namespace cl
    {
    
    cl_int IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms)
    {
        return Platform::GetPlatformIDs(num_entries, platforms, num_platforms);
    }
    
    cl_int GetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms)
    {
        return Platform::GetPlatformIDs(num_entries, platforms, num_platforms);
    }
    
    cl_int GetPlatformInfo(cl_platform_id platform,
                           PlatformInfo param_name,
                           size_t param_value_size,
                           void *param_value,
                           size_t *param_value_size_ret)
    {
        return Platform::CastOrDefault(platform)->getInfo(param_name, param_value_size, param_value,
                                                          param_value_size_ret);
    }
    
    cl_int GetDeviceIDs(cl_platform_id platform,
                        DeviceType device_type,
                        cl_uint num_entries,
                        cl_device_id *devices,
                        cl_uint *num_devices)
    {
        return Platform::CastOrDefault(platform)->getDeviceIDs(device_type, num_entries, devices,
                                                               num_devices);
    }
    
    cl_int GetDeviceInfo(cl_device_id device,
                         DeviceInfo param_name,
                         size_t param_value_size,
                         void *param_value,
                         size_t *param_value_size_ret)
    {
        return device->cast<Device>().getInfo(param_name, param_value_size, param_value,
                                              param_value_size_ret);
    }
    
    cl_int CreateSubDevices(cl_device_id in_device,
                            const cl_device_partition_property *properties,
                            cl_uint num_devices,
                            cl_device_id *out_devices,
                            cl_uint *num_devices_ret)
    {
        return in_device->cast<Device>().createSubDevices(properties, num_devices, out_devices,
                                                          num_devices_ret);
    }
    
    cl_int RetainDevice(cl_device_id device)
    {
        Device &dev = device->cast<Device>();
        if (!dev.isRoot())
        {
            dev.retain();
        }
        return CL_SUCCESS;
    }
    
    cl_int ReleaseDevice(cl_device_id device)
    {
        Device &dev = device->cast<Device>();
        if (!dev.isRoot() && dev.release())
        {
            delete &dev;
        }
        return CL_SUCCESS;
    }
    
    cl_int SetDefaultDeviceCommandQueue(cl_context context,
                                        cl_device_id device,
                                        cl_command_queue command_queue)
    {
        WARN_NOT_SUPPORTED(SetDefaultDeviceCommandQueue);
        return 0;
    }
    
    cl_int GetDeviceAndHostTimer(cl_device_id device,
                                 cl_ulong *device_timestamp,
                                 cl_ulong *host_timestamp)
    {
        WARN_NOT_SUPPORTED(GetDeviceAndHostTimer);
        return 0;
    }
    
    cl_int GetHostTimer(cl_device_id device, cl_ulong *host_timestamp)
    {
        WARN_NOT_SUPPORTED(GetHostTimer);
        return 0;
    }
    
    cl_context CreateContext(const cl_context_properties *properties,
                             cl_uint num_devices,
                             const cl_device_id *devices,
                             void(CL_CALLBACK *pfn_notify)(const char *errinfo,
                                                           const void *private_info,
                                                           size_t cb,
                                                           void *user_data),
                             void *user_data,
                             cl_int &errorCode)
    {
        return Platform::CreateContext(properties, num_devices, devices, pfn_notify, user_data,
                                       errorCode);
    }
    
    cl_context CreateContextFromType(const cl_context_properties *properties,
                                     DeviceType device_type,
                                     void(CL_CALLBACK *pfn_notify)(const char *errinfo,
                                                                   const void *private_info,
                                                                   size_t cb,
                                                                   void *user_data),
                                     void *user_data,
                                     cl_int &errorCode)
    {
        return Platform::CreateContextFromType(properties, device_type, pfn_notify, user_data,
                                               errorCode);
    }
    
    cl_int RetainContext(cl_context context)
    {
        context->cast<Context>().retain();
        return CL_SUCCESS;
    }
    
    cl_int ReleaseContext(cl_context context)
    {
        Context &ctx = context->cast<Context>();
        if (ctx.release())
        {
            delete &ctx;
        }
        return CL_SUCCESS;
    }
    
    cl_int GetContextInfo(cl_context context,
                          ContextInfo param_name,
                          size_t param_value_size,
                          void *param_value,
                          size_t *param_value_size_ret)
    {
        return context->cast<Context>().getInfo(param_name, param_value_size, param_value,
                                                param_value_size_ret);
    }
    
    cl_int SetContextDestructorCallback(cl_context context,
                                        void(CL_CALLBACK *pfn_notify)(cl_context context,
                                                                      void *user_data),
                                        void *user_data)
    {
        WARN_NOT_SUPPORTED(SetContextDestructorCallback);
        return 0;
    }
    
    cl_command_queue CreateCommandQueueWithProperties(cl_context context,
                                                      cl_device_id device,
                                                      const cl_queue_properties *properties,
                                                      cl_int &errorCode)
    {
        return context->cast<Context>().createCommandQueueWithProperties(device, properties, errorCode);
    }
    
    cl_int RetainCommandQueue(cl_command_queue command_queue)
    {
        command_queue->cast<CommandQueue>().retain();
        return CL_SUCCESS;
    }
    
    cl_int ReleaseCommandQueue(cl_command_queue command_queue)
    {
        CommandQueue &queue = command_queue->cast<CommandQueue>();
        if (queue.release())
        {
            delete &queue;
        }
        return CL_SUCCESS;
    }
    
    cl_int GetCommandQueueInfo(cl_command_queue command_queue,
                               CommandQueueInfo param_name,
                               size_t param_value_size,
                               void *param_value,
                               size_t *param_value_size_ret)
    {
        return command_queue->cast<CommandQueue>().getInfo(param_name, param_value_size, param_value,
                                                           param_value_size_ret);
    }
    
    cl_mem CreateBuffer(cl_context context,
                        MemFlags flags,
                        size_t size,
                        void *host_ptr,
                        cl_int &errorCode)
    {
        return context->cast<Context>().createBuffer(nullptr, flags, size, host_ptr, errorCode);
    }
    
    cl_mem CreateBufferWithProperties(cl_context context,
                                      const cl_mem_properties *properties,
                                      MemFlags flags,
                                      size_t size,
                                      void *host_ptr,
                                      cl_int &errorCode)
    {
        return context->cast<Context>().createBuffer(properties, flags, size, host_ptr, errorCode);
    }
    
    cl_mem CreateSubBuffer(cl_mem buffer,
                           MemFlags flags,
                           cl_buffer_create_type buffer_create_type,
                           const void *buffer_create_info,
                           cl_int &errorCode)
    {
        return buffer->cast<Buffer>().createSubBuffer(flags, buffer_create_type, buffer_create_info,
                                                      errorCode);
    }
    
    cl_mem CreateImage(cl_context context,
                       MemFlags flags,
                       const cl_image_format *image_format,
                       const cl_image_desc *image_desc,
                       void *host_ptr,
                       cl_int &errorCode)
    {
        return context->cast<Context>().createImage(nullptr, flags, image_format, image_desc, host_ptr,
                                                    errorCode);
    }
    
    cl_mem CreateImageWithProperties(cl_context context,
                                     const cl_mem_properties *properties,
                                     MemFlags flags,
                                     const cl_image_format *image_format,
                                     const cl_image_desc *image_desc,
                                     void *host_ptr,
                                     cl_int &errorCode)
    {
        return context->cast<Context>().createImage(properties, flags, image_format, image_desc,
                                                    host_ptr, errorCode);
    }
    
    cl_mem CreatePipe(cl_context context,
                      MemFlags flags,
                      cl_uint pipe_packet_size,
                      cl_uint pipe_max_packets,
                      const cl_pipe_properties *properties,
                      cl_int &errorCode)
    {
        WARN_NOT_SUPPORTED(CreatePipe);
        return 0;
    }
    
    cl_int RetainMemObject(cl_mem memobj)
    {
        memobj->cast<Memory>().retain();
        return CL_SUCCESS;
    }
    
    cl_int ReleaseMemObject(cl_mem memobj)
    {
        Memory &memory = memobj->cast<Memory>();
        if (memory.release())
        {
            delete &memory;
        }
        return CL_SUCCESS;
    }
    
    cl_int GetSupportedImageFormats(cl_context context,
                                    MemFlags flags,
                                    MemObjectType image_type,
                                    cl_uint num_entries,
                                    cl_image_format *image_formats,
                                    cl_uint *num_image_formats)
    {
        return context->cast<Context>().getSupportedImageFormats(flags, image_type, num_entries,
                                                                 image_formats, num_image_formats);
    }
    
    cl_int GetMemObjectInfo(cl_mem memobj,
                            MemInfo param_name,
                            size_t param_value_size,
                            void *param_value,
                            size_t *param_value_size_ret)
    {
        return memobj->cast<Memory>().getInfo(param_name, param_value_size, param_value,
                                              param_value_size_ret);
    }
    
    cl_int GetImageInfo(cl_mem image,
                        ImageInfo param_name,
                        size_t param_value_size,
                        void *param_value,
                        size_t *param_value_size_ret)
    {
        return image->cast<Image>().getInfo(param_name, param_value_size, param_value,
                                            param_value_size_ret);
    }
    
    cl_int GetPipeInfo(cl_mem pipe,
                       PipeInfo param_name,
                       size_t param_value_size,
                       void *param_value,
                       size_t *param_value_size_ret)
    {
        WARN_NOT_SUPPORTED(GetPipeInfo);
        return 0;
    }
    
    cl_int SetMemObjectDestructorCallback(cl_mem memobj,
                                          void(CL_CALLBACK *pfn_notify)(cl_mem memobj, void *user_data),
                                          void *user_data)
    {
        return memobj->cast<Memory>().setDestructorCallback(pfn_notify, user_data);
    }
    
    void *SVMAlloc(cl_context context, SVM_MemFlags flags, size_t size, cl_uint alignment)
    {
        WARN_NOT_SUPPORTED(SVMAlloc);
        return 0;
    }
    
    void SVMFree(cl_context context, void *svm_pointer)
    {
        WARN_NOT_SUPPORTED(SVMFree);
    }
    
    cl_sampler CreateSamplerWithProperties(cl_context context,
                                           const cl_sampler_properties *sampler_properties,
                                           cl_int &errorCode)
    {
        return context->cast<Context>().createSamplerWithProperties(sampler_properties, errorCode);
    }
    
    cl_int RetainSampler(cl_sampler sampler)
    {
        sampler->cast<Sampler>().retain();
        return CL_SUCCESS;
    }
    
    cl_int ReleaseSampler(cl_sampler sampler)
    {
        Sampler &smplr = sampler->cast<Sampler>();
        if (smplr.release())
        {
            delete &smplr;
        }
        return CL_SUCCESS;
    }
    
    cl_int GetSamplerInfo(cl_sampler sampler,
                          SamplerInfo param_name,
                          size_t param_value_size,
                          void *param_value,
                          size_t *param_value_size_ret)
    {
        return sampler->cast<Sampler>().getInfo(param_name, param_value_size, param_value,
                                                param_value_size_ret);
    }
    
    cl_program CreateProgramWithSource(cl_context context,
                                       cl_uint count,
                                       const char **strings,
                                       const size_t *lengths,
                                       cl_int &errorCode)
    {
        return context->cast<Context>().createProgramWithSource(count, strings, lengths, errorCode);
    }
    
    cl_program CreateProgramWithBinary(cl_context context,
                                       cl_uint num_devices,
                                       const cl_device_id *device_list,
                                       const size_t *lengths,
                                       const unsigned char **binaries,
                                       cl_int *binary_status,
                                       cl_int &errorCode)
    {
        return context->cast<Context>().createProgramWithBinary(num_devices, device_list, lengths,
                                                                binaries, binary_status, errorCode);
    }
    
    cl_program CreateProgramWithBuiltInKernels(cl_context context,
                                               cl_uint num_devices,
                                               const cl_device_id *device_list,
                                               const char *kernel_names,
                                               cl_int &errorCode)
    {
        return context->cast<Context>().createProgramWithBuiltInKernels(num_devices, device_list,
                                                                        kernel_names, errorCode);
    }
    
    cl_program CreateProgramWithIL(cl_context context, const void *il, size_t length, cl_int &errorCode)
    {
        return context->cast<Context>().createProgramWithIL(il, length, errorCode);
    }
    
    cl_int RetainProgram(cl_program program)
    {
        program->cast<Program>().retain();
        return CL_SUCCESS;
    }
    
    cl_int ReleaseProgram(cl_program program)
    {
        Program &prog = program->cast<Program>();
        if (prog.release())
        {
            delete &prog;
        }
        return CL_SUCCESS;
    }
    
    cl_int BuildProgram(cl_program program,
                        cl_uint num_devices,
                        const cl_device_id *device_list,
                        const char *options,
                        void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
                        void *user_data)
    {
        return program->cast<Program>().build(num_devices, device_list, options, pfn_notify, user_data);
    }
    
    cl_int CompileProgram(cl_program program,
                          cl_uint num_devices,
                          const cl_device_id *device_list,
                          const char *options,
                          cl_uint num_input_headers,
                          const cl_program *input_headers,
                          const char **header_include_names,
                          void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
                          void *user_data)
    {
        return program->cast<Program>().compile(num_devices, device_list, options, num_input_headers,
                                                input_headers, header_include_names, pfn_notify,
                                                user_data);
    }
    
    cl_program LinkProgram(cl_context context,
                           cl_uint num_devices,
                           const cl_device_id *device_list,
                           const char *options,
                           cl_uint num_input_programs,
                           const cl_program *input_programs,
                           void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
                           void *user_data,
                           cl_int &errorCode)
    {
        return context->cast<Context>().linkProgram(num_devices, device_list, options,
                                                    num_input_programs, input_programs, pfn_notify,
                                                    user_data, errorCode);
    }
    
    cl_int SetProgramReleaseCallback(cl_program program,
                                     void(CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
                                     void *user_data)
    {
        WARN_NOT_SUPPORTED(SetProgramReleaseCallback);
        return 0;
    }
    
    cl_int SetProgramSpecializationConstant(cl_program program,
                                            cl_uint spec_id,
                                            size_t spec_size,
                                            const void *spec_value)
    {
        WARN_NOT_SUPPORTED(SetProgramSpecializationConstant);
        return 0;
    }
    
    cl_int UnloadPlatformCompiler(cl_platform_id platform)
    {
        return platform->cast<Platform>().unloadCompiler();
    }
    
    cl_int GetProgramInfo(cl_program program,
                          ProgramInfo param_name,
                          size_t param_value_size,
                          void *param_value,
                          size_t *param_value_size_ret)
    {
        return program->cast<Program>().getInfo(param_name, param_value_size, param_value,
                                                param_value_size_ret);
    }
    
    cl_int GetProgramBuildInfo(cl_program program,
                               cl_device_id device,
                               ProgramBuildInfo param_name,
                               size_t param_value_size,
                               void *param_value,
                               size_t *param_value_size_ret)
    {
        return program->cast<Program>().getBuildInfo(device, param_name, param_value_size, param_value,
                                                     param_value_size_ret);
    }
    
    cl_kernel CreateKernel(cl_program program, const char *kernel_name, cl_int &errorCode)
    {
        return program->cast<Program>().createKernel(kernel_name, errorCode);
    }
    
    cl_int CreateKernelsInProgram(cl_program program,
                                  cl_uint num_kernels,
                                  cl_kernel *kernels,
                                  cl_uint *num_kernels_ret)
    {
        return program->cast<Program>().createKernels(num_kernels, kernels, num_kernels_ret);
    }
    
    cl_kernel CloneKernel(cl_kernel source_kernel, cl_int &errorCode)
    {
        WARN_NOT_SUPPORTED(CloneKernel);
        return 0;
    }
    
    cl_int RetainKernel(cl_kernel kernel)
    {
        kernel->cast<Kernel>().retain();
        return CL_SUCCESS;
    }
    
    cl_int ReleaseKernel(cl_kernel kernel)
    {
        Kernel &krnl = kernel->cast<Kernel>();
        if (krnl.release())
        {
            delete &krnl;
        }
        return CL_SUCCESS;
    }
    
    cl_int SetKernelArg(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value)
    {
        return kernel->cast<Kernel>().setArg(arg_index, arg_size, arg_value);
    }
    
    cl_int SetKernelArgSVMPointer(cl_kernel kernel, cl_uint arg_index, const void *arg_value)
    {
        WARN_NOT_SUPPORTED(SetKernelArgSVMPointer);
        return 0;
    }
    
    cl_int SetKernelExecInfo(cl_kernel kernel,
                             KernelExecInfo param_name,
                             size_t param_value_size,
                             const void *param_value)
    {
        WARN_NOT_SUPPORTED(SetKernelExecInfo);
        return 0;
    }
    
    cl_int GetKernelInfo(cl_kernel kernel,
                         KernelInfo param_name,
                         size_t param_value_size,
                         void *param_value,
                         size_t *param_value_size_ret)
    {
        return kernel->cast<Kernel>().getInfo(param_name, param_value_size, param_value,
                                              param_value_size_ret);
    }
    
    cl_int GetKernelArgInfo(cl_kernel kernel,
                            cl_uint arg_index,
                            KernelArgInfo param_name,
                            size_t param_value_size,
                            void *param_value,
                            size_t *param_value_size_ret)
    {
        return kernel->cast<Kernel>().getArgInfo(arg_index, param_name, param_value_size, param_value,
                                                 param_value_size_ret);
    }
    
    cl_int GetKernelWorkGroupInfo(cl_kernel kernel,
                                  cl_device_id device,
                                  KernelWorkGroupInfo param_name,
                                  size_t param_value_size,
                                  void *param_value,
                                  size_t *param_value_size_ret)
    {
        return kernel->cast<Kernel>().getWorkGroupInfo(device, param_name, param_value_size,
                                                       param_value, param_value_size_ret);
    }
    
    cl_int GetKernelSubGroupInfo(cl_kernel kernel,
                                 cl_device_id device,
                                 KernelSubGroupInfo param_name,
                                 size_t input_value_size,
                                 const void *input_value,
                                 size_t param_value_size,
                                 void *param_value,
                                 size_t *param_value_size_ret)
    {
        WARN_NOT_SUPPORTED(GetKernelSubGroupInfo);
        return 0;
    }
    
    cl_int WaitForEvents(cl_uint num_events, const cl_event *event_list)
    {
        return (*event_list)->cast<Event>().getContext().waitForEvents(num_events, event_list);
    }
    
    cl_int GetEventInfo(cl_event event,
                        EventInfo param_name,
                        size_t param_value_size,
                        void *param_value,
                        size_t *param_value_size_ret)
    {
        return event->cast<Event>().getInfo(param_name, param_value_size, param_value,
                                            param_value_size_ret);
    }
    
    cl_event CreateUserEvent(cl_context context, cl_int &errorCode)
    {
        return context->cast<Context>().createUserEvent(errorCode);
    }
    
    cl_int RetainEvent(cl_event event)
    {
        event->cast<Event>().retain();
        return CL_SUCCESS;
    }
    
    cl_int ReleaseEvent(cl_event event)
    {
        Event &evt = event->cast<Event>();
        if (evt.release())
        {
            delete &evt;
        }
        return CL_SUCCESS;
    }
    
    cl_int SetUserEventStatus(cl_event event, cl_int execution_status)
    {
        return event->cast<Event>().setUserEventStatus(execution_status);
    }
    
    cl_int SetEventCallback(cl_event event,
                            cl_int command_exec_callback_type,
                            void(CL_CALLBACK *pfn_notify)(cl_event event,
                                                          cl_int event_command_status,
                                                          void *user_data),
                            void *user_data)
    {
        return event->cast<Event>().setCallback(command_exec_callback_type, pfn_notify, user_data);
    }
    
    cl_int GetEventProfilingInfo(cl_event event,
                                 ProfilingInfo param_name,
                                 size_t param_value_size,
                                 void *param_value,
                                 size_t *param_value_size_ret)
    {
        return event->cast<Event>().getProfilingInfo(param_name, param_value_size, param_value,
                                                     param_value_size_ret);
    }
    
    cl_int Flush(cl_command_queue command_queue)
    {
        return command_queue->cast<CommandQueue>().flush();
    }
    
    cl_int Finish(cl_command_queue command_queue)
    {
        return command_queue->cast<CommandQueue>().finish();
    }
    
    cl_int EnqueueReadBuffer(cl_command_queue command_queue,
                             cl_mem buffer,
                             cl_bool blocking_read,
                             size_t offset,
                             size_t size,
                             void *ptr,
                             cl_uint num_events_in_wait_list,
                             const cl_event *event_wait_list,
                             cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueReadBuffer(
            buffer, blocking_read, offset, size, ptr, num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueReadBufferRect(cl_command_queue command_queue,
                                 cl_mem buffer,
                                 cl_bool blocking_read,
                                 const size_t *buffer_origin,
                                 const size_t *host_origin,
                                 const size_t *region,
                                 size_t buffer_row_pitch,
                                 size_t buffer_slice_pitch,
                                 size_t host_row_pitch,
                                 size_t host_slice_pitch,
                                 void *ptr,
                                 cl_uint num_events_in_wait_list,
                                 const cl_event *event_wait_list,
                                 cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueReadBufferRect(
            buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch,
            buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    cl_int EnqueueWriteBuffer(cl_command_queue command_queue,
                              cl_mem buffer,
                              cl_bool blocking_write,
                              size_t offset,
                              size_t size,
                              const void *ptr,
                              cl_uint num_events_in_wait_list,
                              const cl_event *event_wait_list,
                              cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueWriteBuffer(
            buffer, blocking_write, offset, size, ptr, num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueWriteBufferRect(cl_command_queue command_queue,
                                  cl_mem buffer,
                                  cl_bool blocking_write,
                                  const size_t *buffer_origin,
                                  const size_t *host_origin,
                                  const size_t *region,
                                  size_t buffer_row_pitch,
                                  size_t buffer_slice_pitch,
                                  size_t host_row_pitch,
                                  size_t host_slice_pitch,
                                  const void *ptr,
                                  cl_uint num_events_in_wait_list,
                                  const cl_event *event_wait_list,
                                  cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueWriteBufferRect(
            buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch,
            buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    cl_int EnqueueFillBuffer(cl_command_queue command_queue,
                             cl_mem buffer,
                             const void *pattern,
                             size_t pattern_size,
                             size_t offset,
                             size_t size,
                             cl_uint num_events_in_wait_list,
                             const cl_event *event_wait_list,
                             cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueFillBuffer(
            buffer, pattern, pattern_size, offset, size, num_events_in_wait_list, event_wait_list,
            event);
    }
    
    cl_int EnqueueCopyBuffer(cl_command_queue command_queue,
                             cl_mem src_buffer,
                             cl_mem dst_buffer,
                             size_t src_offset,
                             size_t dst_offset,
                             size_t size,
                             cl_uint num_events_in_wait_list,
                             const cl_event *event_wait_list,
                             cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueCopyBuffer(
            src_buffer, dst_buffer, src_offset, dst_offset, size, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    cl_int EnqueueCopyBufferRect(cl_command_queue command_queue,
                                 cl_mem src_buffer,
                                 cl_mem dst_buffer,
                                 const size_t *src_origin,
                                 const size_t *dst_origin,
                                 const size_t *region,
                                 size_t src_row_pitch,
                                 size_t src_slice_pitch,
                                 size_t dst_row_pitch,
                                 size_t dst_slice_pitch,
                                 cl_uint num_events_in_wait_list,
                                 const cl_event *event_wait_list,
                                 cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueCopyBufferRect(
            src_buffer, dst_buffer, src_origin, dst_origin, region, src_row_pitch, src_slice_pitch,
            dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueReadImage(cl_command_queue command_queue,
                            cl_mem image,
                            cl_bool blocking_read,
                            const size_t *origin,
                            const size_t *region,
                            size_t row_pitch,
                            size_t slice_pitch,
                            void *ptr,
                            cl_uint num_events_in_wait_list,
                            const cl_event *event_wait_list,
                            cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueReadImage(
            image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    cl_int EnqueueWriteImage(cl_command_queue command_queue,
                             cl_mem image,
                             cl_bool blocking_write,
                             const size_t *origin,
                             const size_t *region,
                             size_t input_row_pitch,
                             size_t input_slice_pitch,
                             const void *ptr,
                             cl_uint num_events_in_wait_list,
                             const cl_event *event_wait_list,
                             cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueWriteImage(
            image, blocking_write, origin, region, input_row_pitch, input_slice_pitch, ptr,
            num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueFillImage(cl_command_queue command_queue,
                            cl_mem image,
                            const void *fill_color,
                            const size_t *origin,
                            const size_t *region,
                            cl_uint num_events_in_wait_list,
                            const cl_event *event_wait_list,
                            cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueFillImage(
            image, fill_color, origin, region, num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueCopyImage(cl_command_queue command_queue,
                            cl_mem src_image,
                            cl_mem dst_image,
                            const size_t *src_origin,
                            const size_t *dst_origin,
                            const size_t *region,
                            cl_uint num_events_in_wait_list,
                            const cl_event *event_wait_list,
                            cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueCopyImage(
            src_image, dst_image, src_origin, dst_origin, region, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    cl_int EnqueueCopyImageToBuffer(cl_command_queue command_queue,
                                    cl_mem src_image,
                                    cl_mem dst_buffer,
                                    const size_t *src_origin,
                                    const size_t *region,
                                    size_t dst_offset,
                                    cl_uint num_events_in_wait_list,
                                    const cl_event *event_wait_list,
                                    cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueCopyImageToBuffer(
            src_image, dst_buffer, src_origin, region, dst_offset, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    cl_int EnqueueCopyBufferToImage(cl_command_queue command_queue,
                                    cl_mem src_buffer,
                                    cl_mem dst_image,
                                    size_t src_offset,
                                    const size_t *dst_origin,
                                    const size_t *region,
                                    cl_uint num_events_in_wait_list,
                                    const cl_event *event_wait_list,
                                    cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueCopyBufferToImage(
            src_buffer, dst_image, src_offset, dst_origin, region, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    void *EnqueueMapBuffer(cl_command_queue command_queue,
                           cl_mem buffer,
                           cl_bool blocking_map,
                           MapFlags map_flags,
                           size_t offset,
                           size_t size,
                           cl_uint num_events_in_wait_list,
                           const cl_event *event_wait_list,
                           cl_event *event,
                           cl_int &errorCode)
    {
        return command_queue->cast<CommandQueue>().enqueueMapBuffer(
            buffer, blocking_map, map_flags, offset, size, num_events_in_wait_list, event_wait_list,
            event, errorCode);
    }
    
    void *EnqueueMapImage(cl_command_queue command_queue,
                          cl_mem image,
                          cl_bool blocking_map,
                          MapFlags map_flags,
                          const size_t *origin,
                          const size_t *region,
                          size_t *image_row_pitch,
                          size_t *image_slice_pitch,
                          cl_uint num_events_in_wait_list,
                          const cl_event *event_wait_list,
                          cl_event *event,
                          cl_int &errorCode)
    {
        return command_queue->cast<CommandQueue>().enqueueMapImage(
            image, blocking_map, map_flags, origin, region, image_row_pitch, image_slice_pitch,
            num_events_in_wait_list, event_wait_list, event, errorCode);
    }
    
    cl_int EnqueueUnmapMemObject(cl_command_queue command_queue,
                                 cl_mem memobj,
                                 void *mapped_ptr,
                                 cl_uint num_events_in_wait_list,
                                 const cl_event *event_wait_list,
                                 cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueUnmapMemObject(
            memobj, mapped_ptr, num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueMigrateMemObjects(cl_command_queue command_queue,
                                    cl_uint num_mem_objects,
                                    const cl_mem *mem_objects,
                                    MemMigrationFlags flags,
                                    cl_uint num_events_in_wait_list,
                                    const cl_event *event_wait_list,
                                    cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueMigrateMemObjects(
            num_mem_objects, mem_objects, flags, num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueNDRangeKernel(cl_command_queue command_queue,
                                cl_kernel kernel,
                                cl_uint work_dim,
                                const size_t *global_work_offset,
                                const size_t *global_work_size,
                                const size_t *local_work_size,
                                cl_uint num_events_in_wait_list,
                                const cl_event *event_wait_list,
                                cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueNDRangeKernel(
            kernel, work_dim, global_work_offset, global_work_size, local_work_size,
            num_events_in_wait_list, event_wait_list, event);
    }
    
    cl_int EnqueueNativeKernel(cl_command_queue command_queue,
                               void(CL_CALLBACK *user_func)(void *),
                               void *args,
                               size_t cb_args,
                               cl_uint num_mem_objects,
                               const cl_mem *mem_list,
                               const void **args_mem_loc,
                               cl_uint num_events_in_wait_list,
                               const cl_event *event_wait_list,
                               cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueNativeKernel(
            user_func, args, cb_args, num_mem_objects, mem_list, args_mem_loc, num_events_in_wait_list,
            event_wait_list, event);
    }
    
    cl_int EnqueueMarkerWithWaitList(cl_command_queue command_queue,
                                     cl_uint num_events_in_wait_list,
                                     const cl_event *event_wait_list,
                                     cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueMarkerWithWaitList(num_events_in_wait_list,
                                                                             event_wait_list, event);
    }
    
    cl_int EnqueueBarrierWithWaitList(cl_command_queue command_queue,
                                      cl_uint num_events_in_wait_list,
                                      const cl_event *event_wait_list,
                                      cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueBarrierWithWaitList(num_events_in_wait_list,
                                                                              event_wait_list, event);
    }
    
    cl_int EnqueueSVMFree(cl_command_queue command_queue,
                          cl_uint num_svm_pointers,
                          void *svm_pointers[],
                          void(CL_CALLBACK *pfn_free_func)(cl_command_queue queue,
                                                           cl_uint num_svm_pointers,
                                                           void *svm_pointers[],
                                                           void *user_data),
                          void *user_data,
                          cl_uint num_events_in_wait_list,
                          const cl_event *event_wait_list,
                          cl_event *event)
    {
        WARN_NOT_SUPPORTED(EnqueueSVMFree);
        return 0;
    }
    
    cl_int EnqueueSVMMemcpy(cl_command_queue command_queue,
                            cl_bool blocking_copy,
                            void *dst_ptr,
                            const void *src_ptr,
                            size_t size,
                            cl_uint num_events_in_wait_list,
                            const cl_event *event_wait_list,
                            cl_event *event)
    {
        WARN_NOT_SUPPORTED(EnqueueSVMMemcpy);
        return 0;
    }
    
    cl_int EnqueueSVMMemFill(cl_command_queue command_queue,
                             void *svm_ptr,
                             const void *pattern,
                             size_t pattern_size,
                             size_t size,
                             cl_uint num_events_in_wait_list,
                             const cl_event *event_wait_list,
                             cl_event *event)
    {
        WARN_NOT_SUPPORTED(EnqueueSVMMemFill);
        return 0;
    }
    
    cl_int EnqueueSVMMap(cl_command_queue command_queue,
                         cl_bool blocking_map,
                         MapFlags flags,
                         void *svm_ptr,
                         size_t size,
                         cl_uint num_events_in_wait_list,
                         const cl_event *event_wait_list,
                         cl_event *event)
    {
        WARN_NOT_SUPPORTED(EnqueueSVMMap);
        return 0;
    }
    
    cl_int EnqueueSVMUnmap(cl_command_queue command_queue,
                           void *svm_ptr,
                           cl_uint num_events_in_wait_list,
                           const cl_event *event_wait_list,
                           cl_event *event)
    {
        WARN_NOT_SUPPORTED(EnqueueSVMUnmap);
        return 0;
    }
    
    cl_int EnqueueSVMMigrateMem(cl_command_queue command_queue,
                                cl_uint num_svm_pointers,
                                const void **svm_pointers,
                                const size_t *sizes,
                                MemMigrationFlags flags,
                                cl_uint num_events_in_wait_list,
                                const cl_event *event_wait_list,
                                cl_event *event)
    {
        WARN_NOT_SUPPORTED(EnqueueSVMMigrateMem);
        return 0;
    }
    
    void *GetExtensionFunctionAddressForPlatform(cl_platform_id platform, const char *func_name)
    {
        return GetExtensionFunctionAddress(func_name);
    }
    
    cl_int SetCommandQueueProperty(cl_command_queue command_queue,
                                   CommandQueueProperties properties,
                                   cl_bool enable,
                                   cl_command_queue_properties *old_properties)
    {
        return command_queue->cast<CommandQueue>().setProperty(properties, enable, old_properties);
    }
    
    cl_mem CreateImage2D(cl_context context,
                         MemFlags flags,
                         const cl_image_format *image_format,
                         size_t image_width,
                         size_t image_height,
                         size_t image_row_pitch,
                         void *host_ptr,
                         cl_int &errorCode)
    {
        return context->cast<Context>().createImage2D(flags, image_format, image_width, image_height,
                                                      image_row_pitch, host_ptr, errorCode);
    }
    
    cl_mem CreateImage3D(cl_context context,
                         MemFlags flags,
                         const cl_image_format *image_format,
                         size_t image_width,
                         size_t image_height,
                         size_t image_depth,
                         size_t image_row_pitch,
                         size_t image_slice_pitch,
                         void *host_ptr,
                         cl_int &errorCode)
    {
        return context->cast<Context>().createImage3D(flags, image_format, image_width, image_height,
                                                      image_depth, image_row_pitch, image_slice_pitch,
                                                      host_ptr, errorCode);
    }
    
    cl_int EnqueueMarker(cl_command_queue command_queue, cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueMarker(event);
    }
    
    cl_int EnqueueWaitForEvents(cl_command_queue command_queue,
                                cl_uint num_events,
                                const cl_event *event_list)
    {
        return command_queue->cast<CommandQueue>().enqueueWaitForEvents(num_events, event_list);
    }
    
    cl_int EnqueueBarrier(cl_command_queue command_queue)
    {
        return command_queue->cast<CommandQueue>().enqueueBarrier();
    }
    
    cl_int UnloadCompiler()
    {
        Platform *const platform = Platform::GetDefault();
        return platform != nullptr ? platform->unloadCompiler() : CL_SUCCESS;
    }
    
    void *GetExtensionFunctionAddress(const char *func_name)
    {
        if (func_name == nullptr)
        {
            return nullptr;
        }
        const ProcTable &procTable = GetProcTable();
        const auto it              = procTable.find(func_name);
        return it != procTable.cend() ? it->second : nullptr;
    }
    
    cl_command_queue CreateCommandQueue(cl_context context,
                                        cl_device_id device,
                                        CommandQueueProperties properties,
                                        cl_int &errorCode)
    {
        return context->cast<Context>().createCommandQueue(device, properties, errorCode);
    }
    
    cl_sampler CreateSampler(cl_context context,
                             cl_bool normalized_coords,
                             AddressingMode addressing_mode,
                             FilterMode filter_mode,
                             cl_int &errorCode)
    {
        return context->cast<Context>().createSampler(normalized_coords, addressing_mode, filter_mode,
                                                      errorCode);
    }
    
    cl_int EnqueueTask(cl_command_queue command_queue,
                       cl_kernel kernel,
                       cl_uint num_events_in_wait_list,
                       const cl_event *event_wait_list,
                       cl_event *event)
    {
        return command_queue->cast<CommandQueue>().enqueueTask(kernel, num_events_in_wait_list,
                                                               event_wait_list, event);
    }
    
    }  // namespace cl