1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/lite/delegates/gpu/cl/opencl_wrapper.h"
17
18 #if defined(_WIN32)
19 #define __WINDOWS__
20 #endif
21
22 #ifdef __WINDOWS__
23 #include <windows.h>
24 #else
25 #include <dlfcn.h>
26 #endif
27
28 #include <string>
29
30 #include "absl/strings/str_cat.h"
31 #include "tensorflow/lite/delegates/gpu/common/status.h"
32
33 namespace tflite {
34 namespace gpu {
35 namespace cl {
36
37 #ifdef __ANDROID__
38 #define LoadFunction(function) \
39 if (use_wrapper) { \
40 function = reinterpret_cast<PFN_##function>(loadOpenCLPointer(#function)); \
41 } else { \
42 function = reinterpret_cast<PFN_##function>(dlsym(libopencl, #function)); \
43 }
44 #elif defined(__WINDOWS__)
45 #define LoadFunction(function) \
46 function = \
47 reinterpret_cast<PFN_##function>(GetProcAddress(libopencl, #function));
48 #else
49 #define LoadFunction(function) \
50 function = reinterpret_cast<PFN_##function>(dlsym(libopencl, #function));
51 #endif
52
53 #ifdef __WINDOWS__
54 void LoadOpenCLFunctions(HMODULE libopencl);
55 #else
56 void LoadOpenCLFunctions(void* libopencl, bool use_wrapper);
57 #endif
58
LoadOpenCL()59 absl::Status LoadOpenCL() {
60 #ifdef __WINDOWS__
61 HMODULE libopencl = LoadLibraryA("OpenCL.dll");
62 if (libopencl) {
63 LoadOpenCLFunctions(libopencl);
64 return absl::OkStatus();
65 } else {
66 DWORD error_code = GetLastError();
67 return absl::UnknownError(absl::StrCat(
68 "Can not open OpenCL library on this device, error code - ",
69 error_code));
70 }
71 #else
72 void* libopencl = nullptr;
73 #ifdef __ANDROID__
74 // Pixel phone or auto?
75 libopencl = dlopen("libOpenCL-pixel.so", RTLD_NOW | RTLD_LOCAL);
76 if (!libopencl) {
77 libopencl = dlopen("libOpenCL-car.so", RTLD_NOW | RTLD_LOCAL);
78 }
79 if (libopencl) {
80 typedef void (*enableOpenCL_t)();
81 enableOpenCL_t enableOpenCL =
82 reinterpret_cast<enableOpenCL_t>(dlsym(libopencl, "enableOpenCL"));
83 enableOpenCL();
84 LoadOpenCLFunctions(libopencl, true);
85 return absl::OkStatus();
86 }
87 #endif
88 #ifdef __APPLE__
89 static const char* kClLibName =
90 "/System/Library/Frameworks/OpenCL.framework/OpenCL";
91 #else
92 static const char* kClLibName = "libOpenCL.so";
93 #endif
94 libopencl = dlopen(kClLibName, RTLD_NOW | RTLD_LOCAL);
95 if (libopencl) {
96 LoadOpenCLFunctions(libopencl, false);
97 return absl::OkStatus();
98 }
99 // record error
100 std::string error(dlerror());
101 return absl::UnknownError(
102 absl::StrCat("Can not open OpenCL library on this device - ", error));
103 #endif
104 }
105
106 #ifdef __WINDOWS__
LoadOpenCLFunctions(HMODULE libopencl)107 void LoadOpenCLFunctions(HMODULE libopencl) {
108 #else
109 void LoadOpenCLFunctions(void* libopencl, bool use_wrapper) {
110 #ifdef __ANDROID__
111 typedef void* (*loadOpenCLPointer_t)(const char* name);
112 loadOpenCLPointer_t loadOpenCLPointer;
113 if (use_wrapper) {
114 loadOpenCLPointer = reinterpret_cast<loadOpenCLPointer_t>(
115 dlsym(libopencl, "loadOpenCLPointer"));
116 }
117 #endif
118 #endif
119
120 LoadFunction(clGetPlatformIDs);
121 LoadFunction(clGetPlatformInfo);
122 LoadFunction(clGetDeviceIDs);
123 LoadFunction(clGetDeviceInfo);
124 LoadFunction(clCreateSubDevices);
125 LoadFunction(clRetainDevice);
126 LoadFunction(clReleaseDevice);
127 LoadFunction(clCreateContext);
128 LoadFunction(clCreateContextFromType);
129 LoadFunction(clRetainContext);
130 LoadFunction(clReleaseContext);
131 LoadFunction(clGetContextInfo);
132 LoadFunction(clCreateCommandQueueWithProperties);
133 LoadFunction(clRetainCommandQueue);
134 LoadFunction(clReleaseCommandQueue);
135 LoadFunction(clGetCommandQueueInfo);
136 LoadFunction(clCreateBuffer);
137 LoadFunction(clCreateSubBuffer);
138 LoadFunction(clCreateImage);
139 LoadFunction(clCreatePipe);
140 LoadFunction(clRetainMemObject);
141 LoadFunction(clReleaseMemObject);
142 LoadFunction(clGetSupportedImageFormats);
143 LoadFunction(clGetMemObjectInfo);
144 LoadFunction(clGetImageInfo);
145 LoadFunction(clGetPipeInfo);
146 LoadFunction(clSetMemObjectDestructorCallback);
147 LoadFunction(clSVMAlloc);
148 LoadFunction(clSVMFree);
149 LoadFunction(clCreateSamplerWithProperties);
150 LoadFunction(clRetainSampler);
151 LoadFunction(clReleaseSampler);
152 LoadFunction(clGetSamplerInfo);
153 LoadFunction(clCreateProgramWithSource);
154 LoadFunction(clCreateProgramWithBinary);
155 LoadFunction(clCreateProgramWithBuiltInKernels);
156 LoadFunction(clRetainProgram);
157 LoadFunction(clReleaseProgram);
158 LoadFunction(clBuildProgram);
159 LoadFunction(clCompileProgram);
160 LoadFunction(clLinkProgram);
161 LoadFunction(clUnloadPlatformCompiler);
162 LoadFunction(clGetProgramInfo);
163 LoadFunction(clGetProgramBuildInfo);
164 LoadFunction(clCreateKernel);
165 LoadFunction(clCreateKernelsInProgram);
166 LoadFunction(clRetainKernel);
167 LoadFunction(clReleaseKernel);
168 LoadFunction(clSetKernelArg);
169 LoadFunction(clSetKernelArgSVMPointer);
170 LoadFunction(clSetKernelExecInfo);
171 LoadFunction(clGetKernelInfo);
172 LoadFunction(clGetKernelArgInfo);
173 LoadFunction(clGetKernelWorkGroupInfo);
174 LoadFunction(clWaitForEvents);
175 LoadFunction(clGetEventInfo);
176 LoadFunction(clCreateUserEvent);
177 LoadFunction(clRetainEvent);
178 LoadFunction(clReleaseEvent);
179 LoadFunction(clSetUserEventStatus);
180 LoadFunction(clSetEventCallback);
181 LoadFunction(clGetEventProfilingInfo);
182 LoadFunction(clFlush);
183 LoadFunction(clFinish);
184 LoadFunction(clEnqueueReadBuffer);
185 LoadFunction(clEnqueueReadBufferRect);
186 LoadFunction(clEnqueueWriteBuffer);
187 LoadFunction(clEnqueueWriteBufferRect);
188 LoadFunction(clEnqueueFillBuffer);
189 LoadFunction(clEnqueueCopyBuffer);
190 LoadFunction(clEnqueueCopyBufferRect);
191 LoadFunction(clEnqueueReadImage);
192 LoadFunction(clEnqueueWriteImage);
193 LoadFunction(clEnqueueFillImage);
194 LoadFunction(clEnqueueCopyImage);
195 LoadFunction(clEnqueueCopyImageToBuffer);
196 LoadFunction(clEnqueueCopyBufferToImage);
197 LoadFunction(clEnqueueMapBuffer);
198 LoadFunction(clEnqueueMapImage);
199 LoadFunction(clEnqueueUnmapMemObject);
200 LoadFunction(clEnqueueMigrateMemObjects);
201 LoadFunction(clEnqueueNDRangeKernel);
202 LoadFunction(clEnqueueNativeKernel);
203 LoadFunction(clEnqueueMarkerWithWaitList);
204 LoadFunction(clEnqueueBarrierWithWaitList);
205 LoadFunction(clEnqueueSVMFree);
206 LoadFunction(clEnqueueSVMMemcpy);
207 LoadFunction(clEnqueueSVMMemFill);
208 LoadFunction(clEnqueueSVMMap);
209 LoadFunction(clEnqueueSVMUnmap);
210 LoadFunction(clGetExtensionFunctionAddressForPlatform);
211 LoadFunction(clCreateImage2D);
212 LoadFunction(clCreateImage3D);
213 LoadFunction(clEnqueueMarker);
214 LoadFunction(clEnqueueWaitForEvents);
215 LoadFunction(clEnqueueBarrier);
216 LoadFunction(clUnloadCompiler);
217 LoadFunction(clGetExtensionFunctionAddress);
218 LoadFunction(clCreateCommandQueue);
219 LoadFunction(clCreateSampler);
220 LoadFunction(clEnqueueTask);
221
222 // OpenGL sharing
223 LoadFunction(clCreateFromGLBuffer);
224 LoadFunction(clCreateFromGLTexture);
225 LoadFunction(clEnqueueAcquireGLObjects);
226 LoadFunction(clEnqueueReleaseGLObjects);
227
228 // cl_khr_egl_event extension
229 LoadFunction(clCreateEventFromEGLSyncKHR);
230
231 // EGL sharing
232 LoadFunction(clCreateFromEGLImageKHR);
233 LoadFunction(clEnqueueAcquireEGLObjectsKHR);
234 LoadFunction(clEnqueueReleaseEGLObjectsKHR);
235
236 LoadQcomExtensionFunctions();
237 }
238
239 // No OpenCL support, do not set function addresses
240 PFN_clGetPlatformIDs clGetPlatformIDs;
241 PFN_clGetPlatformInfo clGetPlatformInfo;
242 PFN_clGetDeviceIDs clGetDeviceIDs;
243 PFN_clGetDeviceInfo clGetDeviceInfo;
244 PFN_clCreateSubDevices clCreateSubDevices;
245 PFN_clRetainDevice clRetainDevice;
246 PFN_clReleaseDevice clReleaseDevice;
247 PFN_clCreateContext clCreateContext;
248 PFN_clCreateContextFromType clCreateContextFromType;
249 PFN_clRetainContext clRetainContext;
250 PFN_clReleaseContext clReleaseContext;
251 PFN_clGetContextInfo clGetContextInfo;
252 PFN_clCreateCommandQueueWithProperties clCreateCommandQueueWithProperties;
253 PFN_clRetainCommandQueue clRetainCommandQueue;
254 PFN_clReleaseCommandQueue clReleaseCommandQueue;
255 PFN_clGetCommandQueueInfo clGetCommandQueueInfo;
256 PFN_clCreateBuffer clCreateBuffer;
257 PFN_clCreateSubBuffer clCreateSubBuffer;
258 PFN_clCreateImage clCreateImage;
259 PFN_clCreatePipe clCreatePipe;
260 PFN_clRetainMemObject clRetainMemObject;
261 PFN_clReleaseMemObject clReleaseMemObject;
262 PFN_clGetSupportedImageFormats clGetSupportedImageFormats;
263 PFN_clGetMemObjectInfo clGetMemObjectInfo;
264 PFN_clGetImageInfo clGetImageInfo;
265 PFN_clGetPipeInfo clGetPipeInfo;
266 PFN_clSetMemObjectDestructorCallback clSetMemObjectDestructorCallback;
267 PFN_clSVMAlloc clSVMAlloc;
268 PFN_clSVMFree clSVMFree;
269 PFN_clCreateSamplerWithProperties clCreateSamplerWithProperties;
270 PFN_clRetainSampler clRetainSampler;
271 PFN_clReleaseSampler clReleaseSampler;
272 PFN_clGetSamplerInfo clGetSamplerInfo;
273 PFN_clCreateProgramWithSource clCreateProgramWithSource;
274 PFN_clCreateProgramWithBinary clCreateProgramWithBinary;
275 PFN_clCreateProgramWithBuiltInKernels clCreateProgramWithBuiltInKernels;
276 PFN_clRetainProgram clRetainProgram;
277 PFN_clReleaseProgram clReleaseProgram;
278 PFN_clBuildProgram clBuildProgram;
279 PFN_clCompileProgram clCompileProgram;
280 PFN_clLinkProgram clLinkProgram;
281 PFN_clUnloadPlatformCompiler clUnloadPlatformCompiler;
282 PFN_clGetProgramInfo clGetProgramInfo;
283 PFN_clGetProgramBuildInfo clGetProgramBuildInfo;
284 PFN_clCreateKernel clCreateKernel;
285 PFN_clCreateKernelsInProgram clCreateKernelsInProgram;
286 PFN_clRetainKernel clRetainKernel;
287 PFN_clReleaseKernel clReleaseKernel;
288 PFN_clSetKernelArg clSetKernelArg;
289 PFN_clSetKernelArgSVMPointer clSetKernelArgSVMPointer;
290 PFN_clSetKernelExecInfo clSetKernelExecInfo;
291 PFN_clGetKernelInfo clGetKernelInfo;
292 PFN_clGetKernelArgInfo clGetKernelArgInfo;
293 PFN_clGetKernelWorkGroupInfo clGetKernelWorkGroupInfo;
294 PFN_clWaitForEvents clWaitForEvents;
295 PFN_clGetEventInfo clGetEventInfo;
296 PFN_clCreateUserEvent clCreateUserEvent;
297 PFN_clRetainEvent clRetainEvent;
298 PFN_clReleaseEvent clReleaseEvent;
299 PFN_clSetUserEventStatus clSetUserEventStatus;
300 PFN_clSetEventCallback clSetEventCallback;
301 PFN_clGetEventProfilingInfo clGetEventProfilingInfo;
302 PFN_clFlush clFlush;
303 PFN_clFinish clFinish;
304 PFN_clEnqueueReadBuffer clEnqueueReadBuffer;
305 PFN_clEnqueueReadBufferRect clEnqueueReadBufferRect;
306 PFN_clEnqueueWriteBuffer clEnqueueWriteBuffer;
307 PFN_clEnqueueWriteBufferRect clEnqueueWriteBufferRect;
308 PFN_clEnqueueFillBuffer clEnqueueFillBuffer;
309 PFN_clEnqueueCopyBuffer clEnqueueCopyBuffer;
310 PFN_clEnqueueCopyBufferRect clEnqueueCopyBufferRect;
311 PFN_clEnqueueReadImage clEnqueueReadImage;
312 PFN_clEnqueueWriteImage clEnqueueWriteImage;
313 PFN_clEnqueueFillImage clEnqueueFillImage;
314 PFN_clEnqueueCopyImage clEnqueueCopyImage;
315 PFN_clEnqueueCopyImageToBuffer clEnqueueCopyImageToBuffer;
316 PFN_clEnqueueCopyBufferToImage clEnqueueCopyBufferToImage;
317 PFN_clEnqueueMapBuffer clEnqueueMapBuffer;
318 PFN_clEnqueueMapImage clEnqueueMapImage;
319 PFN_clEnqueueUnmapMemObject clEnqueueUnmapMemObject;
320 PFN_clEnqueueMigrateMemObjects clEnqueueMigrateMemObjects;
321 PFN_clEnqueueNDRangeKernel clEnqueueNDRangeKernel;
322 PFN_clEnqueueNativeKernel clEnqueueNativeKernel;
323 PFN_clEnqueueMarkerWithWaitList clEnqueueMarkerWithWaitList;
324 PFN_clEnqueueBarrierWithWaitList clEnqueueBarrierWithWaitList;
325 PFN_clEnqueueSVMFree clEnqueueSVMFree;
326 PFN_clEnqueueSVMMemcpy clEnqueueSVMMemcpy;
327 PFN_clEnqueueSVMMemFill clEnqueueSVMMemFill;
328 PFN_clEnqueueSVMMap clEnqueueSVMMap;
329 PFN_clEnqueueSVMUnmap clEnqueueSVMUnmap;
330 PFN_clGetExtensionFunctionAddressForPlatform
331 clGetExtensionFunctionAddressForPlatform;
332 PFN_clCreateImage2D clCreateImage2D;
333 PFN_clCreateImage3D clCreateImage3D;
334 PFN_clEnqueueMarker clEnqueueMarker;
335 PFN_clEnqueueWaitForEvents clEnqueueWaitForEvents;
336 PFN_clEnqueueBarrier clEnqueueBarrier;
337 PFN_clUnloadCompiler clUnloadCompiler;
338 PFN_clGetExtensionFunctionAddress clGetExtensionFunctionAddress;
339 PFN_clCreateCommandQueue clCreateCommandQueue;
340 PFN_clCreateSampler clCreateSampler;
341 PFN_clEnqueueTask clEnqueueTask;
342
343 // OpenGL sharing
344 PFN_clCreateFromGLBuffer clCreateFromGLBuffer;
345 PFN_clCreateFromGLTexture clCreateFromGLTexture;
346 PFN_clEnqueueAcquireGLObjects clEnqueueAcquireGLObjects;
347 PFN_clEnqueueReleaseGLObjects clEnqueueReleaseGLObjects;
348
349 // cl_khr_egl_event extension
350 PFN_clCreateEventFromEGLSyncKHR clCreateEventFromEGLSyncKHR;
351
352 // EGL sharing
353 PFN_clCreateFromEGLImageKHR clCreateFromEGLImageKHR;
354 PFN_clEnqueueAcquireEGLObjectsKHR clEnqueueAcquireEGLObjectsKHR;
355 PFN_clEnqueueReleaseEGLObjectsKHR clEnqueueReleaseEGLObjectsKHR;
356
357 DEFINE_QCOM_FUNCTION_PTRS
358
359 cl_mem CreateImage2DLegacy(cl_context context, cl_mem_flags flags,
360 const cl_image_format* image_format,
361 const cl_image_desc* image_desc, void* host_ptr,
362 cl_int* errcode_ret) {
363 if (clCreateImage) { // clCreateImage available since OpenCL 1.2
364 return clCreateImage(context, flags, image_format, image_desc, host_ptr,
365 errcode_ret);
366 } else {
367 return clCreateImage2D(context, flags, image_format,
368 image_desc->image_width, image_desc->image_height,
369 image_desc->image_row_pitch, host_ptr, errcode_ret);
370 }
371 }
372
373 cl_mem CreateImage3DLegacy(cl_context context, cl_mem_flags flags,
374 const cl_image_format* image_format,
375 const cl_image_desc* image_desc, void* host_ptr,
376 cl_int* errcode_ret) {
377 if (clCreateImage) { // clCreateImage available since OpenCL 1.2
378 return clCreateImage(context, flags, image_format, image_desc, host_ptr,
379 errcode_ret);
380 } else {
381 return clCreateImage3D(context, flags, image_format,
382 image_desc->image_width, image_desc->image_height,
383 image_desc->image_depth, image_desc->image_row_pitch,
384 image_desc->image_slice_pitch, host_ptr,
385 errcode_ret);
386 }
387 }
388 } // namespace cl
389 } // namespace gpu
390 } // namespace tflite
391