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