/* * Copyright (c) 2017 ARM Limited. * * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "arm_compute/core/CL/OpenCL.h" #include #include using clBuildProgram_func = cl_int (*)(cl_program, cl_uint, const cl_device_id *, const char *, void (*pfn_notify)(cl_program, void *), void *); using clEnqueueNDRangeKernel_func = 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 clSetKernelArg_func = cl_int (*)(cl_kernel, cl_uint, size_t, const void *); using clReleaseMemObject_func = cl_int (*)(cl_mem); using clEnqueueUnmapMemObject_func = cl_int (*)(cl_command_queue, cl_mem, void *, cl_uint, const cl_event *, cl_event *); using clRetainCommandQueue_func = cl_int (*)(cl_command_queue command_queue); using clReleaseContext_func = cl_int (*)(cl_context); using clReleaseEvent_func = cl_int (*)(cl_event); using clEnqueueWriteBuffer_func = cl_int (*)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *); using clEnqueueReadBuffer_func = cl_int (*)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *); using clGetProgramBuildInfo_func = cl_int (*)(cl_program, cl_device_id, cl_program_build_info, size_t, void *, size_t *); using clRetainProgram_func = cl_int (*)(cl_program program); using clEnqueueMapBuffer_func = 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 clReleaseCommandQueue_func = cl_int (*)(cl_command_queue); using clCreateProgramWithBinary_func = cl_program (*)(cl_context, cl_uint, const cl_device_id *, const size_t *, const unsigned char **, cl_int *, cl_int *); using clRetainContext_func = cl_int (*)(cl_context context); using clReleaseProgram_func = cl_int (*)(cl_program program); using clFlush_func = cl_int (*)(cl_command_queue command_queue); using clGetProgramInfo_func = cl_int (*)(cl_program, cl_program_info, size_t, void *, size_t *); using clCreateKernel_func = cl_kernel (*)(cl_program, const char *, cl_int *); using clRetainKernel_func = cl_int (*)(cl_kernel kernel); using clCreateBuffer_func = cl_mem (*)(cl_context, cl_mem_flags, size_t, void *, cl_int *); using clCreateProgramWithSource_func = cl_program (*)(cl_context, cl_uint, const char **, const size_t *, cl_int *); using clReleaseKernel_func = cl_int (*)(cl_kernel kernel); using clGetDeviceInfo_func = cl_int (*)(cl_device_id, cl_device_info, size_t, void *, size_t *); using clGetDeviceIDs_func = cl_int (*)(cl_platform_id, cl_device_type, cl_uint, cl_device_id *, cl_uint *); class CLSymbols { private: CLSymbols() { void *handle = dlopen("libOpenCL.so", RTLD_LAZY | RTLD_LOCAL); if(handle == nullptr) { std::cerr << "Can't load libOpenCL.so: " << dlerror() << std::endl; } else { clBuildProgram = reinterpret_cast(dlsym(handle, "clBuildProgram")); clEnqueueNDRangeKernel = reinterpret_cast(dlsym(handle, "clEnqueueNDRangeKernel")); clSetKernelArg = reinterpret_cast(dlsym(handle, "clSetKernelArg")); clReleaseKernel = reinterpret_cast(dlsym(handle, "clReleaseKernel")); clCreateProgramWithSource = reinterpret_cast(dlsym(handle, "clCreateProgramWithSource")); clCreateBuffer = reinterpret_cast(dlsym(handle, "clCreateBuffer")); clRetainKernel = reinterpret_cast(dlsym(handle, "clRetainKernel")); clCreateKernel = reinterpret_cast(dlsym(handle, "clCreateKernel")); clGetProgramInfo = reinterpret_cast(dlsym(handle, "clGetProgramInfo")); clFlush = reinterpret_cast(dlsym(handle, "clFlush")); clReleaseProgram = reinterpret_cast(dlsym(handle, "clReleaseProgram")); clRetainContext = reinterpret_cast(dlsym(handle, "clRetainContext")); clCreateProgramWithBinary = reinterpret_cast(dlsym(handle, "clCreateProgramWithBinary")); clReleaseCommandQueue = reinterpret_cast(dlsym(handle, "clReleaseCommandQueue")); clEnqueueMapBuffer = reinterpret_cast(dlsym(handle, "clEnqueueMapBuffer")); clRetainProgram = reinterpret_cast(dlsym(handle, "clRetainProgram")); clGetProgramBuildInfo = reinterpret_cast(dlsym(handle, "clGetProgramBuildInfo")); clEnqueueReadBuffer = reinterpret_cast(dlsym(handle, "clEnqueueReadBuffer")); clEnqueueWriteBuffer = reinterpret_cast(dlsym(handle, "clEnqueueWriteBuffer")); clReleaseEvent = reinterpret_cast(dlsym(handle, "clReleaseEvent")); clReleaseContext = reinterpret_cast(dlsym(handle, "clReleaseContext")); clRetainCommandQueue = reinterpret_cast(dlsym(handle, "clRetainCommandQueue")); clEnqueueUnmapMemObject = reinterpret_cast(dlsym(handle, "clEnqueueUnmapMemObject")); clReleaseMemObject = reinterpret_cast(dlsym(handle, "clReleaseMemObject")); clGetDeviceInfo = reinterpret_cast(dlsym(handle, "clGetDeviceInfo")); clGetDeviceIDs = reinterpret_cast(dlsym(handle, "clGetDeviceIDs")); dlclose(handle); } } public: static CLSymbols &get() { static CLSymbols symbols = CLSymbols(); return symbols; } clBuildProgram_func clBuildProgram = nullptr; clEnqueueNDRangeKernel_func clEnqueueNDRangeKernel = nullptr; clSetKernelArg_func clSetKernelArg = nullptr; clReleaseKernel_func clReleaseKernel = nullptr; clCreateProgramWithSource_func clCreateProgramWithSource = nullptr; clCreateBuffer_func clCreateBuffer = nullptr; clRetainKernel_func clRetainKernel = nullptr; clCreateKernel_func clCreateKernel = nullptr; clGetProgramInfo_func clGetProgramInfo = nullptr; clFlush_func clFlush = nullptr; clReleaseProgram_func clReleaseProgram = nullptr; clRetainContext_func clRetainContext = nullptr; clCreateProgramWithBinary_func clCreateProgramWithBinary = nullptr; clReleaseCommandQueue_func clReleaseCommandQueue = nullptr; clEnqueueMapBuffer_func clEnqueueMapBuffer = nullptr; clRetainProgram_func clRetainProgram = nullptr; clGetProgramBuildInfo_func clGetProgramBuildInfo = nullptr; clEnqueueReadBuffer_func clEnqueueReadBuffer = nullptr; clEnqueueWriteBuffer_func clEnqueueWriteBuffer = nullptr; clReleaseEvent_func clReleaseEvent = nullptr; clReleaseContext_func clReleaseContext = nullptr; clRetainCommandQueue_func clRetainCommandQueue = nullptr; clEnqueueUnmapMemObject_func clEnqueueUnmapMemObject = nullptr; clReleaseMemObject_func clReleaseMemObject = nullptr; clGetDeviceInfo_func clGetDeviceInfo = nullptr; clGetDeviceIDs_func clGetDeviceIDs = nullptr; }; bool arm_compute::opencl_is_available() { return CLSymbols::get().clBuildProgram != nullptr; } 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) { auto func = CLSymbols::get().clBuildProgram; if(func != nullptr) { return func(program, num_devices, device_list, options, pfn_notify, user_data); } else { return CL_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::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_OUT_OF_RESOURCES; } } cl_int clSetKernelArg( cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value) { auto func = CLSymbols::get().clSetKernelArg; if(func != nullptr) { return func(kernel, arg_index, arg_size, arg_value); } else { return CL_OUT_OF_RESOURCES; } } cl_int clReleaseMemObject(cl_mem memobj) { auto func = CLSymbols::get().clReleaseMemObject; if(func != nullptr) { return func(memobj); } else { return CL_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::get().clEnqueueUnmapMemObject; if(func != nullptr) { return func(command_queue, memobj, mapped_ptr, num_events_in_wait_list, event_wait_list, event); } else { return CL_OUT_OF_RESOURCES; } } cl_int clRetainCommandQueue(cl_command_queue command_queue) { auto func = CLSymbols::get().clRetainCommandQueue; if(func != nullptr) { return func(command_queue); } else { return CL_OUT_OF_RESOURCES; } } cl_int clReleaseContext(cl_context context) { auto func = CLSymbols::get().clReleaseContext; if(func != nullptr) { return func(context); } else { return CL_OUT_OF_RESOURCES; } } cl_int clReleaseEvent(cl_event event) { auto func = CLSymbols::get().clReleaseEvent; if(func != nullptr) { return func(event); } else { return CL_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::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_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::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_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::get().clGetProgramBuildInfo; if(func != nullptr) { return func(program, device, param_name, param_value_size, param_value, param_value_size_ret); } else { return CL_OUT_OF_RESOURCES; } } cl_int clRetainProgram(cl_program program) { auto func = CLSymbols::get().clRetainProgram; if(func != nullptr) { return func(program); } else { return CL_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::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_OUT_OF_RESOURCES; } return nullptr; } } cl_int clReleaseCommandQueue(cl_command_queue command_queue) { auto func = CLSymbols::get().clReleaseCommandQueue; if(func != nullptr) { return func(command_queue); } else { return CL_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::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_OUT_OF_RESOURCES; } return nullptr; } } cl_int clRetainContext(cl_context context) { auto func = CLSymbols::get().clRetainContext; if(func != nullptr) { return func(context); } else { return CL_OUT_OF_RESOURCES; } } cl_int clReleaseProgram(cl_program program) { auto func = CLSymbols::get().clReleaseProgram; if(func != nullptr) { return func(program); } else { return CL_OUT_OF_RESOURCES; } } cl_int clFlush(cl_command_queue command_queue) { auto func = CLSymbols::get().clFlush; if(func != nullptr) { return func(command_queue); } else { return CL_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::get().clGetProgramInfo; if(func != nullptr) { return func(program, param_name, param_value_size, param_value, param_value_size_ret); } else { return CL_OUT_OF_RESOURCES; } } cl_kernel clCreateKernel( cl_program program, const char *kernel_name, cl_int *errcode_ret) { auto func = CLSymbols::get().clCreateKernel; if(func != nullptr) { return func(program, kernel_name, errcode_ret); } else { if(errcode_ret != nullptr) { *errcode_ret = CL_OUT_OF_RESOURCES; } return nullptr; } } cl_int clRetainKernel(cl_kernel kernel) { auto func = CLSymbols::get().clRetainKernel; if(func != nullptr) { return func(kernel); } else { return CL_OUT_OF_RESOURCES; } } cl_mem clCreateBuffer( cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errcode_ret) { auto func = CLSymbols::get().clCreateBuffer; if(func != nullptr) { return func(context, flags, size, host_ptr, errcode_ret); } else { if(errcode_ret != nullptr) { *errcode_ret = CL_OUT_OF_RESOURCES; } return nullptr; } } cl_program clCreateProgramWithSource( cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret) { auto func = CLSymbols::get().clCreateProgramWithSource; if(func != nullptr) { return func(context, count, strings, lengths, errcode_ret); } else { if(errcode_ret != nullptr) { *errcode_ret = CL_OUT_OF_RESOURCES; } return nullptr; } } cl_int clReleaseKernel(cl_kernel kernel) { auto func = CLSymbols::get().clReleaseKernel; if(func != nullptr) { return func(kernel); } else { return CL_OUT_OF_RESOURCES; } } cl_int clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, cl_device_id *devices, cl_uint *num_devices) { auto func = CLSymbols::get().clGetDeviceIDs; if(func != nullptr) { return func(platform, device_type, num_entries, devices, num_devices); } else { return CL_OUT_OF_RESOURCES; } } 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) { auto func = CLSymbols::get().clGetDeviceInfo; if(func != nullptr) { return func(device, param_name, param_value_size, param_value, param_value_size_ret); } else { return CL_OUT_OF_RESOURCES; } }