1 /*
2 This file is part of darktable,
3 Copyright (C) 2011-2020 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #ifdef HAVE_OPENCL
20
21 #include "common/dlopencl.h"
22 #include "common/darktable.h"
23 #include "common/dynload.h"
24
25 #include <assert.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #if defined(WIN32)
32 static const char *ocllib[] = { "OpenCL.dll", NULL };
33 #elif defined(__APPLE__)
34 static const char *ocllib[] = { "/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL", NULL };
35 #else
36 static const char *ocllib[] = { "libOpenCL", "libOpenCL.so", "libOpenCL.so.1", NULL };
37 #endif
38
39
40 /* only for debugging: default noop function for all unassigned function pointers */
dt_dlopencl_noop(void)41 void dt_dlopencl_noop(void)
42 {
43 /* we should normally never get here */
44 fprintf(stderr, "dt_dlopencl internal error: unsupported function call\n");
45 raise(SIGABRT);
46 }
47
48
49 /* dynamically load OpenCL library and bind needed symbols */
dt_dlopencl_init(const char * name)50 dt_dlopencl_t *dt_dlopencl_init(const char *name)
51 {
52 dt_gmodule_t *module = NULL;
53 dt_dlopencl_t *ocl;
54 const char *library = NULL;
55 int success;
56
57 /* check if our platform supports gmodules */
58 success = dt_gmodule_supported();
59 if(!success) return NULL;
60
61 /* try to load library. if a name is given check only that library - else iterate over default names. */
62 if(name != NULL && name[0] != '\0')
63 {
64 library = name;
65 module = dt_gmodule_open(library);
66 if(module == NULL)
67 dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not find opencl runtime library '%s'\n", library);
68 else
69 dt_print(DT_DEBUG_OPENCL, "[opencl_init] found opencl runtime library '%s'\n", library);
70 }
71 else
72 {
73 const char **iter = ocllib;
74 while(*iter && (module == NULL))
75 {
76 library = *iter;
77 module = dt_gmodule_open(library);
78 if(module == NULL)
79 dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not find opencl runtime library '%s'\n", library);
80 else
81 dt_print(DT_DEBUG_OPENCL, "[opencl_init] found opencl runtime library '%s'\n", library);
82 iter++;
83 }
84 }
85
86 if(module == NULL)
87 return NULL;
88 else
89 {
90 /* now bind symbols */
91 success = TRUE;
92 ocl = (dt_dlopencl_t *)malloc(sizeof(dt_dlopencl_t));
93
94 if(ocl == NULL)
95 {
96 free(module);
97 return NULL;
98 }
99
100 ocl->symbols = (dt_dlopencl_symbols_t *)calloc(1, sizeof(dt_dlopencl_symbols_t));
101
102 if(ocl->symbols == NULL)
103 {
104 free(ocl);
105 free(module);
106 return NULL;
107 }
108
109 ocl->library = module->library;
110
111 /* assign noop function as a default to each function pointer */
112 void (**slist)(void) = (void (**)(void))ocl->symbols;
113 /* sanity check against padding */
114 if(sizeof(dt_dlopencl_symbols_t) % sizeof(void (*)(void)) == 0)
115 for(int k = 0; k < sizeof(dt_dlopencl_symbols_t) / sizeof(void (*)(void)); k++) slist[k] = dt_dlopencl_noop;
116
117 /* only bind needed symbols */
118 success = success && dt_gmodule_symbol(module, "clGetPlatformIDs",
119 (void (**)(void)) & ocl->symbols->dt_clGetPlatformIDs);
120 success = success && dt_gmodule_symbol(module, "clGetPlatformInfo",
121 (void (**)(void)) & ocl->symbols->dt_clGetPlatformInfo);
122 success = success && dt_gmodule_symbol(module, "clGetDeviceIDs",
123 (void (**)(void)) & ocl->symbols->dt_clGetDeviceIDs);
124 success = success && dt_gmodule_symbol(module, "clGetDeviceInfo",
125 (void (**)(void)) & ocl->symbols->dt_clGetDeviceInfo);
126 success = success && dt_gmodule_symbol(module, "clCreateContext",
127 (void (**)(void)) & ocl->symbols->dt_clCreateContext);
128 success = success && dt_gmodule_symbol(module, "clCreateCommandQueue",
129 (void (**)(void)) & ocl->symbols->dt_clCreateCommandQueue);
130 success = success && dt_gmodule_symbol(module, "clCreateProgramWithSource",
131 (void (**)(void)) & ocl->symbols->dt_clCreateProgramWithSource);
132 success = success && dt_gmodule_symbol(module, "clBuildProgram",
133 (void (**)(void)) & ocl->symbols->dt_clBuildProgram);
134 success = success && dt_gmodule_symbol(module, "clGetProgramBuildInfo",
135 (void (**)(void)) & ocl->symbols->dt_clGetProgramBuildInfo);
136 success = success && dt_gmodule_symbol(module, "clCreateKernel",
137 (void (**)(void)) & ocl->symbols->dt_clCreateKernel);
138 success = success && dt_gmodule_symbol(module, "clCreateBuffer",
139 (void (**)(void)) & ocl->symbols->dt_clCreateBuffer);
140 success = success && dt_gmodule_symbol(module, "clCreateImage2D",
141 (void (**)(void)) & ocl->symbols->dt_clCreateImage2D);
142 success = success && dt_gmodule_symbol(module, "clEnqueueWriteBuffer",
143 (void (**)(void)) & ocl->symbols->dt_clEnqueueWriteBuffer);
144 success = success && dt_gmodule_symbol(module, "clSetKernelArg",
145 (void (**)(void)) & ocl->symbols->dt_clSetKernelArg);
146 success = success && dt_gmodule_symbol(module, "clGetKernelWorkGroupInfo",
147 (void (**)(void)) & ocl->symbols->dt_clGetKernelWorkGroupInfo);
148 success = success && dt_gmodule_symbol(module, "clEnqueueNDRangeKernel",
149 (void (**)(void)) & ocl->symbols->dt_clEnqueueNDRangeKernel);
150 success = success && dt_gmodule_symbol(module, "clEnqueueReadImage",
151 (void (**)(void)) & ocl->symbols->dt_clEnqueueReadImage);
152 success = success && dt_gmodule_symbol(module, "clEnqueueWriteImage",
153 (void (**)(void)) & ocl->symbols->dt_clEnqueueWriteImage);
154 success = success && dt_gmodule_symbol(module, "clEnqueueCopyImage",
155 (void (**)(void)) & ocl->symbols->dt_clEnqueueCopyImage);
156 success = success && dt_gmodule_symbol(module, "clEnqueueCopyImageToBuffer",
157 (void (**)(void)) & ocl->symbols->dt_clEnqueueCopyImageToBuffer);
158 success = success && dt_gmodule_symbol(module, "clEnqueueCopyBufferToImage",
159 (void (**)(void)) & ocl->symbols->dt_clEnqueueCopyBufferToImage);
160 success = success && dt_gmodule_symbol(module, "clFinish", (void (**)(void)) & ocl->symbols->dt_clFinish);
161 success = success && dt_gmodule_symbol(module, "clEnqueueReadBuffer",
162 (void (**)(void)) & ocl->symbols->dt_clEnqueueReadBuffer);
163 success = success && dt_gmodule_symbol(module, "clReleaseMemObject",
164 (void (**)(void)) & ocl->symbols->dt_clReleaseMemObject);
165 success = success && dt_gmodule_symbol(module, "clReleaseProgram",
166 (void (**)(void)) & ocl->symbols->dt_clReleaseProgram);
167 success = success && dt_gmodule_symbol(module, "clReleaseKernel",
168 (void (**)(void)) & ocl->symbols->dt_clReleaseKernel);
169 success = success && dt_gmodule_symbol(module, "clReleaseCommandQueue",
170 (void (**)(void)) & ocl->symbols->dt_clReleaseCommandQueue);
171 success = success && dt_gmodule_symbol(module, "clReleaseContext",
172 (void (**)(void)) & ocl->symbols->dt_clReleaseContext);
173 success = success && dt_gmodule_symbol(module, "clReleaseEvent",
174 (void (**)(void)) & ocl->symbols->dt_clReleaseEvent);
175 success = success && dt_gmodule_symbol(module, "clWaitForEvents",
176 (void (**)(void)) & ocl->symbols->dt_clWaitForEvents);
177 success = success && dt_gmodule_symbol(module, "clGetEventInfo",
178 (void (**)(void)) & ocl->symbols->dt_clGetEventInfo);
179 success = success && dt_gmodule_symbol(module, "clGetEventProfilingInfo",
180 (void (**)(void)) & ocl->symbols->dt_clGetEventProfilingInfo);
181 success = success && dt_gmodule_symbol(module, "clGetKernelInfo",
182 (void (**)(void)) & ocl->symbols->dt_clGetKernelInfo);
183 success = success && dt_gmodule_symbol(module, "clEnqueueBarrier",
184 (void (**)(void)) & ocl->symbols->dt_clEnqueueBarrier);
185 success = success && dt_gmodule_symbol(module, "clGetKernelWorkGroupInfo",
186 (void (**)(void)) & ocl->symbols->dt_clGetKernelWorkGroupInfo);
187 success = success && dt_gmodule_symbol(module, "clEnqueueReadBuffer",
188 (void (**)(void)) & ocl->symbols->dt_clEnqueueReadBuffer);
189 success = success && dt_gmodule_symbol(module, "clEnqueueWriteBuffer",
190 (void (**)(void)) & ocl->symbols->dt_clEnqueueWriteBuffer);
191 success = success && dt_gmodule_symbol(module, "clGetProgramInfo",
192 (void (**)(void)) & ocl->symbols->dt_clGetProgramInfo);
193 success = success && dt_gmodule_symbol(module, "clCreateProgramWithBinary",
194 (void (**)(void)) & ocl->symbols->dt_clCreateProgramWithBinary);
195 success = success && dt_gmodule_symbol(module, "clEnqueueCopyBuffer",
196 (void (**)(void)) & ocl->symbols->dt_clEnqueueCopyBuffer);
197 success = success && dt_gmodule_symbol(module, "clEnqueueMapBuffer",
198 (void (**)(void)) & ocl->symbols->dt_clEnqueueMapBuffer);
199 success = success && dt_gmodule_symbol(module, "clEnqueueUnmapMemObject",
200 (void (**)(void)) & ocl->symbols->dt_clEnqueueUnmapMemObject);
201 success = success && dt_gmodule_symbol(module, "clGetMemObjectInfo",
202 (void (**)(void)) & ocl->symbols->dt_clGetMemObjectInfo);
203 success = success && dt_gmodule_symbol(module, "clGetImageInfo",
204 ((void (**)(void)) & ocl->symbols->dt_clGetImageInfo));
205
206 ocl->have_opencl = success;
207
208 if(!success)
209 dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not load all required symbols from library\n");
210 }
211
212 free(module);
213
214 if(!success)
215 {
216 free(ocl->symbols);
217 free(ocl);
218 return NULL;
219 }
220
221 return ocl;
222 }
223
224 #endif
225
226 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
227 // vim: shiftwidth=2 expandtab tabstop=2 cindent
228 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
229