• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
237 // No OpenCL support, do not set function addresses
238 PFN_clGetPlatformIDs clGetPlatformIDs;
239 PFN_clGetPlatformInfo clGetPlatformInfo;
240 PFN_clGetDeviceIDs clGetDeviceIDs;
241 PFN_clGetDeviceInfo clGetDeviceInfo;
242 PFN_clCreateSubDevices clCreateSubDevices;
243 PFN_clRetainDevice clRetainDevice;
244 PFN_clReleaseDevice clReleaseDevice;
245 PFN_clCreateContext clCreateContext;
246 PFN_clCreateContextFromType clCreateContextFromType;
247 PFN_clRetainContext clRetainContext;
248 PFN_clReleaseContext clReleaseContext;
249 PFN_clGetContextInfo clGetContextInfo;
250 PFN_clCreateCommandQueueWithProperties clCreateCommandQueueWithProperties;
251 PFN_clRetainCommandQueue clRetainCommandQueue;
252 PFN_clReleaseCommandQueue clReleaseCommandQueue;
253 PFN_clGetCommandQueueInfo clGetCommandQueueInfo;
254 PFN_clCreateBuffer clCreateBuffer;
255 PFN_clCreateSubBuffer clCreateSubBuffer;
256 PFN_clCreateImage clCreateImage;
257 PFN_clCreatePipe clCreatePipe;
258 PFN_clRetainMemObject clRetainMemObject;
259 PFN_clReleaseMemObject clReleaseMemObject;
260 PFN_clGetSupportedImageFormats clGetSupportedImageFormats;
261 PFN_clGetMemObjectInfo clGetMemObjectInfo;
262 PFN_clGetImageInfo clGetImageInfo;
263 PFN_clGetPipeInfo clGetPipeInfo;
264 PFN_clSetMemObjectDestructorCallback clSetMemObjectDestructorCallback;
265 PFN_clSVMAlloc clSVMAlloc;
266 PFN_clSVMFree clSVMFree;
267 PFN_clCreateSamplerWithProperties clCreateSamplerWithProperties;
268 PFN_clRetainSampler clRetainSampler;
269 PFN_clReleaseSampler clReleaseSampler;
270 PFN_clGetSamplerInfo clGetSamplerInfo;
271 PFN_clCreateProgramWithSource clCreateProgramWithSource;
272 PFN_clCreateProgramWithBinary clCreateProgramWithBinary;
273 PFN_clCreateProgramWithBuiltInKernels clCreateProgramWithBuiltInKernels;
274 PFN_clRetainProgram clRetainProgram;
275 PFN_clReleaseProgram clReleaseProgram;
276 PFN_clBuildProgram clBuildProgram;
277 PFN_clCompileProgram clCompileProgram;
278 PFN_clLinkProgram clLinkProgram;
279 PFN_clUnloadPlatformCompiler clUnloadPlatformCompiler;
280 PFN_clGetProgramInfo clGetProgramInfo;
281 PFN_clGetProgramBuildInfo clGetProgramBuildInfo;
282 PFN_clCreateKernel clCreateKernel;
283 PFN_clCreateKernelsInProgram clCreateKernelsInProgram;
284 PFN_clRetainKernel clRetainKernel;
285 PFN_clReleaseKernel clReleaseKernel;
286 PFN_clSetKernelArg clSetKernelArg;
287 PFN_clSetKernelArgSVMPointer clSetKernelArgSVMPointer;
288 PFN_clSetKernelExecInfo clSetKernelExecInfo;
289 PFN_clGetKernelInfo clGetKernelInfo;
290 PFN_clGetKernelArgInfo clGetKernelArgInfo;
291 PFN_clGetKernelWorkGroupInfo clGetKernelWorkGroupInfo;
292 PFN_clWaitForEvents clWaitForEvents;
293 PFN_clGetEventInfo clGetEventInfo;
294 PFN_clCreateUserEvent clCreateUserEvent;
295 PFN_clRetainEvent clRetainEvent;
296 PFN_clReleaseEvent clReleaseEvent;
297 PFN_clSetUserEventStatus clSetUserEventStatus;
298 PFN_clSetEventCallback clSetEventCallback;
299 PFN_clGetEventProfilingInfo clGetEventProfilingInfo;
300 PFN_clFlush clFlush;
301 PFN_clFinish clFinish;
302 PFN_clEnqueueReadBuffer clEnqueueReadBuffer;
303 PFN_clEnqueueReadBufferRect clEnqueueReadBufferRect;
304 PFN_clEnqueueWriteBuffer clEnqueueWriteBuffer;
305 PFN_clEnqueueWriteBufferRect clEnqueueWriteBufferRect;
306 PFN_clEnqueueFillBuffer clEnqueueFillBuffer;
307 PFN_clEnqueueCopyBuffer clEnqueueCopyBuffer;
308 PFN_clEnqueueCopyBufferRect clEnqueueCopyBufferRect;
309 PFN_clEnqueueReadImage clEnqueueReadImage;
310 PFN_clEnqueueWriteImage clEnqueueWriteImage;
311 PFN_clEnqueueFillImage clEnqueueFillImage;
312 PFN_clEnqueueCopyImage clEnqueueCopyImage;
313 PFN_clEnqueueCopyImageToBuffer clEnqueueCopyImageToBuffer;
314 PFN_clEnqueueCopyBufferToImage clEnqueueCopyBufferToImage;
315 PFN_clEnqueueMapBuffer clEnqueueMapBuffer;
316 PFN_clEnqueueMapImage clEnqueueMapImage;
317 PFN_clEnqueueUnmapMemObject clEnqueueUnmapMemObject;
318 PFN_clEnqueueMigrateMemObjects clEnqueueMigrateMemObjects;
319 PFN_clEnqueueNDRangeKernel clEnqueueNDRangeKernel;
320 PFN_clEnqueueNativeKernel clEnqueueNativeKernel;
321 PFN_clEnqueueMarkerWithWaitList clEnqueueMarkerWithWaitList;
322 PFN_clEnqueueBarrierWithWaitList clEnqueueBarrierWithWaitList;
323 PFN_clEnqueueSVMFree clEnqueueSVMFree;
324 PFN_clEnqueueSVMMemcpy clEnqueueSVMMemcpy;
325 PFN_clEnqueueSVMMemFill clEnqueueSVMMemFill;
326 PFN_clEnqueueSVMMap clEnqueueSVMMap;
327 PFN_clEnqueueSVMUnmap clEnqueueSVMUnmap;
328 PFN_clGetExtensionFunctionAddressForPlatform
329     clGetExtensionFunctionAddressForPlatform;
330 PFN_clCreateImage2D clCreateImage2D;
331 PFN_clCreateImage3D clCreateImage3D;
332 PFN_clEnqueueMarker clEnqueueMarker;
333 PFN_clEnqueueWaitForEvents clEnqueueWaitForEvents;
334 PFN_clEnqueueBarrier clEnqueueBarrier;
335 PFN_clUnloadCompiler clUnloadCompiler;
336 PFN_clGetExtensionFunctionAddress clGetExtensionFunctionAddress;
337 PFN_clCreateCommandQueue clCreateCommandQueue;
338 PFN_clCreateSampler clCreateSampler;
339 PFN_clEnqueueTask clEnqueueTask;
340 
341 // OpenGL sharing
342 PFN_clCreateFromGLBuffer clCreateFromGLBuffer;
343 PFN_clCreateFromGLTexture clCreateFromGLTexture;
344 PFN_clEnqueueAcquireGLObjects clEnqueueAcquireGLObjects;
345 PFN_clEnqueueReleaseGLObjects clEnqueueReleaseGLObjects;
346 
347 // cl_khr_egl_event extension
348 PFN_clCreateEventFromEGLSyncKHR clCreateEventFromEGLSyncKHR;
349 
350 // EGL sharing
351 PFN_clCreateFromEGLImageKHR clCreateFromEGLImageKHR;
352 PFN_clEnqueueAcquireEGLObjectsKHR clEnqueueAcquireEGLObjectsKHR;
353 PFN_clEnqueueReleaseEGLObjectsKHR clEnqueueReleaseEGLObjectsKHR;
354 
355 cl_mem CreateImage2DLegacy(cl_context context, cl_mem_flags flags,
356                            const cl_image_format* image_format,
357                            const cl_image_desc* image_desc, void* host_ptr,
358                            cl_int* errcode_ret) {
359   if (clCreateImage) {  // clCreateImage available since OpenCL 1.2
360     return clCreateImage(context, flags, image_format, image_desc, host_ptr,
361                          errcode_ret);
362   } else {
363     return clCreateImage2D(context, flags, image_format,
364                            image_desc->image_width, image_desc->image_height,
365                            image_desc->image_row_pitch, host_ptr, errcode_ret);
366   }
367 }
368 
369 cl_mem CreateImage3DLegacy(cl_context context, cl_mem_flags flags,
370                            const cl_image_format* image_format,
371                            const cl_image_desc* image_desc, void* host_ptr,
372                            cl_int* errcode_ret) {
373   if (clCreateImage) {  // clCreateImage available since OpenCL 1.2
374     return clCreateImage(context, flags, image_format, image_desc, host_ptr,
375                          errcode_ret);
376   } else {
377     return clCreateImage3D(context, flags, image_format,
378                            image_desc->image_width, image_desc->image_height,
379                            image_desc->image_depth, image_desc->image_row_pitch,
380                            image_desc->image_slice_pitch, host_ptr,
381                            errcode_ret);
382   }
383 }
384 }  // namespace cl
385 }  // namespace gpu
386 }  // namespace tflite
387