diff --git a/paddle/fluid/lite/opencl/CMakeLists.txt b/paddle/fluid/lite/opencl/CMakeLists.txt index 06072a1067d69d8376c9de2fd31dd452fb79efde..b0d20bef8bc08ef02fb54c1742aae6828bde2ecf 100644 --- a/paddle/fluid/lite/opencl/CMakeLists.txt +++ b/paddle/fluid/lite/opencl/CMakeLists.txt @@ -3,13 +3,7 @@ if (NOT LITE_WITH_OPENCL) endif() if (WITH_LITE AND LITE_WITH_LIGHT_WEIGHT_FRAMEWORK) - add_library(opencl-lib SHARED IMPORTED) - set_target_properties(opencl-lib - PROPERTIES - IMPORTED_LOCATION - #${CMAKE_SOURCE_DIR}/opencl-lib/armeabi-v7a/libOpenCL.so) - ${CMAKE_SOURCE_DIR}/opencl-lib/armeabi-v7a/libGLES_mali.so) - + cc_library(cl_wrapper SRCS cl_wrapper.cc) cc_library(cl_tool SRCS cl_tool.cc) target_compile_options(cl_tool BEFORE PUBLIC -Wno-ignored-qualifiers) cc_library(cl_half SRCS cl_half.cc) @@ -20,7 +14,6 @@ if (WITH_LITE AND LITE_WITH_LIGHT_WEIGHT_FRAMEWORK) cc_library(cl_image_converter SRCS cl_image_converter.cc DEPS cl_half lite_tensor) cc_library(cl_image SRCS cl_image.cc DEPS cl_half lite_tensor cl_image_converter cl_engine) cc_library(cl_caller SRCS cl_caller.cc DEPS cl_helper cl_image) - lite_cc_test(test_cl_runtime SRCS cl_test.cc DEPS cl_helper cl_image cl_caller) - target_link_libraries(test_cl_runtime opencl-lib) + lite_cc_test(test_cl_runtime SRCS cl_test.cc DEPS cl_helper cl_image cl_caller cl_wrapper) add_dependencies(cl_tool opencl_clhpp) endif() diff --git a/paddle/fluid/lite/opencl/cl_wrapper.cc b/paddle/fluid/lite/opencl/cl_wrapper.cc new file mode 100644 index 0000000000000000000000000000000000000000..52c68bdc969c311864e79f9351f26d84d0613f5e --- /dev/null +++ b/paddle/fluid/lite/opencl/cl_wrapper.cc @@ -0,0 +1,962 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include +#include +#include +#include +#include "paddle/fluid/lite/opencl/cl2_header.h" + +/** + * Wrapper of OpenCL 2.0, based on file opencl20/CL/cl.h + */ + +#if CL_HPP_TARGET_OPENCL_VERSION < 200 +#define CL_API_SUFFIX__VERSION_2_0 +#endif + +namespace paddle { +namespace lite { + +class OpenCLLibrary final { + private: + OpenCLLibrary(); + OpenCLLibrary(const OpenCLLibrary &) = delete; + OpenCLLibrary &operator=(const OpenCLLibrary &) = delete; + + bool Load(); + void *LoadFromPath(const std::string &path); + + public: + static OpenCLLibrary *Get(); + + using clGetPlatformIDsFunc = cl_int (*)(cl_uint, cl_platform_id *, cl_uint *); + using clGetPlatformInfoFunc = cl_int (*)(cl_platform_id, cl_platform_info, + size_t, void *, size_t *); + using clBuildProgramFunc = cl_int (*)(cl_program, cl_uint, + const cl_device_id *, const char *, + void (*pfn_notify)(cl_program, void *), + void *); + using clEnqueueNDRangeKernelFunc = cl_int (*)(cl_command_queue, cl_kernel, + cl_uint, const size_t *, + const size_t *, const size_t *, + cl_uint, const cl_event *, + cl_event *); + using clSetKernelArgFunc = cl_int (*)(cl_kernel, cl_uint, size_t, + const void *); + using clRetainMemObjectFunc = cl_int (*)(cl_mem); + using clReleaseMemObjectFunc = cl_int (*)(cl_mem); + using clEnqueueUnmapMemObjectFunc = cl_int (*)(cl_command_queue, cl_mem, + void *, cl_uint, + const cl_event *, cl_event *); + using clRetainCommandQueueFunc = cl_int (*)(cl_command_queue command_queue); + using clCreateContextFunc = cl_context (*)( + const cl_context_properties *, cl_uint, const cl_device_id *, + void(CL_CALLBACK *)( // NOLINT(readability/casting) + const char *, const void *, size_t, void *), + void *, cl_int *); + using clCreateContextFromTypeFunc = + cl_context (*)(const cl_context_properties *, cl_device_type, + void(CL_CALLBACK *)( // NOLINT(readability/casting) + const char *, const void *, size_t, void *), + void *, cl_int *); + using clReleaseContextFunc = cl_int (*)(cl_context); + using clWaitForEventsFunc = cl_int (*)(cl_uint, const cl_event *); + using clReleaseEventFunc = cl_int (*)(cl_event); + using clEnqueueWriteBufferFunc = cl_int (*)(cl_command_queue, cl_mem, cl_bool, + size_t, size_t, const void *, + cl_uint, const cl_event *, + cl_event *); + using clEnqueueReadBufferFunc = cl_int (*)(cl_command_queue, cl_mem, cl_bool, + size_t, size_t, void *, cl_uint, + const cl_event *, cl_event *); + using clEnqueueReadImageFunc = cl_int (*)(cl_command_queue, cl_mem, cl_bool, + const size_t *, const size_t *, + size_t, size_t, void *, cl_uint, + const cl_event *, cl_event *); + using clGetProgramBuildInfoFunc = cl_int (*)(cl_program, cl_device_id, + cl_program_build_info, size_t, + void *, size_t *); + using clRetainProgramFunc = cl_int (*)(cl_program program); + using clEnqueueMapBufferFunc = void *(*)(cl_command_queue, cl_mem, cl_bool, + cl_map_flags, size_t, size_t, + cl_uint, const cl_event *, + cl_event *, cl_int *); + using clEnqueueMapImageFunc = void *(*)(cl_command_queue, cl_mem, cl_bool, + cl_map_flags, const size_t *, + const size_t *, size_t *, size_t *, + cl_uint, const cl_event *, cl_event *, + cl_int *); + using clCreateCommandQueueFunc = cl_command_queue(CL_API_CALL *)( // NOLINT + cl_context, cl_device_id, cl_command_queue_properties, cl_int *); + using clCreateCommandQueueWithPropertiesFunc = cl_command_queue (*)( + cl_context, cl_device_id, const cl_queue_properties *, cl_int *); + using clReleaseCommandQueueFunc = cl_int (*)(cl_command_queue); + using clCreateProgramWithBinaryFunc = cl_program (*)(cl_context, cl_uint, + const cl_device_id *, + const size_t *, + const unsigned char **, + cl_int *, cl_int *); + using clRetainContextFunc = cl_int (*)(cl_context context); + using clGetContextInfoFunc = cl_int (*)(cl_context, cl_context_info, size_t, + void *, size_t *); + using clReleaseProgramFunc = cl_int (*)(cl_program program); + using clFlushFunc = cl_int (*)(cl_command_queue command_queue); + using clFinishFunc = cl_int (*)(cl_command_queue command_queue); + using clGetProgramInfoFunc = cl_int (*)(cl_program, cl_program_info, size_t, + void *, size_t *); + using clCreateKernelFunc = cl_kernel (*)(cl_program, const char *, cl_int *); + using clRetainKernelFunc = cl_int (*)(cl_kernel kernel); + using clCreateBufferFunc = cl_mem (*)(cl_context, cl_mem_flags, size_t, + void *, cl_int *); + using clCreateImage2DFunc = cl_mem(CL_API_CALL *)(cl_context, // NOLINT + cl_mem_flags, + const cl_image_format *, + size_t, size_t, size_t, + void *, cl_int *); + using clCreateImageFunc = cl_mem (*)(cl_context, cl_mem_flags, + const cl_image_format *, + const cl_image_desc *, void *, cl_int *); + using clCreateUserEventFunc = cl_event (*)(cl_context, cl_int *); + using clCreateProgramWithSourceFunc = cl_program (*)(cl_context, cl_uint, + const char **, + const size_t *, + cl_int *); + using clReleaseKernelFunc = cl_int (*)(cl_kernel kernel); + using clGetDeviceInfoFunc = cl_int (*)(cl_device_id, cl_device_info, size_t, + void *, size_t *); + using clGetDeviceIDsFunc = cl_int (*)(cl_platform_id, cl_device_type, cl_uint, + cl_device_id *, cl_uint *); + using clRetainDeviceFunc = cl_int (*)(cl_device_id); + using clReleaseDeviceFunc = cl_int (*)(cl_device_id); + using clRetainEventFunc = cl_int (*)(cl_event); + using clGetKernelWorkGroupInfoFunc = cl_int (*)(cl_kernel, cl_device_id, + cl_kernel_work_group_info, + size_t, void *, size_t *); + using clGetEventInfoFunc = cl_int (*)(cl_event event, + cl_event_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret); + using clGetEventProfilingInfoFunc = cl_int (*)(cl_event event, + cl_profiling_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret); + using clGetImageInfoFunc = cl_int (*)(cl_mem, cl_image_info, size_t, void *, + size_t *); + +#define PADDLE_CL_DEFINE_FUNC_PTR(func) func##Func func = nullptr + + PADDLE_CL_DEFINE_FUNC_PTR(clGetPlatformIDs); + PADDLE_CL_DEFINE_FUNC_PTR(clGetPlatformInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clBuildProgram); + PADDLE_CL_DEFINE_FUNC_PTR(clEnqueueNDRangeKernel); + PADDLE_CL_DEFINE_FUNC_PTR(clSetKernelArg); + PADDLE_CL_DEFINE_FUNC_PTR(clReleaseKernel); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateProgramWithSource); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateBuffer); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateImage); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateImage2D); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateUserEvent); + PADDLE_CL_DEFINE_FUNC_PTR(clRetainKernel); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateKernel); + PADDLE_CL_DEFINE_FUNC_PTR(clGetProgramInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clFlush); + PADDLE_CL_DEFINE_FUNC_PTR(clFinish); + PADDLE_CL_DEFINE_FUNC_PTR(clReleaseProgram); + PADDLE_CL_DEFINE_FUNC_PTR(clRetainContext); + PADDLE_CL_DEFINE_FUNC_PTR(clGetContextInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateProgramWithBinary); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateCommandQueue); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateCommandQueueWithProperties); + PADDLE_CL_DEFINE_FUNC_PTR(clReleaseCommandQueue); + PADDLE_CL_DEFINE_FUNC_PTR(clEnqueueMapBuffer); + PADDLE_CL_DEFINE_FUNC_PTR(clEnqueueMapImage); + PADDLE_CL_DEFINE_FUNC_PTR(clRetainProgram); + PADDLE_CL_DEFINE_FUNC_PTR(clGetProgramBuildInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clEnqueueReadBuffer); + PADDLE_CL_DEFINE_FUNC_PTR(clEnqueueReadImage); + PADDLE_CL_DEFINE_FUNC_PTR(clEnqueueWriteBuffer); + PADDLE_CL_DEFINE_FUNC_PTR(clWaitForEvents); + PADDLE_CL_DEFINE_FUNC_PTR(clReleaseEvent); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateContext); + PADDLE_CL_DEFINE_FUNC_PTR(clCreateContextFromType); + PADDLE_CL_DEFINE_FUNC_PTR(clReleaseContext); + PADDLE_CL_DEFINE_FUNC_PTR(clRetainCommandQueue); + PADDLE_CL_DEFINE_FUNC_PTR(clEnqueueUnmapMemObject); + PADDLE_CL_DEFINE_FUNC_PTR(clRetainMemObject); + PADDLE_CL_DEFINE_FUNC_PTR(clReleaseMemObject); + PADDLE_CL_DEFINE_FUNC_PTR(clGetDeviceInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clGetDeviceIDs); + PADDLE_CL_DEFINE_FUNC_PTR(clRetainDevice); + PADDLE_CL_DEFINE_FUNC_PTR(clReleaseDevice); + PADDLE_CL_DEFINE_FUNC_PTR(clRetainEvent); + PADDLE_CL_DEFINE_FUNC_PTR(clGetKernelWorkGroupInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clGetEventInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clGetEventProfilingInfo); + PADDLE_CL_DEFINE_FUNC_PTR(clGetImageInfo); + +#undef PADDLE_CL_DEFINE_FUNC_PTR + + private: + void *handle_ = nullptr; +}; + +OpenCLLibrary *OpenCLLibrary::Get() { + static OpenCLLibrary library; + return &library; +} + +OpenCLLibrary::OpenCLLibrary() { + this->Load(); + // Do not call dlclose which may unload all OpenCL symbols. + // If close the OpenCL library, the static OpenCLlite destructor may fail. + // If there is no dlclose, the library will be closed when the program exist. + // Besides, the library will not be load repeatedly even dlopen many times. +} + +bool OpenCLLibrary::Load() { + if (handle_ != nullptr) { + return true; + } + + // Add customized OpenCL search path here + const std::vector paths = { + "libOpenCL.so", +#if defined(__aarch64__) + // Qualcomm Adreno with Android + "/system/vendor/lib64/libOpenCL.so", + "/system/lib64/libOpenCL.so", + // Mali with Android + "/system/vendor/lib64/egl/libGLES_mali.so", + "/system/lib64/egl/libGLES_mali.so", + // Typical Linux board + "/usr/lib/aarch64-linux-gnu/libOpenCL.so", +#else + // Qualcomm Adreno with Android + "/system/vendor/lib/libOpenCL.so", + "/system/lib/libOpenCL.so", + // Mali with Android + "/system/vendor/lib/egl/libGLES_mali.so", + "/system/lib/egl/libGLES_mali.so", + // Typical Linux board + "/usr/lib/arm-linux-gnueabihf/libOpenCL.so", +#endif + }; + + for (const auto &path : paths) { + VLOG(3) << "Loading OpenCL from " << path; + void *handle = LoadFromPath(path); + if (handle != nullptr) { + handle_ = handle; + break; + } + } + + if (handle_ == nullptr) { + LOG(ERROR) + << "Failed to load OpenCL library, " + "please make sure there exists OpenCL library on your device, " + "and your APP have right to access the library."; + return false; + } + + return true; +} + +void *OpenCLLibrary::LoadFromPath(const std::string &path) { + void *handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); + + if (handle == nullptr) { + VLOG(3) << "Failed to load OpenCL library from path " << path + << " error code: " << dlerror(); + return nullptr; + } + +#define PADDLE_CL_ASSIGN_FROM_DLSYM(func) \ + do { \ + void *ptr = dlsym(handle, #func); \ + if (ptr == nullptr) { \ + VLOG(1) << "Failed to load " << #func << " from " << path; \ + continue; \ + } \ + func = reinterpret_cast(ptr); \ + VLOG(3) << "Loaded " << #func << " from " << path; \ + } while (false) + + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetPlatformIDs); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetPlatformInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clBuildProgram); + PADDLE_CL_ASSIGN_FROM_DLSYM(clEnqueueNDRangeKernel); + PADDLE_CL_ASSIGN_FROM_DLSYM(clSetKernelArg); + PADDLE_CL_ASSIGN_FROM_DLSYM(clReleaseKernel); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateProgramWithSource); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateBuffer); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateImage); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateImage2D); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateUserEvent); + PADDLE_CL_ASSIGN_FROM_DLSYM(clRetainKernel); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateKernel); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetProgramInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clFlush); + PADDLE_CL_ASSIGN_FROM_DLSYM(clFinish); + PADDLE_CL_ASSIGN_FROM_DLSYM(clReleaseProgram); + PADDLE_CL_ASSIGN_FROM_DLSYM(clRetainContext); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetContextInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateProgramWithBinary); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateCommandQueue); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateCommandQueueWithProperties); + PADDLE_CL_ASSIGN_FROM_DLSYM(clReleaseCommandQueue); + PADDLE_CL_ASSIGN_FROM_DLSYM(clEnqueueMapBuffer); + PADDLE_CL_ASSIGN_FROM_DLSYM(clEnqueueMapImage); + PADDLE_CL_ASSIGN_FROM_DLSYM(clRetainProgram); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetProgramBuildInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clEnqueueReadBuffer); + PADDLE_CL_ASSIGN_FROM_DLSYM(clEnqueueReadImage); + PADDLE_CL_ASSIGN_FROM_DLSYM(clEnqueueWriteBuffer); + PADDLE_CL_ASSIGN_FROM_DLSYM(clWaitForEvents); + PADDLE_CL_ASSIGN_FROM_DLSYM(clReleaseEvent); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateContext); + PADDLE_CL_ASSIGN_FROM_DLSYM(clCreateContextFromType); + PADDLE_CL_ASSIGN_FROM_DLSYM(clReleaseContext); + PADDLE_CL_ASSIGN_FROM_DLSYM(clRetainCommandQueue); + PADDLE_CL_ASSIGN_FROM_DLSYM(clEnqueueUnmapMemObject); + PADDLE_CL_ASSIGN_FROM_DLSYM(clRetainMemObject); + PADDLE_CL_ASSIGN_FROM_DLSYM(clReleaseMemObject); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetDeviceInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetDeviceIDs); + PADDLE_CL_ASSIGN_FROM_DLSYM(clRetainDevice); + PADDLE_CL_ASSIGN_FROM_DLSYM(clReleaseDevice); + PADDLE_CL_ASSIGN_FROM_DLSYM(clRetainEvent); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetKernelWorkGroupInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetEventInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetEventProfilingInfo); + PADDLE_CL_ASSIGN_FROM_DLSYM(clGetImageInfo); + +#undef PADDLE_CL_ASSIGN_FROM_DLSYM + + return handle; +} + +} // namespace lite +} // namespace paddle + +CL_API_ENTRY cl_event clCreateUserEvent(cl_context context, cl_int *errcode_ret) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateUserEvent; + if (func != nullptr) { + return func(context, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +// Platform APIs +CL_API_ENTRY cl_int +clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, + cl_uint *num_platforms) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetPlatformIDs; + if (func != nullptr) { + return func(num_entries, platforms, num_platforms); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int +clGetPlatformInfo(cl_platform_id platform, cl_platform_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetPlatformInfo; + if (func != nullptr) { + return func(platform, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Device APIs +CL_API_ENTRY cl_int clGetDeviceIDs( + cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, + cl_device_id *devices, cl_uint *num_devices) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetDeviceIDs; + if (func != nullptr) { + return func(platform, device_type, num_entries, devices, num_devices); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int +clGetDeviceInfo(cl_device_id device, cl_device_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetDeviceInfo; + if (func != nullptr) { + return func(device, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clRetainDevice(cl_device_id device) + CL_API_SUFFIX__VERSION_1_2 { + auto func = paddle::lite::OpenCLLibrary::Get()->clRetainDevice; + if (func != nullptr) { + return func(device); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clReleaseDevice(cl_device_id device) + CL_API_SUFFIX__VERSION_1_2 { + auto func = paddle::lite::OpenCLLibrary::Get()->clReleaseDevice; + if (func != nullptr) { + return func(device); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Context APIs +CL_API_ENTRY cl_context clCreateContext( + const cl_context_properties *properties, cl_uint num_devices, + const cl_device_id *devices, + void(CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *), + void *user_data, cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateContext; + if (func != nullptr) { + return func(properties, num_devices, devices, pfn_notify, user_data, + errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_context clCreateContextFromType( + const cl_context_properties *properties, cl_device_type device_type, + void(CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *), + void *user_data, cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateContextFromType; + if (func != nullptr) { + return func(properties, device_type, pfn_notify, user_data, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_int clRetainContext(cl_context context) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clRetainContext; + if (func != nullptr) { + return func(context); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clReleaseContext(cl_context context) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clReleaseContext; + if (func != nullptr) { + return func(context); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int +clGetContextInfo(cl_context context, cl_context_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetContextInfo; + if (func != nullptr) { + return func(context, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Program Object APIs +CL_API_ENTRY cl_program clCreateProgramWithSource( + cl_context context, cl_uint count, const char **strings, + const size_t *lengths, cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateProgramWithSource; + if (func != nullptr) { + return func(context, count, strings, lengths, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_program clCreateProgramWithBinary( + 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 *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateProgramWithBinary; + if (func != nullptr) { + return func(context, num_devices, device_list, lengths, binaries, + binary_status, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_int +clGetProgramInfo(cl_program program, cl_program_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetProgramInfo; + if (func != nullptr) { + return func(program, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clGetProgramBuildInfo( + cl_program program, cl_device_id device, cl_program_build_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetProgramBuildInfo; + if (func != nullptr) { + return func(program, device, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clRetainProgram(cl_program program) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clRetainProgram; + if (func != nullptr) { + return func(program); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clReleaseProgram(cl_program program) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clReleaseProgram; + if (func != nullptr) { + return func(program); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clBuildProgram( + 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) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clBuildProgram; + if (func != nullptr) { + return func(program, num_devices, device_list, options, pfn_notify, + user_data); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Kernel Object APIs +CL_API_ENTRY cl_kernel +clCreateKernel(cl_program program, const char *kernel_name, + cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateKernel; + if (func != nullptr) { + return func(program, kernel_name, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_int clRetainKernel(cl_kernel kernel) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clRetainKernel; + if (func != nullptr) { + return func(kernel); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clReleaseKernel(cl_kernel kernel) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clReleaseKernel; + if (func != nullptr) { + return func(kernel); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clSetKernelArg(cl_kernel kernel, cl_uint arg_index, + size_t arg_size, const void *arg_value) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clSetKernelArg; + if (func != nullptr) { + return func(kernel, arg_index, arg_size, arg_value); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Memory Object APIs +CL_API_ENTRY cl_mem +clCreateBuffer(cl_context context, cl_mem_flags flags, size_t size, + void *host_ptr, cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateBuffer; + if (func != nullptr) { + return func(context, flags, size, host_ptr, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_mem clCreateImage( + cl_context context, cl_mem_flags flags, const cl_image_format *image_format, + const cl_image_desc *image_desc, void *host_ptr, + cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_2 { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateImage; + if (func != nullptr) { + return func(context, flags, image_format, image_desc, host_ptr, + errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_int clRetainMemObject(cl_mem memobj) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clRetainMemObject; + if (func != nullptr) { + return func(memobj); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clReleaseMemObject(cl_mem memobj) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clReleaseMemObject; + if (func != nullptr) { + return func(memobj); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clGetImageInfo(cl_mem image, cl_image_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetImageInfo; + if (func != nullptr) { + return func(image, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Command Queue APIs +CL_API_ENTRY cl_command_queue clCreateCommandQueueWithProperties( + cl_context context, cl_device_id device, + const cl_queue_properties *properties, + cl_int *errcode_ret) CL_API_SUFFIX__VERSION_2_0 { + auto func = + paddle::lite::OpenCLLibrary::Get()->clCreateCommandQueueWithProperties; + if (func != nullptr) { + return func(context, device, properties, errcode_ret); + } else { + // Fix MediaTek MT6771 OpenCL driver breakage + VLOG(3) << "Fallback to clCreateCommandQueue"; + if (properties[0] == CL_QUEUE_PROPERTIES) { +// When calling with OpenCL-CLHPP, the 2nd param is provided by caller. +#pragma GCC diagnostic push // disable warning both for clang and gcc +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + return clCreateCommandQueue(context, device, properties[1], errcode_ret); +#pragma GCC diagnostic pop + } else { + LOG(FATAL) << "Unknown calling parameters, check the code here"; + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } + } +} + +CL_API_ENTRY cl_int clRetainCommandQueue(cl_command_queue command_queue) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clRetainCommandQueue; + if (func != nullptr) { + return func(command_queue); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clReleaseCommandQueue(cl_command_queue command_queue) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clReleaseCommandQueue; + if (func != nullptr) { + return func(command_queue); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Enqueued Commands APIs +CL_API_ENTRY cl_int clEnqueueReadBuffer( + 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) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clEnqueueReadBuffer; + if (func != nullptr) { + return func(command_queue, buffer, blocking_read, offset, size, ptr, + num_events_in_wait_list, event_wait_list, event); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clEnqueueReadImage( + 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) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clEnqueueReadImage; + if (func != nullptr) { + return func(command_queue, image, blocking_read, origin, region, row_pitch, + slice_pitch, ptr, num_events_in_wait_list, event_wait_list, + event); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clEnqueueWriteBuffer( + 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) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clEnqueueWriteBuffer; + if (func != nullptr) { + return func(command_queue, buffer, blocking_write, offset, size, ptr, + num_events_in_wait_list, event_wait_list, event); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY void *clEnqueueMapBuffer( + cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, + cl_map_flags 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 *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clEnqueueMapBuffer; + if (func != nullptr) { + return func(command_queue, buffer, blocking_map, map_flags, offset, size, + num_events_in_wait_list, event_wait_list, event, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY void *clEnqueueMapImage( + cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, + cl_map_flags 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 *errcode_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clEnqueueMapImage; + if (func != nullptr) { + return func(command_queue, image, blocking_map, map_flags, origin, region, + image_row_pitch, image_slice_pitch, num_events_in_wait_list, + event_wait_list, event, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +CL_API_ENTRY cl_int clEnqueueUnmapMemObject( + 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) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clEnqueueUnmapMemObject; + if (func != nullptr) { + return func(command_queue, memobj, mapped_ptr, num_events_in_wait_list, + event_wait_list, event); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clGetKernelWorkGroupInfo( + cl_kernel kernel, cl_device_id device, cl_kernel_work_group_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetKernelWorkGroupInfo; + if (func != nullptr) { + return func(kernel, device, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clEnqueueNDRangeKernel( + 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) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clEnqueueNDRangeKernel; + if (func != nullptr) { + return func(command_queue, kernel, work_dim, global_work_offset, + global_work_size, local_work_size, num_events_in_wait_list, + event_wait_list, event); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Event Object APIs +CL_API_ENTRY cl_int clWaitForEvents( + cl_uint num_events, const cl_event *event_list) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clWaitForEvents; + if (func != nullptr) { + return func(num_events, event_list); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clRetainEvent(cl_event event) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clRetainEvent; + if (func != nullptr) { + return func(event); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clReleaseEvent(cl_event event) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clReleaseEvent; + if (func != nullptr) { + return func(event); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Event API +CL_API_ENTRY cl_int clGetEventInfo(cl_event event, cl_event_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetEventInfo; + if (func != nullptr) { + return func(event, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Profiling APIs +CL_API_ENTRY cl_int clGetEventProfilingInfo( + cl_event event, cl_profiling_info param_name, size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clGetEventProfilingInfo; + if (func != nullptr) { + return func(event, param_name, param_value_size, param_value, + param_value_size_ret); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Flush and Finish APIs +CL_API_ENTRY cl_int clFlush(cl_command_queue command_queue) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clFlush; + if (func != nullptr) { + return func(command_queue); + } else { + return CL_INVALID_PLATFORM; + } +} + +CL_API_ENTRY cl_int clFinish(cl_command_queue command_queue) + CL_API_SUFFIX__VERSION_1_0 { + auto func = paddle::lite::OpenCLLibrary::Get()->clFinish; + if (func != nullptr) { + return func(command_queue); + } else { + return CL_INVALID_PLATFORM; + } +} + +// Deprecated OpenCL 1.1 APIs +CL_API_ENTRY /* CL_EXT_PREFIX__VERSION_1_1_DEPRECATED */ cl_mem clCreateImage2D( + cl_context context, cl_mem_flags 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 *errcode_ret) /* CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED */ { + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateImage2D; + if (func != nullptr) { + return func(context, flags, image_format, image_width, image_height, + image_row_pitch, host_ptr, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +} + +// Deprecated OpenCL 2.0 APIs +CL_API_ENTRY /*CL_EXT_PREFIX__VERSION_1_2_DEPRECATED*/ cl_command_queue +clCreateCommandQueue(cl_context context, cl_device_id device, + cl_command_queue_properties properties, + cl_int *errcode_ret) +/* CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED */ { // NOLINT + auto func = paddle::lite::OpenCLLibrary::Get()->clCreateCommandQueue; + if (func != nullptr) { + return func(context, device, properties, errcode_ret); + } else { + if (errcode_ret != nullptr) *errcode_ret = CL_INVALID_PLATFORM; + return nullptr; + } +}