xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/delegates/gpu/cl/opencl_wrapper.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
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