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