Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
opencl.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2012, 2016 johannes hanika.
4 Copyright (C) 2011 Bruce Guenter.
5 Copyright (C) 2011 Henrik Andersson.
6 Copyright (C) 2011 Moritz Lipp.
7 Copyright (C) 2011-2019 Ulrich Pegelow.
8 Copyright (C) 2012 Christian Tellefsen.
9 Copyright (C) 2012 Jérémy Rosen.
10 Copyright (C) 2012 Michal Babej.
11 Copyright (C) 2012 Richard Wonka.
12 Copyright (C) 2012-2014, 2016-2018 Tobias Ellinghaus.
13 Copyright (C) 2013-2019 Roman Lebedev.
14 Copyright (C) 2013 Simon Spannagel.
15 Copyright (C) 2015, 2019 Dan Torop.
16 Copyright (C) 2015, 2017 parafin.
17 Copyright (C) 2015 Pascal de Bruijn.
18 Copyright (C) 2016-2017, 2019 Peter Budai.
19 Copyright (C) 2017-2019 Edgardo Hoszowski.
20 Copyright (C) 2017, 2019 luzpaz.
21 Copyright (C) 2019 Andreas Schneider.
22 Copyright (C) 2019, 2021-2022, 2025-2026 Aurélien PIERRE.
23 Copyright (C) 2019 Damian D. Martinez Dreyer.
24 Copyright (C) 2019-2020 Heiko Bauke.
25 Copyright (C) 2019 jakubfi.
26 Copyright (C) 2019-2021 Pascal Obry.
27 Copyright (C) 2020 David-Tillmann Schaefer.
28 Copyright (C) 2020-2022 Hubert Kowalski.
29 Copyright (C) 2020-2021 Ralf Brown.
30 Copyright (C) 2021 Chris Elston.
31 Copyright (C) 2022 Hanno Schwalm.
32 Copyright (C) 2022 Martin Bařinka.
33 Copyright (C) 2022 Victor Forsiuk.
34 Copyright (C) 2024 Alynx Zhou.
35 Copyright (C) 2025 Guillaume Stutin.
36
37 darktable is free software: you can redistribute it and/or modify
38 it under the terms of the GNU General Public License as published by
39 the Free Software Foundation, either version 3 of the License, or
40 (at your option) any later version.
41
42 darktable is distributed in the hope that it will be useful,
43 but WITHOUT ANY WARRANTY; without even the implied warranty of
44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
46
47 You should have received a copy of the GNU General Public License
48 along with darktable. If not, see <http://www.gnu.org/licenses/>.
49*/
50
51#ifdef HAVE_OPENCL
52
53#include "common/opencl.h"
54#include "common/bilateralcl.h"
55#include "common/darktable.h"
56#include "common/dlopencl.h"
57#include "common/dwt.h"
59#include "common/gaussian.h"
61#include "common/heal.h"
64#include "common/nvidia_gpus.h"
66#include "common/tea.h"
67#include "control/conf.h"
68#include "control/control.h"
69#include "gui/splash.h"
70#include "develop/blend.h"
71#include "develop/pixelpipe.h"
73
74#include <assert.h>
75#include <locale.h>
76#include <stdio.h>
77#include <string.h>
78#include <strings.h>
79
80#include <ctype.h>
81#include <errno.h>
82#include <libgen.h>
83#include <sys/stat.h>
84#include <zlib.h>
85
86static gboolean _opencl_splash_active = FALSE;
87
88static inline void _opencl_splash_update_compile(const char *programname)
89{
90 if(IS_NULL_PTR(programname)) return;
91 if(IS_NULL_PTR(darktable.gui)) return;
92
94 {
97 }
98
99 dt_gui_splash_updatef(_("Building OpenCL kernels: %s"), programname);
100}
101
102static const char *dt_opencl_get_vendor_by_id(unsigned int id);
103static char *_ascii_str_canonical(const char *in, char *out, int maxlen);
105static void dt_opencl_priority_parse(dt_opencl_t *cl, char *configstr, int *priority_list, int *mandatory);
107static void dt_opencl_update_priorities();
112
113
114int dt_opencl_get_device_info(dt_opencl_t *cl, cl_device_id device, cl_device_info param_name, void **param_value,
115 size_t *param_value_size)
116{
117 *param_value_size = SIZE_MAX;
118
119 // 1. figure out how much memory is needed
120 cl_int err = (cl->dlocl->symbols->dt_clGetDeviceInfo)(device, param_name, 0, NULL, param_value_size);
121 if(err != CL_SUCCESS)
122 {
124 "[dt_opencl_get_device_info] could not query the actual size in bytes of info %d: %i\n", param_name, err);
125 goto error;
126 }
127
128 // 2. did we /actually/ get the size?
129 if(*param_value_size == SIZE_MAX || *param_value_size == 0)
130 {
131 // both of these sizes make no sense. either i failed to parse spec, or opencl implementation bug?
133 "[dt_opencl_get_device_info] ERROR: no size returned, or zero size returned for data %d: %" G_GSIZE_FORMAT "\n",
134 param_name, *param_value_size);
135 err = CL_INVALID_VALUE; // FIXME: anything better?
136 goto error;
137 }
138
139 // 3. make sure that *param_value points to big-enough memory block
140 {
141 void *ptr = realloc(*param_value, *param_value_size);
142 if(IS_NULL_PTR(ptr))
143 {
145 "[dt_opencl_get_device_info] memory allocation failed! tried to allocate %" G_GSIZE_FORMAT " bytes for data %d: %i",
146 *param_value_size, param_name, err);
147 err = CL_OUT_OF_HOST_MEMORY;
148 goto error;
149 }
150
151 // allocation succeeded, update pointer.
152 *param_value = ptr;
153 }
154
155 // 4. actually get the value
156 err = (cl->dlocl->symbols->dt_clGetDeviceInfo)(device, param_name, *param_value_size, *param_value, NULL);
157 if(err != CL_SUCCESS)
158 {
159 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_get_device_info] could not query info %d: %i\n", param_name, err);
160 goto error;
161 }
162
163 return CL_SUCCESS;
164
165error:
166 dt_free(*param_value);
167 *param_value_size = 0;
168 return err;
169}
170
171int dt_opencl_avoid_atomics(const int devid)
172{
174 return (!cl->inited || devid < 0) ? 0 : cl->dev[devid].avoid_atomics;
175}
176
177int dt_opencl_micro_nap(const int devid)
178{
180 return (!cl->inited || devid < 0) ? 0 : cl->dev[devid].micro_nap;
181}
182
183gboolean dt_opencl_use_pinned_memory(const int devid)
184{
186 if(!cl->inited || devid < 0) return FALSE;
187 return cl->dev[devid].pinned_memory & DT_OPENCL_PINNING_ON;
188}
189
190gboolean dt_opencl_is_pinned_memory(cl_mem mem)
191{
192 const cl_mem_flags flags = dt_opencl_get_mem_flags(mem);
193 return (flags & CL_MEM_USE_HOST_PTR) || (flags & CL_MEM_ALLOC_HOST_PTR);
194}
195
196void dt_opencl_write_device_config(const int devid)
197{
198 if(devid < 0) return;
200 gchar buf[256] = { 0 };
201 gchar key_device[256] = { 0 };
202 g_snprintf(key_device, 254, "%s/%i/%s", DT_CLDEVICE_HEAD, devid, cl->dev[devid].cname);
203
204 g_snprintf(buf, sizeof(buf), "%s/avoid_atomics", key_device);
205 dt_conf_set_int(buf, cl->dev[devid].avoid_atomics);
206
207 g_snprintf(buf, sizeof(buf), "%s/micro_nap", key_device);
208 dt_conf_set_int(buf, cl->dev[devid].micro_nap);
209
210 g_snprintf(buf, sizeof(buf), "%s/pinned_memory", key_device);
212
213 g_snprintf(buf, sizeof(buf), "%s/wd", key_device);
214 dt_conf_set_int(buf, cl->dev[devid].clroundup_wd);
215
216 g_snprintf(buf, sizeof(buf), "%s/ht", key_device);
217 dt_conf_set_int(buf, cl->dev[devid].clroundup_ht);
218
219 g_snprintf(buf, sizeof(buf), "%s/event_handles", key_device);
220 dt_conf_set_int(buf, cl->dev[devid].event_handles);
221
222 g_snprintf(buf, sizeof(buf), "%s/disabled", key_device);
223 dt_conf_set_int(buf, cl->dev[devid].disabled & 1);
224
225 g_snprintf(buf, sizeof(buf), "%s/id%i/forced_headroom", key_device, devid);
226 dt_conf_set_int(buf, cl->dev[devid].forced_headroom);
227}
228
229static int _dt_opencl_get_conf_int(const gchar *key_device, const gchar *conf_name, gboolean *safety_ok)
230{
231 int res = 0;
232 gchar *key = g_strconcat(key_device, "/", conf_name, NULL);
233 const gboolean existing_device = dt_conf_key_not_empty(key);
234 if(existing_device)
235 res = dt_conf_get_int(key);
236 else
237 {
238 dt_print(DT_DEBUG_OPENCL, "Warning: conf '%s' not found in anselrc.\n", key);
239 *safety_ok = FALSE;
240 }
241
242 dt_free(key);
243 return res;
244}
245
246gboolean dt_opencl_read_device_config(const int devid)
247{
248 if(devid < 0) return FALSE;
250 gchar key_device[256] = { 0 };
251 g_snprintf(key_device, 254, "%s/%i/%s", DT_CLDEVICE_HEAD, devid, cl->dev[devid].cname);
252 gboolean safety_ok = TRUE;
253
254 int avoid_atomics = _dt_opencl_get_conf_int(key_device, "avoid_atomics", &safety_ok);
255 int micro_nap = _dt_opencl_get_conf_int(key_device, "micro_nap", &safety_ok);
256 int pinned_memory = _dt_opencl_get_conf_int(key_device, "pinned_memory", &safety_ok);
257 int wd = _dt_opencl_get_conf_int(key_device, "wd", &safety_ok);
258 int ht = _dt_opencl_get_conf_int(key_device, "ht", &safety_ok);
259 int event_handles = _dt_opencl_get_conf_int(key_device, "event_handles", &safety_ok);
260 int disabled = _dt_opencl_get_conf_int(key_device, "disabled", &safety_ok);
261
262 // some rudimentary safety checking if string seems to be ok
263 safety_ok |= (wd > 1) && (wd < 513) && (ht > 1) && (ht < 513);
264
265 if(safety_ok)
266 {
267 cl->dev[devid].avoid_atomics = avoid_atomics;
268 cl->dev[devid].micro_nap = micro_nap;
269 cl->dev[devid].pinned_memory = pinned_memory;
270 cl->dev[devid].clroundup_wd = wd;
271 cl->dev[devid].clroundup_ht = ht;
272 cl->dev[devid].event_handles = event_handles;
273 cl->dev[devid].disabled = disabled;
274 }
275 else // if there is something wrong with the found conf key reset to defaults
276 {
277 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_read_device_config] malformed data '%s'\n", key_device);
278 }
279
280 // do some safety housekeeping
281 cl->dev[devid].avoid_atomics &= 1;
283 cl->dev[devid].micro_nap = CLAMP(cl->dev[devid].micro_nap, 250, 1000000);
284 if((cl->dev[devid].clroundup_wd < 2) || (cl->dev[devid].clroundup_wd > 512))
285 cl->dev[devid].clroundup_wd = 16;
286 if((cl->dev[devid].clroundup_ht < 2) || (cl->dev[devid].clroundup_ht > 512))
287 cl->dev[devid].clroundup_ht = 16;
288 if(cl->dev[devid].event_handles < 0)
289 cl->dev[devid].event_handles = 0x40961440;
290
291 cl->dev[devid].use_events = (cl->dev[devid].event_handles != 0) ? 1 : 0;
292 cl->dev[devid].disabled &= 1;
293
294 // Also take care of extended device data, these are not only device specific but also depend on the devid
295 g_snprintf(key_device, 254, "%s/%i/%s/id%i/forced_headroom", DT_CLDEVICE_HEAD, devid, cl->dev[devid].cname, devid);
296 if(dt_conf_key_not_empty(key_device))
297 {
298 int forced_headroom = dt_conf_get_int(key_device);
299 if(forced_headroom > 0) cl->dev[devid].forced_headroom = forced_headroom;
300 }
301 else if(cl->dev[devid].host_unified_memory)
302 cl->dev[devid].forced_headroom = MAX(512ul, (size_t)dt_conf_get_int64("memory_opencl_headroom"));
303 else // this is used if updating to 4.0 or fresh installs; see commenting _opencl_get_unused_device_mem()
304 cl->dev[devid].forced_headroom = dt_conf_get_int64("memory_opencl_headroom");
305
307 return !safety_ok;
308}
309
311{
313 if(IS_NULL_PTR(cl)) return 0;
314
315 return cl->num_detected_devs;
316}
317
319{
321 if(IS_NULL_PTR(cl) || detected < 0 || detected >= cl->num_detected_devs) return NULL;
322
323 return cl->detected_devs + detected;
324}
325
326gboolean dt_opencl_detected_device_enabled(const int detected)
327{
329 if(IS_NULL_PTR(device)) return FALSE;
330
331 gchar key[256] = { 0 };
332 g_snprintf(key, sizeof(key), "%s/%d/%s/disabled", DT_CLDEVICE_HEAD, device->config_id,
333 !IS_NULL_PTR(device->cname) ? device->cname : "");
334 const gboolean disabled = dt_conf_key_not_empty(key) ? dt_conf_get_int(key) : (device->disabled & 1);
335
336 return !disabled;
337}
338
339int dt_opencl_set_detected_device_enabled(const int detected, const gboolean enabled)
340{
342 if(IS_NULL_PTR(device)) return -1;
343
344 gchar key[256] = { 0 };
345 g_snprintf(key, sizeof(key), "%s/%d/%s/disabled", DT_CLDEVICE_HEAD, device->config_id,
346 !IS_NULL_PTR(device->cname) ? device->cname : "");
347 dt_conf_set_int(key, enabled ? 0 : 1);
348
350 cl->detected_devs[detected].disabled = enabled ? 0 : 1;
351
352 gboolean opencl_enabled = enabled;
353 if(!opencl_enabled)
354 {
355 // The global OpenCL preference is derived from all detected GPUs. We are looking
356 // for any GPU still enabled before turning OpenCL off globally.
357 for(int dev = 0; dev < cl->num_detected_devs; dev++)
358 {
360 {
361 opencl_enabled = TRUE;
362 break;
363 }
364 }
365 }
366
367 dt_conf_set_bool("opencl", opencl_enabled);
368 return 0;
369}
370
371gboolean dt_opencl_detected_device_pinned_memory(const int detected)
372{
374 if(IS_NULL_PTR(device)) return FALSE;
375
376 gchar key[256] = { 0 };
377 g_snprintf(key, sizeof(key), "%s/%d/%s/pinned_memory", DT_CLDEVICE_HEAD, device->config_id,
378 !IS_NULL_PTR(device->cname) ? device->cname : "");
379 const int pinned_memory = dt_conf_key_not_empty(key) ? dt_conf_get_int(key) : device->pinned_memory;
380
381 return pinned_memory & DT_OPENCL_PINNING_ON;
382}
383
384int dt_opencl_set_detected_device_pinned_memory(const int detected, const gboolean enabled)
385{
387 if(IS_NULL_PTR(device)) return -1;
388
389 gchar key[256] = { 0 };
390 const int pinned_memory = enabled ? DT_OPENCL_PINNING_ON : DT_OPENCL_PINNING_OFF;
391 g_snprintf(key, sizeof(key), "%s/%d/%s/pinned_memory", DT_CLDEVICE_HEAD, device->config_id,
392 !IS_NULL_PTR(device->cname) ? device->cname : "");
393 dt_conf_set_int(key, pinned_memory);
394
396 cl->detected_devs[detected].pinned_memory = pinned_memory;
397 // device->config_id is this device's live index into cl->dev[] (assigned at detection time,
398 // see dt_opencl_device_init()) -- apply immediately instead of only on the next restart, since
399 // dt_opencl_use_pinned_memory() reads cl->dev[], never cl->detected_devs[].
400 if(device->config_id >= 0 && device->config_id < cl->num_devs)
401 cl->dev[device->config_id].pinned_memory = pinned_memory;
402 return 0;
403}
404
405size_t dt_opencl_detected_device_headroom(const int detected)
406{
408 if(IS_NULL_PTR(device)) return 0;
409
410 gchar key[256] = { 0 };
411 g_snprintf(key, sizeof(key), "%s/%d/%s/id%d/forced_headroom", DT_CLDEVICE_HEAD, device->config_id,
412 !IS_NULL_PTR(device->cname) ? device->cname : "", device->config_id);
413
414 return dt_conf_key_not_empty(key) ? (size_t)dt_conf_get_int(key) : device->forced_headroom;
415}
416
417int dt_opencl_set_detected_device_headroom(const int detected, const size_t headroom)
418{
420 if(IS_NULL_PTR(device)) return -1;
421
422 gchar key[256] = { 0 };
423 g_snprintf(key, sizeof(key), "%s/%d/%s/id%d/forced_headroom", DT_CLDEVICE_HEAD, device->config_id,
424 !IS_NULL_PTR(device->cname) ? device->cname : "", device->config_id);
425 const int clamped_headroom = (int)MIN(headroom, (size_t)G_MAXINT);
426 dt_conf_set_int(key, clamped_headroom);
427
429 cl->detected_devs[detected].forced_headroom = clamped_headroom;
430 // Same live-apply as pinned memory above: device->config_id is this device's index into
431 // cl->dev[], which dt_opencl_get_device_available() actually reads through used_available.
432 // dt_opencl_check_tuning() recomputes that from the value we just wrote, so the new headroom
433 // is in effect before this function returns instead of only after a restart.
434 if(device->config_id >= 0 && device->config_id < cl->num_devs)
435 {
436 cl->dev[device->config_id].forced_headroom = clamped_headroom;
438 }
439 return 0;
440}
441
442// returns 0 if all ok or an error if we failed to init this device
443static int dt_opencl_device_init(dt_opencl_t *cl, const int dev, cl_device_id *devices, const int k)
444{
445 int res;
446 cl_int err;
447 gboolean lock_initialized = FALSE;
448
449 memset(cl->dev[dev].program, 0x0, sizeof(cl_program) * DT_OPENCL_MAX_PROGRAMS);
450 memset(cl->dev[dev].program_used, 0x0, sizeof(int) * DT_OPENCL_MAX_PROGRAMS);
451 memset(cl->dev[dev].kernel, 0x0, sizeof(cl_kernel) * DT_OPENCL_MAX_KERNELS);
452 memset(cl->dev[dev].kernel_used, 0x0, sizeof(int) * DT_OPENCL_MAX_KERNELS);
453 cl->dev[dev].context = NULL;
454 cl->dev[dev].cmd_queue = NULL;
455 cl->dev[dev].eventlist = NULL;
456 cl->dev[dev].eventtags = NULL;
457 cl->dev[dev].numevents = 0;
458 cl->dev[dev].eventsconsolidated = 0;
459 cl->dev[dev].maxevents = 0;
460 cl->dev[dev].maxeventslot = 0;
461 cl->dev[dev].lostevents = 0;
462 cl->dev[dev].totalevents = 0;
463 cl->dev[dev].totalsuccess = 0;
464 cl->dev[dev].totallost = 0;
465 cl->dev[dev].summary = CL_COMPLETE;
466 cl->dev[dev].used_global_mem = 0;
467 cl->dev[dev].nvidia_sm_20 = 0;
468 cl->dev[dev].vendor = NULL;
469 cl->dev[dev].name = NULL;
470 cl->dev[dev].cname = NULL;
471 cl->dev[dev].options = NULL;
472 cl->dev[dev].options_md5 = NULL;
473 cl->dev[dev].memory_in_use = 0;
474 cl->dev[dev].peak_memory = 0;
475 cl->dev[dev].used_available = 0;
476 // setting sane/conservative defaults at first
477 cl->dev[dev].avoid_atomics = 0;
478 cl->dev[dev].micro_nap = 250;
480 cl->dev[dev].clroundup_wd = 16;
481 cl->dev[dev].clroundup_ht = 16;
482 cl->dev[dev].use_events = 1;
483 cl->dev[dev].event_handles = 128;
484 cl->dev[dev].disabled = 0;
485 cl->dev[dev].forced_headroom = 0;
486 cl->dev[dev].runtime_error = 0;
487 cl_device_id devid = cl->dev[dev].devid = devices[k];
488
489 char *infostr = NULL;
490 size_t infostr_size;
491
492 char *cname = NULL;
493 size_t cname_size;
494
495 char *vendor = NULL;
496 size_t vendor_size;
497
498 char *driverversion = NULL;
499 size_t driverversion_size;
500
501 char *deviceversion = NULL;
502 size_t deviceversion_size;
503
504 size_t infoint;
505 size_t *infointtab = NULL;
506 cl_device_type type;
507 cl_bool image_support = 0;
508 cl_bool device_available = 0;
509 cl_uint vendor_id = 0;
510 cl_bool little_endian = 0;
511 cl_platform_id platform_id = 0;
512
513 char *dtcache = calloc(PATH_MAX, sizeof(char));
514 char *cachedir = calloc(PATH_MAX, sizeof(char));
515 char *devname = calloc(DT_OPENCL_CBUFFSIZE, sizeof(char));
516 char *drvversion = calloc(DT_OPENCL_CBUFFSIZE, sizeof(char));
517 char *platform_name = calloc(DT_OPENCL_CBUFFSIZE, sizeof(char));
518 char *platform_vendor = calloc(DT_OPENCL_CBUFFSIZE, sizeof(char));
519
520 char kerneldir[PATH_MAX] = { 0 };
521 char *filename = calloc(PATH_MAX, sizeof(char));
522 char *confentry = calloc(PATH_MAX, sizeof(char));
523 char *binname = calloc(PATH_MAX, sizeof(char));
524 dt_print_nts(DT_DEBUG_OPENCL, "\n[dt_opencl_device_init]\n");
525
526 // test GPU availability, vendor, memory, image support etc:
527 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_AVAILABLE, sizeof(cl_bool), &device_available, NULL);
528
529 // Queried early (before dt_opencl_read_device_config() below, which needs it to pick a sane
530 // default headroom on first run) rather than alongside the other capability queries further down.
531 cl_bool host_unified_memory = CL_FALSE;
532 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(cl_bool),
533 &host_unified_memory, NULL);
534 cl->dev[dev].host_unified_memory = (host_unified_memory == CL_TRUE);
535
536 err = dt_opencl_get_device_info(cl, devid, CL_DEVICE_VENDOR, (void **)&vendor, &vendor_size);
537 if(err != CL_SUCCESS)
538 {
539 dt_print_nts(DT_DEBUG_OPENCL, " *** could not get vendor name of device %d: %i\n", k, err);
540 res = -1;
541 goto end;
542 }
543
544 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_VENDOR_ID, sizeof(cl_uint), &vendor_id, NULL);
545
546 err = dt_opencl_get_device_info(cl, devid, CL_DEVICE_NAME, (void **)&infostr, &infostr_size);
547 if(err != CL_SUCCESS)
548 {
549 dt_print_nts(DT_DEBUG_OPENCL, " *** could not get device name of device %d: %i\n", k, err);
550 res = -1;
551 goto end;
552 }
553
554 // get the canonical device name
555 cname_size = infostr_size;
556 cname = malloc(cname_size);
557 _ascii_str_canonical(infostr, cname, cname_size);
558 cl->dev[dev].name = strdup(infostr);
559 cl->dev[dev].cname = strdup(cname);
560
561 // take every detected device into account of checksum
562 cl->crc = crc32(cl->crc, (const unsigned char *)infostr, strlen(infostr));
563
564 err = (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_PLATFORM, sizeof(cl_platform_id), &platform_id, NULL);
565 if(err != CL_SUCCESS)
566 {
567 g_strlcpy(platform_vendor, "no platform id", DT_OPENCL_CBUFFSIZE);
568 g_strlcpy(platform_name, "no platform id", DT_OPENCL_CBUFFSIZE);
569 dt_print_nts(DT_DEBUG_OPENCL, " *** could not get platform id for device `%s' : %i\n", cl->dev[dev].name, err);
570 }
571 else
572 {
573 err = (cl->dlocl->symbols->dt_clGetPlatformInfo)(platform_id, CL_PLATFORM_NAME, DT_OPENCL_CBUFFSIZE, platform_name, NULL);
574 if(err != CL_SUCCESS)
575 {
576 dt_print_nts(DT_DEBUG_OPENCL, " *** could not get platform name for device `%s' : %i\n", cl->dev[dev].name, err);
577 g_strlcpy(platform_name, "???", DT_OPENCL_CBUFFSIZE);
578 }
579
580 err = (cl->dlocl->symbols->dt_clGetPlatformInfo)(platform_id, CL_PLATFORM_VENDOR, DT_OPENCL_CBUFFSIZE, platform_vendor, NULL);
581 if(err != CL_SUCCESS)
582 {
583 dt_print_nts(DT_DEBUG_OPENCL, " *** could not get platform vendor for device `%s' : %i\n", cl->dev[dev].name, err);
584 g_strlcpy(platform_vendor, "???", DT_OPENCL_CBUFFSIZE);
585 }
586 }
587
588 const gboolean newdevice = dt_opencl_read_device_config(dev);
589 dt_print_nts(DT_DEBUG_OPENCL, " DEVICE: %d: '%s'%s\n", k, infostr, (newdevice) ? ", NEW" : "" );
590 dt_print_nts(DT_DEBUG_OPENCL, " CANONICAL NAME: %s\n", cname);
591 dt_print_nts(DT_DEBUG_OPENCL, " PLATFORM NAME & VENDOR: %s, %s\n", platform_name, platform_vendor);
592
593 err = dt_opencl_get_device_info(cl, devid, CL_DRIVER_VERSION, (void **)&driverversion, &driverversion_size);
594 if(err != CL_SUCCESS)
595 {
596 dt_print_nts(DT_DEBUG_OPENCL, " *** driver version not available *** %i\n", err);
597 res = -1;
598 cl->dev[dev].disabled |= 1;
599 goto end;
600 }
601
602 err = dt_opencl_get_device_info(cl, devid, CL_DEVICE_VERSION, (void **)&deviceversion, &deviceversion_size);
603 if(err != CL_SUCCESS)
604 {
605 dt_print_nts(DT_DEBUG_OPENCL, " *** device version not available *** %i\n", err);
606 res = -1;
607 cl->dev[dev].disabled |= 1;
608 goto end;
609 }
610
611 // take every detected device driver into account of checksum
612 cl->crc = crc32(cl->crc, (const unsigned char *)deviceversion, deviceversion_size);
613
614 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL);
615 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &image_support, NULL);
616 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t),
617 &(cl->dev[dev].max_image_height), NULL);
618 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t),
619 &(cl->dev[dev].max_image_width), NULL);
620 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong),
621 &(cl->dev[dev].max_mem_alloc), NULL);
622 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_ENDIAN_LITTLE, sizeof(cl_bool), &little_endian, NULL);
623
624 cl->dev[dev].cltype = (unsigned int)type;
625
626
627 if(!strncasecmp(vendor, "NVIDIA", 6))
628 {
629 // very lame attempt to detect support for atomic float add in global memory.
630 // we need compute model sm_20, but let's try for all nvidia devices :(
632 }
633
634 const gboolean is_cpu_device = (type & CL_DEVICE_TYPE_CPU) == CL_DEVICE_TYPE_CPU;
635
636 // micro_nap can be made less conservative on current systems at least if not on-CPU
637 if(newdevice)
638 cl->dev[dev].micro_nap = (is_cpu_device) ? 1000 : 250;
639
640 dt_print_nts(DT_DEBUG_OPENCL, " DRIVER VERSION: %s\n", driverversion);
641 dt_print_nts(DT_DEBUG_OPENCL, " DEVICE VERSION: %s%s\n", deviceversion,
642 cl->dev[dev].nvidia_sm_20 ? ", SM_20 SUPPORT" : "");
643 dt_print_nts(DT_DEBUG_OPENCL, " DEVICE_TYPE: %s%s%s\n",
644 ((type & CL_DEVICE_TYPE_CPU) == CL_DEVICE_TYPE_CPU) ? "CPU" : "",
645 ((type & CL_DEVICE_TYPE_GPU) == CL_DEVICE_TYPE_GPU) ? "GPU" : "",
646 (type & CL_DEVICE_TYPE_ACCELERATOR) ? ", Accelerator" : "" );
647
648 if(is_cpu_device && newdevice)
649 {
650 dt_print_nts(DT_DEBUG_OPENCL, " *** discarding new device as emulated by CPU ***\n");
651 cl->dev[dev].disabled |= 1;
652 res = -1;
653 goto end;
654 }
655
656 if(!device_available)
657 {
658 dt_print_nts(DT_DEBUG_OPENCL, " *** device is not available ***\n");
659 res = -1;
660 goto end;
661 }
662
663 if(!image_support)
664 {
665 dt_print_nts(DT_DEBUG_OPENCL, " *** The OpenCL driver doesn't provide image support. See also 'clinfo' output ***\n");
666 res = -1;
667 cl->dev[dev].disabled |= 1;
668 goto end;
669 }
670
671 if(!little_endian)
672 {
673 dt_print_nts(DT_DEBUG_OPENCL, " *** device is not little endian ***\n");
674 res = -1;
675 cl->dev[dev].disabled |= 1;
676 goto end;
677 }
678
679 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong),
680 &(cl->dev[dev].max_global_mem), NULL);
681 if(cl->dev[dev].max_global_mem < (uint64_t)512ul * 1024ul * 1024ul)
682 {
683 dt_print_nts(DT_DEBUG_OPENCL, " *** insufficient global memory (%" PRIu64 "MB) ***\n",
684 cl->dev[dev].max_global_mem / 1024 / 1024);
685 res = -1;
686 cl->dev[dev].disabled |= 1;
687 goto end;
688 }
689
690 cl->dev[dev].vendor = strdup(dt_opencl_get_vendor_by_id(vendor_id));
691
692 const gboolean is_blacklisted = dt_opencl_check_driver_blacklist(deviceversion);
693
694 // disable device for now if this is the first time detected and blacklisted too.
695 if(newdevice && is_blacklisted)
696 {
697 // To keep installations we look for the old blacklist conf key
698 const gboolean old_blacklist = dt_conf_get_bool("opencl_disable_drivers_blacklist");
699 cl->dev[dev].disabled |= (old_blacklist) ? 0 : 1;
700 if(cl->dev[dev].disabled)
701 dt_print_nts(DT_DEBUG_OPENCL, " *** new device is blacklisted ***\n");
702 res = -1;
703 goto end;
704 }
705
706 dt_print_nts(DT_DEBUG_OPENCL, " GLOBAL MEM SIZE: %.0f MB\n", (double)cl->dev[dev].max_global_mem / 1024.0 / 1024.0);
707 dt_print_nts(DT_DEBUG_OPENCL, " MAX MEM ALLOC: %.0f MB\n", (double)cl->dev[dev].max_mem_alloc / 1024.0 / 1024.0);
708 dt_print_nts(DT_DEBUG_OPENCL, " MAX IMAGE SIZE: %" G_GSIZE_FORMAT " x %" G_GSIZE_FORMAT "\n", cl->dev[dev].max_image_width, cl->dev[dev].max_image_height);
709 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(infoint), &infoint, NULL);
710 dt_print_nts(DT_DEBUG_OPENCL, " MAX WORK GROUP SIZE: %" G_GSIZE_FORMAT "\n", infoint);
711 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(infoint), &infoint, NULL);
712 dt_print_nts(DT_DEBUG_OPENCL, " MAX WORK ITEM DIMENSIONS: %" G_GSIZE_FORMAT "\n", infoint);
713
714 size_t infointtab_size;
715 err = dt_opencl_get_device_info(cl, devid, CL_DEVICE_MAX_WORK_ITEM_SIZES, (void **)&infointtab, &infointtab_size);
716 if(err == CL_SUCCESS)
717 {
718 dt_print_nts(DT_DEBUG_OPENCL, " MAX WORK ITEM SIZES: [ ");
719 for(size_t i = 0; i < infoint; i++) dt_print_nts(DT_DEBUG_OPENCL, "%" G_GSIZE_FORMAT " ", infointtab[i]);
720 dt_free(infointtab);
722 }
723 else
724 {
725 dt_print_nts(DT_DEBUG_OPENCL, " *** could not get maximum work item sizes ***\n");
726 res = -1;
727 cl->dev[dev].disabled |= 1;
728 goto end;
729 }
730
731 const gboolean pinning = (cl->dev[dev].pinned_memory & DT_OPENCL_PINNING_ON);
732 dt_print_nts(DT_DEBUG_OPENCL, " PINNED MEMORY TRANSFER: %s\n", pinning ? "WANTED" : "NO");
733 dt_print_nts(DT_DEBUG_OPENCL, " FORCED HEADROOM: %" G_GSIZE_FORMAT "\n", cl->dev[dev].forced_headroom);
734 dt_print_nts(DT_DEBUG_OPENCL, " AVOID ATOMICS: %s\n", (cl->dev[dev].avoid_atomics) ? "YES" : "NO");
735 dt_print_nts(DT_DEBUG_OPENCL, " MICRO NAP: %i\n", cl->dev[dev].micro_nap);
736 dt_print_nts(DT_DEBUG_OPENCL, " ROUNDUP WIDTH: %i\n", cl->dev[dev].clroundup_wd);
737 dt_print_nts(DT_DEBUG_OPENCL, " ROUNDUP HEIGHT: %i\n", cl->dev[dev].clroundup_ht);
738 dt_print_nts(DT_DEBUG_OPENCL, " CHECK EVENT HANDLES: %i\n", cl->dev[dev].event_handles);
739 dt_print_nts(DT_DEBUG_OPENCL, " DEFAULT DEVICE: %s\n", (type & CL_DEVICE_TYPE_DEFAULT) ? "YES" : "NO");
740
741 if(type & CL_DEVICE_TYPE_GPU)
742 {
743 dt_opencl_detected_device_t *detected_devs
744 = g_realloc(cl->detected_devs, sizeof(*cl->detected_devs) * (cl->num_detected_devs + 1));
745 if(!IS_NULL_PTR(detected_devs))
746 {
747 cl->detected_devs = detected_devs;
749 detected->config_id = dev;
750 detected->name = g_strdup(cl->dev[dev].name);
751 detected->cname = g_strdup(cl->dev[dev].cname);
752 detected->cltype = cl->dev[dev].cltype;
753 detected->disabled = cl->dev[dev].disabled & 1;
754 detected->pinned_memory = cl->dev[dev].pinned_memory;
755 detected->forced_headroom = cl->dev[dev].forced_headroom;
756 detected->host_unified_memory = cl->dev[dev].host_unified_memory;
757 cl->num_detected_devs++;
758 }
759 }
760
761 if(cl->dev[dev].disabled)
762 {
763 dt_print_nts(DT_DEBUG_OPENCL, " *** marked as disabled ***\n");
764 res = -1;
765 goto end;
766 }
767 dt_print_nts(DT_DEBUG_OPENCL, " *** Device enabled ***\n");
768
769 dt_pthread_mutex_init(&cl->dev[dev].lock, NULL);
770 lock_initialized = TRUE;
771
772 cl->dev[dev].context = (cl->dlocl->symbols->dt_clCreateContext)(0, 1, &devid, NULL, NULL, &err);
773 if(err != CL_SUCCESS)
774 {
775 dt_print_nts(DT_DEBUG_OPENCL, " *** could not create context *** %i\n", err);
776 res = -1;
777 goto end;
778 }
779 // create a command queue for first device the context reported
781 cl->dev[dev].context, devid, (darktable.unmuted & DT_DEBUG_PERF) ? CL_QUEUE_PROFILING_ENABLE : 0, &err);
782 if(err != CL_SUCCESS)
783 {
784 dt_print_nts(DT_DEBUG_OPENCL, " *** could not create command queue *** %i\n", err);
785 res = -1;
786 goto end;
787 }
788
789 dt_loc_get_kerneldir(kerneldir, sizeof(kerneldir));
790 dt_print_nts(DT_DEBUG_OPENCL, " KERNEL SOURCE DIRECTORY: %s\n", kerneldir);
791
792 double tstart, tend, tdiff;
793 dt_loc_get_user_cache_dir(dtcache, PATH_MAX * sizeof(char));
794
795 int len = MIN(strlen(infostr),1024 * sizeof(char));;
796 int j = 0;
797 // remove non-alphanumeric chars from device name
798 for(int i = 0; i < len; i++)
799 if(isalnum(infostr[i])) devname[j++] = infostr[i];
800 devname[j] = 0;
801 len = MIN(strlen(driverversion), 1024 * sizeof(char));
802 j = 0;
803 // remove non-alphanumeric chars from driver version
804 for(int i = 0; i < len; i++)
805 if(isalnum(driverversion[i])) drvversion[j++] = driverversion[i];
806 drvversion[j] = 0;
807 snprintf(cachedir, PATH_MAX * sizeof(char), "%s" G_DIR_SEPARATOR_S "cached_kernels_for_%s_%s", dtcache, devname, drvversion);
808
809 dt_print_nts(DT_DEBUG_OPENCL, " KERNEL BUILD DIRECTORY: %s\n", cachedir);
810
811 if(g_mkdir_with_parents(cachedir, 0700) == -1)
812 {
813 dt_print_nts(DT_DEBUG_OPENCL, " *** failed to create kernel directory `%s' ***\n", cachedir);
814 res = -1;
815 goto end;
816 }
817
818 dt_concat_path_file(filename, kerneldir, "programs.conf");
819
820 char *escapedkerneldir = NULL;
821#ifndef __APPLE__
822 escapedkerneldir = g_strdup_printf("\"%s\"", kerneldir);
823#else
824 escapedkerneldir = dt_util_str_replace(kerneldir, " ", "\\ ");
825#endif
826
827 gchar* compile_option_name_cname = g_strdup_printf("%s/%i/%s/building", DT_CLDEVICE_HEAD, dev, cl->dev[dev].cname);
828 const char* compile_opt = NULL;
829
830 if(dt_conf_key_exists(compile_option_name_cname))
831 compile_opt = dt_conf_get_string_const(compile_option_name_cname);
832 else
833 {
834 switch(vendor_id)
835 {
837 compile_opt = DT_OPENCL_DEFAULT_COMPILE_AMD;
838 break;
841 break;
844 break;
845 default:
846 compile_opt = DT_OPENCL_DEFAULT_COMPILE;
847 }
848 }
849 gchar *my_option = g_strdup(compile_opt);
850 dt_conf_set_string(compile_option_name_cname, my_option);
851
852 cl->dev[dev].options = g_strdup_printf("-w %s %s -D%s=1 -I%s",
853 my_option,
854 (cl->dev[dev].nvidia_sm_20 ? " -DNVIDIA_SM_20=1" : ""),
855 dt_opencl_get_vendor_by_id(vendor_id), escapedkerneldir);
856 // Keep kernel checksum stable when the runtime kernel path changes (e.g. AppImage mount point).
857 const char *kerneldir_token = "<ansel-kernels>";
858 char *escapedkerneldir_md5 = NULL;
859#ifndef __APPLE__
860 escapedkerneldir_md5 = g_strdup_printf("\"%s\"", kerneldir_token);
861#else
862 escapedkerneldir_md5 = g_strdup(kerneldir_token);
863#endif
864 cl->dev[dev].options_md5 = g_strdup_printf("-w %s %s -D%s=1 -I%s",
865 my_option,
866 (cl->dev[dev].nvidia_sm_20 ? " -DNVIDIA_SM_20=1" : ""),
867 dt_opencl_get_vendor_by_id(vendor_id), escapedkerneldir_md5);
868
869 dt_print_nts(DT_DEBUG_OPENCL, " CL COMPILER OPTION: %s\n", my_option);
870
871 dt_free(compile_option_name_cname);
872 dt_free(my_option);
873 dt_free(escapedkerneldir);
874 dt_free(escapedkerneldir_md5);
875 escapedkerneldir = NULL;
876
877 const char *clincludes[DT_OPENCL_MAX_INCLUDES] = { "rgb_norms.h", "noise_generator.h", "color_conversion.h", "colorspaces.cl", "colorspace.h", "common.h", NULL };
878 char *includemd5[DT_OPENCL_MAX_INCLUDES] = { NULL };
879 dt_opencl_md5sum(clincludes, includemd5);
880
881 if(newdevice) // so far the device seems to be ok. Make sure to write&export the conf database to
882 {
885 }
886
887 // now load all darktable cl kernels.
888 // TODO: compile as a job?
889 tstart = dt_get_wtime();
890 FILE *f = g_fopen(filename, "rb");
891 if(f)
892 {
893 while(!feof(f))
894 {
895 int prog = -1;
896 gchar *confline_pattern = g_strdup_printf("%%%" G_GSIZE_FORMAT "[^\n]\n", PATH_MAX * sizeof(char) - 1);
897 int rd = fscanf(f, confline_pattern, confentry);
898 dt_free(confline_pattern);
899 if(rd != 1) continue;
900 // remove comments:
901 size_t end = strlen(confentry);
902 for(size_t pos = 0; pos < end; pos++)
903 if(confentry[pos] == '#')
904 {
905 confentry[pos] = '\0';
906 for(int l = pos - 1; l >= 0; l--)
907 {
908 if(confentry[l] == ' ')
909 confentry[l] = '\0';
910 else
911 break;
912 }
913 break;
914 }
915 if(confentry[0] == '\0') continue;
916
917 const char *programname = NULL, *programnumber = NULL;
918 gchar **tokens = g_strsplit_set(confentry, " \t", 2);
919 if(tokens)
920 {
921 programname = tokens[0];
922 if(tokens[0])
923 programnumber = tokens[1]; // if the 0st wasn't NULL then we have at least the terminating NULL in [1]
924 }
925
926 prog = programnumber ? strtol(programnumber, NULL, 10) : -1;
927
928 if(IS_NULL_PTR(programname) || programname[0] == '\0' || prog < 0)
929 {
930 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_device_init] malformed entry in programs.conf `%s'; ignoring it!\n", confentry);
931 continue;
932 }
933 dt_concat_path_file(filename, kerneldir, programname);
934 gchar *program_bin = g_strdup_printf("%s.bin", programname);
935 dt_concat_path_file(binname, cachedir, program_bin);
936 dt_free(program_bin);
937
938 dt_vprint(DT_DEBUG_OPENCL, "[dt_opencl_device_init] testing program `%s' ..\n", programname);
939 int loaded_cached;
940 char md5sum[33];
941 if(dt_opencl_load_program(dev, prog, filename, binname, cachedir, md5sum, includemd5, &loaded_cached))
942 {
943 if(!loaded_cached)
945
946 if(dt_opencl_build_program(dev, prog, binname, cachedir, md5sum, loaded_cached) != CL_SUCCESS)
947 {
948 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_device_init] failed to compile program `%s'!\n", programname);
949 fclose(f);
950 g_strfreev(tokens);
951 res = -1;
952 goto end;
953 }
954 }
955
956 g_strfreev(tokens);
957 }
958
959 fclose(f);
960 tend = dt_get_wtime();
961 tdiff = tend - tstart;
962 dt_print_nts(DT_DEBUG_OPENCL, " KERNEL LOADING TIME: %2.4lf sec\n", tdiff);
963 }
964 else
965 {
966 dt_print_nts(DT_DEBUG_OPENCL, "[dt_opencl_device_init] could not open `%s'!\n", filename);
967 res = -1;
968 goto end;
969 }
970 for(int n = 0; n < DT_OPENCL_MAX_INCLUDES; n++) dt_free(includemd5[n]);
971 res = 0;
972
973end:
974 // we always write the device config to keep track of disabled devices
976
977 if(res != 0)
978 {
979 if(lock_initialized)
980 {
981 for(int n = 0; n < DT_OPENCL_MAX_KERNELS; n++)
982 if(cl->dev[dev].kernel_used[n]) (cl->dlocl->symbols->dt_clReleaseKernel)(cl->dev[dev].kernel[n]);
983 for(int n = 0; n < DT_OPENCL_MAX_PROGRAMS; n++)
984 if(cl->dev[dev].program_used[n]) (cl->dlocl->symbols->dt_clReleaseProgram)(cl->dev[dev].program[n]);
985 if(!IS_NULL_PTR(cl->dev[dev].cmd_queue))
987 if(!IS_NULL_PTR(cl->dev[dev].context))
988 (cl->dlocl->symbols->dt_clReleaseContext)(cl->dev[dev].context);
990 }
991
992 dt_free(cl->dev[dev].vendor);
993 dt_free(cl->dev[dev].name);
994 dt_free(cl->dev[dev].cname);
995 dt_free(cl->dev[dev].options);
996 dt_free(cl->dev[dev].options_md5);
997 }
998
999 dt_free(infostr);
1000 dt_free(cname);
1001 dt_free(vendor);
1002 dt_free(driverversion);
1003 dt_free(deviceversion);
1004
1005 dt_free(dtcache);
1006 dt_free(cachedir);
1007 dt_free(devname);
1008 dt_free(drvversion);
1009 dt_free(platform_name);
1010 dt_free(platform_vendor);
1011
1012 dt_free(filename);
1013 dt_free(confentry);
1014 dt_free(binname);
1015
1016 return res;
1017}
1018
1019void dt_opencl_init(dt_opencl_t *cl, const gboolean exclude_opencl, const gboolean print_statistics)
1020{
1022
1023 dt_pthread_mutex_init(&cl->lock, NULL);
1025 cl->mem_sizes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
1026 cl->inited = 0;
1027 cl->enabled = 0;
1028 cl->stopped = 0;
1029 cl->error_count = 0;
1030 cl->print_statistics = print_statistics;
1031
1032 // work-around to fix a bug in some AMD OpenCL compilers, which would fail parsing certain numerical
1033 // constants if locale is different from "C".
1034 // we save the current locale, set locale to "C", and restore the previous setting after OpenCL is
1035 // initialized
1036 char *locale = strdup(setlocale(LC_ALL, NULL));
1037 setlocale(LC_ALL, "C");
1038
1039 cl->crc = 5781;
1040 cl->dlocl = NULL;
1041 cl->dev_priority_image = 0;
1042 cl->dev_priority_preview = 0;
1043 cl->dev_priority_export = 0;
1044 cl->dev_priority_thumbnail = 0;
1045 cl->num_detected_devs = 0;
1046 cl->detected_devs = NULL;
1047
1048 if(exclude_opencl) return;
1049
1050 cl_platform_id *all_platforms = NULL;
1051 cl_uint *all_num_devices = NULL;
1052
1053 char *platform_name = calloc(DT_OPENCL_CBUFFSIZE, sizeof(char));
1054 char *platform_vendor = calloc(DT_OPENCL_CBUFFSIZE, sizeof(char));
1055
1056 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] opencl related configuration options:\n");
1057 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] opencl: %s\n", dt_conf_get_bool("opencl") ? "ON" : "OFF" );
1058 // look for explicit definition of opencl_runtime library in preferences
1059 const char *library = dt_conf_get_string_const("opencl_library");
1060 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] opencl_library: '%s'\n", (strlen(library) == 0) ? "default path" : library);
1061 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] opencl_mandatory_timeout: %d\n",
1062 dt_conf_get_int("opencl_mandatory_timeout"));
1063
1064 // dynamically load opencl runtime
1065 if((cl->dlocl = dt_dlopencl_init(library)) == NULL)
1066 {
1068 "[opencl_init] no working opencl library found. Continue with opencl disabled\n");
1069 goto finally;
1070 }
1071 else
1072 {
1073 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] opencl library '%s' found on your system and loaded\n",
1074 cl->dlocl->library);
1075 }
1076
1077 cl_int err;
1078 all_platforms = malloc(sizeof(cl_platform_id) * DT_OPENCL_MAX_PLATFORMS);
1079 all_num_devices = malloc(sizeof(cl_uint) * DT_OPENCL_MAX_PLATFORMS);
1080 cl_uint num_platforms = DT_OPENCL_MAX_PLATFORMS;
1081 err = (cl->dlocl->symbols->dt_clGetPlatformIDs)(DT_OPENCL_MAX_PLATFORMS, all_platforms, &num_platforms);
1082 if(err != CL_SUCCESS)
1083 {
1084 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] could not get platforms: %i\n", err);
1085 goto finally;
1086 }
1087
1088 if(num_platforms == 0)
1089 {
1090 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] no opencl platform available\n");
1091 goto finally;
1092 }
1093 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] found %d platform%s\n", num_platforms,
1094 num_platforms > 1 ? "s" : "");
1095
1096 for(int n = 0; n < num_platforms; n++)
1097 {
1098 cl_platform_id platform = all_platforms[n];
1099 // get the number of GPU devices available to the platforms
1100 // the other common option is CL_DEVICE_TYPE_GPU/CPU (but the latter doesn't work with the nvidia drivers)
1101 err = (cl->dlocl->symbols->dt_clGetDeviceIDs)(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &(all_num_devices[n]));
1102 if(err != CL_SUCCESS)
1103 {
1104 cl_int errv = (cl->dlocl->symbols->dt_clGetPlatformInfo)(platform, CL_PLATFORM_VENDOR, DT_OPENCL_CBUFFSIZE, platform_vendor, NULL);
1105 cl_int errn = (cl->dlocl->symbols->dt_clGetPlatformInfo)(platform, CL_PLATFORM_NAME, DT_OPENCL_CBUFFSIZE, platform_name, NULL);
1106 if((errn == CL_SUCCESS) && (errv == CL_SUCCESS))
1107 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] no devices found for %s (vendor) - %s (name)\n", platform_vendor, platform_name);
1108 else
1109 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] no devices found for unknown platform\n");
1110
1111 all_num_devices[n] = 0;
1112 }
1113 else
1114 {
1115 char profile[64] = { 0 };
1116 size_t profile_size;
1117 err = (cl->dlocl->symbols->dt_clGetPlatformInfo)(platform, CL_PLATFORM_PROFILE, 64, profile, &profile_size);
1118 if(err != CL_SUCCESS)
1119 {
1120 all_num_devices[n] = 0;
1121 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] could not get profile: %i\n", err);
1122 }
1123 else
1124 {
1125 // fprintf(stderr, "%s\n", profile);
1126 if(strcmp("FULL_PROFILE", profile) != 0)
1127 {
1128 all_num_devices[n] = 0;
1129 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] platform %i is not FULL_PROFILE\n", n);
1130 }
1131 }
1132 }
1133 }
1134
1135 cl_uint num_devices = 0;
1136 for(int n = 0; n < num_platforms; n++) num_devices += all_num_devices[n];
1137
1138 // create the device list
1139 cl_device_id *devices = 0;
1140 if(num_devices)
1141 {
1142 cl->dev = (dt_opencl_device_t *)malloc(sizeof(dt_opencl_device_t) * num_devices);
1143 devices = (cl_device_id *)malloc(sizeof(cl_device_id) * num_devices);
1144 if(IS_NULL_PTR(cl->dev) || IS_NULL_PTR(devices))
1145 {
1146 dt_free(cl->dev);
1147 dt_free(devices);
1148 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] could not allocate memory\n");
1149 goto finally;
1150 }
1151 }
1152
1153 cl_device_id *devs = devices;
1154 for(int n = 0; n < num_platforms; n++)
1155 {
1156 if(all_num_devices[n])
1157 {
1158 cl_platform_id platform = all_platforms[n];
1159 err = (cl->dlocl->symbols->dt_clGetDeviceIDs)(platform, CL_DEVICE_TYPE_ALL, all_num_devices[n], devs,
1160 NULL);
1161 if(err != CL_SUCCESS)
1162 {
1163 num_devices -= all_num_devices[n];
1164 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] could not get devices list: %i\n", err);
1165 }
1166 devs += all_num_devices[n];
1167 }
1168 }
1169 devs = NULL;
1170
1171 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] found %d device%s\n", num_devices, num_devices > 1 ? "s" : "");
1172 if(num_devices == 0)
1173 {
1174 if(devices)
1175 {
1176 dt_free(devices);
1177 }
1178 goto finally;
1179 }
1180
1181 int dev = 0;
1182 for(int k = 0; k < num_devices; k++)
1183 {
1184 const int res = dt_opencl_device_init(cl, dev, devices, k);
1185 if(res != 0)
1186 continue;
1187 // increase dev only if dt_opencl_device_init was successful (res == 0)
1188 ++dev;
1189 }
1190 dt_free(devices);
1191
1192 if(dev > 0)
1193 {
1194 cl->num_devs = dev;
1195 cl->inited = 1;
1196 cl->enabled = dt_conf_get_bool("opencl");
1197 memset(cl->mandatory, 0, sizeof(cl->mandatory));
1198 cl->dev_priority_image = (int *)malloc(sizeof(int) * (dev + 1));
1199 cl->dev_priority_preview = (int *)malloc(sizeof(int) * (dev + 1));
1200 cl->dev_priority_export = (int *)malloc(sizeof(int) * (dev + 1));
1201 cl->dev_priority_thumbnail = (int *)malloc(sizeof(int) * (dev + 1));
1202
1203 // only check successful malloc in debug mode; darktable will crash anyhow sooner or later if mallocs that
1204 // small would fail
1207
1208 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] OpenCL successfully initialized.\n");
1209 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] here are the internal numbers and names of OpenCL devices available to Ansel:\n");
1210 for(int i = 0; i < dev; i++) dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init]\t\t%d\t'%s'\n", i, cl->dev[i].name);
1211 }
1212 else
1213 {
1214 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] no suitable devices found.\n");
1215 }
1216
1217finally:
1218 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] FINALLY: opencl is %sAVAILABLE on this system.\n",
1219 cl->inited ? "" : "NOT ");
1220 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_init] initial status of opencl enabled flag is %s.\n",
1221 cl->enabled ? "ON" : "OFF");
1222
1223 char checksum[64];
1224 snprintf(checksum, sizeof(checksum), "%u", cl->crc);
1225
1226 if(cl->inited)
1227 {
1228 dt_capabilities_add("opencl");
1234 cl->dwt = dt_dwt_init_cl_global();
1238 }
1239
1241
1242 if(!cl->inited)// initialization failed
1243 {
1244 for(int i = 0; cl->dev && i < cl->num_devs; i++) dt_opencl_cleanup_device(cl, i);
1245 }
1246
1247 dt_free(all_num_devices);
1248 dt_free(all_platforms);
1249 dt_free(platform_name);
1250 dt_free(platform_vendor);
1251
1252 if(locale)
1253 {
1254 setlocale(LC_ALL, locale);
1255 dt_free(locale);
1256 }
1257
1258 return;
1259}
1260
1262{
1264 for(int k = 0; k < DT_OPENCL_MAX_KERNELS; k++)
1265 if(cl->dev[i].kernel_used[k]) (cl->dlocl->symbols->dt_clReleaseKernel)(cl->dev[i].kernel[k]);
1266 for(int k = 0; k < DT_OPENCL_MAX_PROGRAMS; k++)
1267 if(cl->dev[i].program_used[k]) (cl->dlocl->symbols->dt_clReleaseProgram)(cl->dev[i].program[k]);
1268 if(!IS_NULL_PTR(cl->dev[i].cmd_queue))
1270 if(!IS_NULL_PTR(cl->dev[i].context))
1272
1274 {
1275 dt_print_nts(DT_DEBUG_OPENCL, " [opencl_summary_statistics] device '%s' (%d): peak memory usage %" G_GSIZE_FORMAT " bytes (%.1f MB)\n",
1276 cl->dev[i].name, i, cl->dev[i].peak_memory, (float)cl->dev[i].peak_memory/(1024*1024));
1277 }
1278
1279 if(cl->print_statistics && cl->dev[i].use_events)
1280 {
1281 if(cl->dev[i].totalevents)
1282 {
1283 dt_print_nts(DT_DEBUG_OPENCL, " [opencl_summary_statistics] device '%s' (%d): %d out of %d events were "
1284 "successful and %d events lost. max event=%d%s\n",
1285 cl->dev[i].name, i, cl->dev[i].totalsuccess, cl->dev[i].totalevents, cl->dev[i].totallost,
1286 cl->dev[i].maxeventslot, (cl->dev[i].maxeventslot > 1024) ? "\n *** Warning, slots > 1024" : "");
1287 }
1288 else
1289 {
1290 dt_print_nts(DT_DEBUG_OPENCL, " [opencl_summary_statistics] device '%s' (%d): NOT utilized\n",
1291 cl->dev[i].name, i);
1292 }
1293 }
1294
1295 if(cl->dev[i].use_events)
1296 {
1298
1299 dt_free(cl->dev[i].eventlist);
1300 dt_free(cl->dev[i].eventtags);
1301 }
1302
1303 dt_free(cl->dev[i].vendor);
1304 dt_free(cl->dev[i].name);
1305 dt_free(cl->dev[i].cname);
1306 dt_free(cl->dev[i].options);
1307 dt_free(cl->dev[i].options_md5);
1308}
1309
1311{
1312 if(cl->inited)
1313 {
1323
1324 for(int i = 0; i < cl->num_devs; i++)
1326
1331 }
1332
1333 if(cl->dlocl)
1334 {
1335 dt_free(cl->dlocl->symbols);
1336 dt_free(cl->dlocl->library);
1337 dt_free(cl->dlocl);
1338 }
1339
1340 for(int i = 0; i < cl->num_detected_devs; i++)
1341 {
1344 }
1346
1347 dt_free(cl->dev);
1348 if(cl->mem_sizes) g_hash_table_destroy(cl->mem_sizes);
1351}
1352
1353static const char *dt_opencl_get_vendor_by_id(unsigned int id)
1354{
1355 const char *vendor;
1356
1357 switch(id)
1358 {
1360 vendor = "AMD";
1361 break;
1363 vendor = "NVIDIA";
1364 break;
1366 vendor = "INTEL";
1367 break;
1368 default:
1369 vendor = "UNKNOWN";
1370 }
1371
1372 return vendor;
1373}
1374
1375gboolean dt_opencl_finish(const int devid)
1376{
1378 if(!cl->inited || devid < 0) return FALSE;
1379
1380 cl_int err = (cl->dlocl->symbols->dt_clFinish)(cl->dev[devid].cmd_queue);
1381
1382 // take the opportunity to release some event handles, but without printing
1383 // summary statistics
1384 cl_int success = dt_opencl_events_flush(devid, 0);
1385
1386 return (err == CL_SUCCESS && success == CL_COMPLETE);
1387}
1388
1389int dt_opencl_enqueue_barrier(const int devid)
1390{
1392 if(!cl->inited || devid < 0) return -1;
1393 return (cl->dlocl->symbols->dt_clEnqueueBarrier)(cl->dev[devid].cmd_queue);
1394}
1395
1396static int _take_from_list(int *list, int value)
1397{
1398 int result = -1;
1399
1400 while(*list != -1 && *list != value) list++;
1401 result = *list;
1402
1403 while(*list != -1)
1404 {
1405 *list = *(list + 1);
1406 list++;
1407 }
1408
1409 return result;
1410}
1411
1412
1413static int _device_by_cname(const char *name)
1414{
1416 int devs = cl->num_devs;
1417 char tmp[2048] = { 0 };
1418 int result = -1;
1419
1420 _ascii_str_canonical(name, tmp, sizeof(tmp));
1421
1422 for(int i = 0; i < devs; i++)
1423 {
1424 if(!strcmp(tmp, cl->dev[i].cname))
1425 {
1426 result = i;
1427 break;
1428 }
1429 }
1430
1431 return result;
1432}
1433
1434
1435static char *_ascii_str_canonical(const char *in, char *out, int maxlen)
1436{
1437 if(IS_NULL_PTR(out))
1438 {
1439 maxlen = strlen(in) + 1;
1440 out = malloc(maxlen);
1441 if(IS_NULL_PTR(out)) return NULL;
1442 }
1443
1444 int len = 0;
1445
1446 while(*in != '\0' && len < maxlen - 1)
1447 {
1448 int n = strcspn(in, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
1449 in += n;
1450 if(n != 0) continue;
1451 out[len] = tolower(*in);
1452 len++;
1453 in++;
1454 }
1455 out[len] = '\0';
1456
1457 return out;
1458}
1459
1460// parse a single token of priority string and store priorities in priority_list
1461static void dt_opencl_priority_parse(dt_opencl_t *cl, char *configstr, int *priority_list, int *mandatory)
1462{
1463 int devs = cl->num_devs;
1464 int count = 0;
1465 int *full = malloc(sizeof(int) * (devs + 1));
1466 int mnd = 0;
1467
1468 // NULL or empty configstring?
1469 if(IS_NULL_PTR(configstr) || *configstr == '\0')
1470 {
1471 priority_list[0] = -1;
1472 *mandatory = 0;
1473 dt_free(full);
1474 return;
1475 }
1476
1477 // check if user wants us to force-use opencl device(s)
1478 if(configstr[0] == '+')
1479 {
1480 mnd = 1;
1481 configstr++;
1482 }
1483
1484 // first start with a full list of devices to take from
1485 for(int i = 0; i < devs; i++) full[i] = i;
1486 full[devs] = -1;
1487
1488 gchar **tokens = g_strsplit(configstr, ",", 0);
1489 gchar **tokens_ptr = tokens;
1490
1491 while(!IS_NULL_PTR(tokens) && !IS_NULL_PTR(*tokens_ptr) && count < devs + 1 && full[0] != -1)
1492 {
1493 gchar *str = *tokens_ptr;
1494 int not = 0;
1495 int all = 0;
1496
1497 switch(*str)
1498 {
1499 case '*':
1500 all = 1;
1501 break;
1502 case '!':
1503 not = 1;
1504 while(*str == '!') str++;
1505 break;
1506 }
1507
1508 if(all)
1509 {
1510 // copy all remaining device numbers from full to priority list
1511 for(int i = 0; i < devs && full[i] != -1; i++)
1512 {
1513 priority_list[count] = full[i];
1514 count++;
1515 }
1516 full[0] = -1; // mark full list as empty
1517 }
1518 else if(*str != '\0')
1519 {
1520 char *endptr = NULL;
1521
1522 // first check if str corresponds to an existing canonical device name
1523 long number = _device_by_cname(str);
1524
1525 // if not try to convert string into decimal device number
1526 if(number < 0) number = strtol(str, &endptr, 10);
1527
1528 // still not found or negative number given? set number to -1
1529 if(number < 0 || (number == 0 && endptr == str)) number = -1;
1530
1531 // try to take number out of remaining device list
1532 int dev_number = _take_from_list(full, number);
1533
1534 if(!not&&dev_number != -1)
1535 {
1536 priority_list[count] = dev_number;
1537 count++;
1538 }
1539 }
1540
1541 tokens_ptr++;
1542 }
1543
1544 g_strfreev(tokens);
1545
1546 // terminate priority list with -1
1547 while(count < devs + 1) priority_list[count++] = -1;
1548
1549 // opencl use can only be mandatory if at least one opencl device is given
1550 *mandatory = (priority_list[0] != -1) ? mnd : 0;
1551
1552 dt_free(full);
1553}
1554
1555// set device priorities according to config string
1557{
1559 if(!cl->inited) return;
1560
1561 // Priority parsing iterates over the list of available devices.
1562 // If !cl->inited, that means we have no available device, so empty list.
1563 // Exit early of face a segfault
1564 char *darkroom = dt_conf_get_string("opencl_devid_darkroom");
1565 char *preview = dt_conf_get_string("opencl_devid_preview");
1566 char *export = dt_conf_get_string("opencl_devid_export");
1567 char *thumbnail = dt_conf_get_string("opencl_devid_thumbnail");
1568
1569 dt_opencl_priority_parse(cl, darkroom, cl->dev_priority_image, &cl->mandatory[0]);
1570 dt_opencl_priority_parse(cl, preview, cl->dev_priority_preview, &cl->mandatory[1]);
1571 dt_opencl_priority_parse(cl, export, cl->dev_priority_export, &cl->mandatory[2]);
1572 dt_opencl_priority_parse(cl, thumbnail, cl->dev_priority_thumbnail, &cl->mandatory[3]);
1573
1574 dt_free(darkroom);
1575 dt_free(preview);
1576 dt_free(export);
1577 dt_free(thumbnail);
1578
1579 dt_print_nts(DT_DEBUG_OPENCL, "[dt_opencl_update_priorities] these are your device priorities:\n");
1580 dt_print_nts(DT_DEBUG_OPENCL, "[dt_opencl_update_priorities] \tid |\t\tIMAGE\tPREVIEW\tEXPORT\tTHUMBS\n");
1581 for(int i = 0; i < cl->num_devs; i++)
1582 dt_print_nts(DT_DEBUG_OPENCL, "[dt_opencl_update_priorities]\t%i |\t\t%d\t%d\t%d\t%d\n",
1583 i, cl->dev_priority_image[i],
1585 dt_print_nts(DT_DEBUG_OPENCL, "[dt_opencl_update_priorities] show if opencl use is mandatory for a given pixelpipe:\n");
1586 dt_print_nts(DT_DEBUG_OPENCL, "[dt_opencl_update_priorities] \t\tIMAGE\tPREVIEW\tEXPORT\tTHUMBS\n");
1587 dt_print_nts(DT_DEBUG_OPENCL, "[dt_opencl_update_priorities]\t\t%s\t%s\t%s\t%s\n", cl->mandatory[0] ? "yes" : "no",
1588 cl->mandatory[1] ? "yes" : "no", cl->mandatory[2] ? "yes" : "no", cl->mandatory[3] ? "yes" : "no");
1589}
1590
1591int dt_opencl_lock_device(const int pipetype)
1592{
1594 if(!cl->inited) return -1;
1595
1596
1598
1599 size_t prio_size = sizeof(int) * (cl->num_devs + 1);
1600 int *priority = (int *)malloc(prio_size);
1601 int mandatory;
1602
1603 switch(pipetype)
1604 {
1606 memcpy(priority, cl->dev_priority_image, prio_size);
1607 mandatory = cl->mandatory[0];
1608 break;
1610 memcpy(priority, cl->dev_priority_preview, prio_size);
1611 mandatory = cl->mandatory[1];
1612 break;
1614 memcpy(priority, cl->dev_priority_export, prio_size);
1615 mandatory = cl->mandatory[2];
1616 break;
1618 memcpy(priority, cl->dev_priority_thumbnail, prio_size);
1619 mandatory = cl->mandatory[3];
1620 break;
1621 default:
1622 dt_free(priority);
1623 mandatory = 0;
1624 }
1625
1627
1628 if(priority)
1629 {
1630 const int usec = 5000;
1631 const int nloop = MAX(0, dt_conf_get_int("opencl_mandatory_timeout"));
1632
1633 // check for free opencl device repeatedly if mandatory is TRUE, else give up after first try
1634 for(int n = 0; n < nloop; n++)
1635 {
1636 const int *prio = priority;
1637
1638 while(*prio != -1)
1639 {
1640 if(!dt_pthread_mutex_BAD_trylock(&cl->dev[*prio].lock))
1641 {
1642 int devid = *prio;
1643 dt_free(priority);
1644 return devid;
1645 }
1646 prio++;
1647 }
1648
1649 if(!mandatory)
1650 {
1651 dt_free(priority);
1652 return -1;
1653 }
1654
1655 dt_iop_nap(usec);
1656 }
1657 dt_print(DT_DEBUG_OPENCL, "[opencl_lock_device] reached opencl_mandatory_timeout trying to lock mandatory device, fallback to CPU\n");
1658 }
1659 else
1660 {
1661 // only a fallback if a new pipe type would be added and we forget to take care of it in opencl.c
1662 for(int try_dev = 0; try_dev < cl->num_devs; try_dev++)
1663 {
1664 // get first currently unused processor
1665 if(!dt_pthread_mutex_BAD_trylock(&cl->dev[try_dev].lock)) return try_dev;
1666 }
1667 }
1668
1669 dt_free(priority);
1670
1671 // no free GPU :(
1672 // use CPU processing, if no free device:
1673 return -1;
1674}
1675
1676void dt_opencl_unlock_device(const int dev)
1677{
1679 if(!cl->inited) return;
1680 if(dev < 0 || dev >= cl->num_devs) return;
1682}
1683
1684static FILE *fopen_stat(const char *filename, struct stat *st)
1685{
1686 FILE *f = g_fopen(filename, "rb");
1687 if(IS_NULL_PTR(f))
1688 {
1689 dt_print(DT_DEBUG_OPENCL, "[opencl_fopen_stat] could not open file `%s'!\n", filename);
1690 return NULL;
1691 }
1692 int fd = fileno(f);
1693 if(fstat(fd, st) < 0)
1694 {
1695 dt_print(DT_DEBUG_OPENCL, "[opencl_fopen_stat] could not stat file `%s'!\n", filename);
1696 return NULL;
1697 }
1698 return f;
1699}
1700
1701
1702void dt_opencl_md5sum(const char **files, char **md5sums)
1703{
1704 char kerneldir[PATH_MAX] = { 0 };
1705 char filename[PATH_MAX] = { 0 };
1706 dt_loc_get_kerneldir(kerneldir, sizeof(kerneldir));
1707
1708 for(int n = 0; n < DT_OPENCL_MAX_INCLUDES; n++, files++, md5sums++)
1709 {
1710 if(!*files)
1711 {
1712 *md5sums = NULL;
1713 continue;
1714 }
1715
1716 dt_concat_path_file(filename, kerneldir, *files);
1717
1718 struct stat filestat;
1719 FILE *f = fopen_stat(filename, &filestat);
1720
1721 if(IS_NULL_PTR(f))
1722 {
1723 dt_print(DT_DEBUG_OPENCL, "[opencl_md5sums] could not open file `%s'!\n", filename);
1724 *md5sums = NULL;
1725 continue;
1726 }
1727
1728 size_t filesize = filestat.st_size;
1729 char *file = (char *)malloc(filesize);
1730
1731 if(IS_NULL_PTR(file))
1732 {
1733 dt_print(DT_DEBUG_OPENCL, "[opencl_md5sums] could not allocate buffer for file `%s'!\n", filename);
1734 *md5sums = NULL;
1735 fclose(f);
1736 continue;
1737 }
1738
1739 size_t rd = fread(file, sizeof(char), filesize, f);
1740 fclose(f);
1741
1742 if(rd != filesize)
1743 {
1744 dt_free(file);
1745 dt_print(DT_DEBUG_OPENCL, "[opencl_md5sums] could not read all of file `%s'!\n", filename);
1746 *md5sums = NULL;
1747 continue;
1748 }
1749
1750 *md5sums = g_compute_checksum_for_data(G_CHECKSUM_MD5, (guchar *)file, filesize);
1751
1752 dt_free(file);
1753 }
1754}
1755
1756int dt_opencl_load_program(const int dev, const int prog, const char *filename, const char *binname,
1757 const char *cachedir, char *md5sum, char **includemd5, int *loaded_cached)
1758{
1759 cl_int err;
1761
1762 struct stat filestat, cachedstat;
1763 *loaded_cached = 0;
1764
1765 if(prog < 0 || prog >= DT_OPENCL_MAX_PROGRAMS)
1766 {
1767 dt_print(DT_DEBUG_OPENCL, "[opencl_load_source] invalid program number `%d' of file `%s'!\n", prog,
1768 filename);
1769 return 0;
1770 }
1771
1772 if(cl->dev[dev].program_used[prog])
1773 {
1775 "[opencl_load_source] program number `%d' already in use when loading file `%s'!\n", prog,
1776 filename);
1777 return 0;
1778 }
1779
1780 FILE *f = fopen_stat(filename, &filestat);
1781 if(IS_NULL_PTR(f)) return 0;
1782
1783 size_t filesize = filestat.st_size;
1784 char *file = (char *)malloc(filesize + 2048);
1785 size_t rd = fread(file, sizeof(char), filesize, f);
1786 fclose(f);
1787 if(rd != filesize)
1788 {
1789 dt_free(file);
1790 dt_print(DT_DEBUG_OPENCL, "[opencl_load_source] could not read all of file `%s'!\n", filename);
1791 return 0;
1792 }
1793
1794 char *start = file + filesize;
1795 char *end = start + 2048;
1796 size_t len;
1797
1798 cl_device_id devid = cl->dev[dev].devid;
1799 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DRIVER_VERSION, end - start, start, &len);
1800 start += len;
1801
1802 cl_platform_id platform;
1803 (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_PLATFORM, sizeof(cl_platform_id), &platform, NULL);
1804
1805 (cl->dlocl->symbols->dt_clGetPlatformInfo)(platform, CL_PLATFORM_VERSION, end - start, start, &len);
1806 start += len;
1807
1808 const char *options_md5 = cl->dev[dev].options_md5 ? cl->dev[dev].options_md5 : cl->dev[dev].options;
1809 len = g_strlcpy(start, options_md5, end - start);
1810 start += len;
1811
1812 /* make sure that the md5sums of all the includes are applied as well */
1813 for(int n = 0; n < DT_OPENCL_MAX_INCLUDES; n++)
1814 {
1815 if(!includemd5[n]) continue;
1816 len = g_strlcpy(start, includemd5[n], end - start);
1817 start += len;
1818 }
1819
1820 char *source_md5 = g_compute_checksum_for_data(G_CHECKSUM_MD5, (guchar *)file, start - file);
1821 g_strlcpy(md5sum, source_md5, 33);
1822 dt_free(source_md5);
1823
1824 file[filesize] = '\0';
1825
1826 char linkedfile[PATH_MAX] = { 0 };
1827 ssize_t linkedfile_len = 0;
1828
1829#if defined(_WIN32)
1830 // No symlinks on Windows
1831 // Have to figure out the name using the filename + md5sum
1832 char dup[PATH_MAX] = { 0 };
1833 snprintf(dup, sizeof(dup), "%s.%s", binname, md5sum);
1834 FILE *cached = fopen_stat(dup, &cachedstat);
1835 g_strlcpy(linkedfile, md5sum, sizeof(linkedfile));
1836 linkedfile_len = strlen(md5sum);
1837#else
1838 FILE *cached = fopen_stat(binname, &cachedstat);
1839#endif
1840
1841 if(cached)
1842 {
1843#if !defined(_WIN32)
1844 linkedfile_len = readlink(binname, linkedfile, sizeof(linkedfile) - 1);
1845#endif // !defined(_WIN32)
1846 if(linkedfile_len > 0)
1847 {
1848 linkedfile[linkedfile_len] = '\0';
1849
1850 if(strncmp(linkedfile, md5sum, 33) == 0)
1851 {
1852 // md5sum matches, load cached binary
1853 size_t cached_filesize = cachedstat.st_size;
1854
1855 unsigned char *cached_content = (unsigned char *)malloc(cached_filesize + 1);
1856 rd = fread(cached_content, sizeof(char), cached_filesize, cached);
1857 if(rd != cached_filesize)
1858 {
1859 dt_print(DT_DEBUG_OPENCL, "[opencl_load_program] could not read all of file '%s' MD5: %s!\n", binname, md5sum);
1860 }
1861 else
1862 {
1863 cl->dev[dev].program[prog] = (cl->dlocl->symbols->dt_clCreateProgramWithBinary)(
1864 cl->dev[dev].context, 1, &(cl->dev[dev].devid), &cached_filesize,
1865 (const unsigned char **)&cached_content, NULL, &err);
1866 if(err != CL_SUCCESS)
1867 {
1869 "[opencl_load_program] could not load cached binary program from file '%s' MD5: '%s'! (%i)\n",
1870 binname, md5sum, err);
1871 }
1872 else
1873 {
1874 cl->dev[dev].program_used[prog] = 1;
1875 *loaded_cached = 1;
1876 }
1877 }
1878 dt_free(cached_content);
1879 }
1880 }
1881 fclose(cached);
1882 }
1883
1884
1885 if(*loaded_cached == 0)
1886 {
1887 // if loading cached was unsuccessful for whatever reason,
1888 // try to remove cached binary & link
1889#if !defined(_WIN32)
1890 if(linkedfile_len > 0)
1891 {
1892 char link_dest[PATH_MAX] = { 0 };
1893 dt_concat_path_file(link_dest, cachedir, linkedfile);
1894 g_unlink(link_dest);
1895 }
1896 g_unlink(binname);
1897#else
1898 // delete the file which contains the MD5 name
1899 g_unlink(dup);
1900#endif
1901
1903 "[opencl_load_program] could not load cached binary program, trying to compile source\n");
1904
1905 cl->dev[dev].program[prog] = (cl->dlocl->symbols->dt_clCreateProgramWithSource)(
1906 cl->dev[dev].context, 1, (const char **)&file, &filesize, &err);
1907 dt_free(file);
1908 if((err != CL_SUCCESS) || (cl->dev[dev].program[prog] == NULL))
1909 {
1910 dt_print(DT_DEBUG_OPENCL, "[opencl_load_source] could not create program from file `%s'! (%i)\n",
1911 filename, err);
1912 return 0;
1913 }
1914 else
1915 {
1916 cl->dev[dev].program_used[prog] = 1;
1917 }
1918 }
1919 else
1920 {
1921 dt_free(file);
1922 dt_vprint(DT_DEBUG_OPENCL, "[opencl_load_program] loaded cached binary program from file '%s' MD5: '%s' \n", binname, md5sum);
1923 }
1924
1925 dt_vprint(DT_DEBUG_OPENCL, "[opencl_load_program] successfully loaded program from '%s' MD5: '%s'\n", filename, md5sum);
1926
1927 return 1;
1928}
1929
1930int dt_opencl_build_program(const int dev, const int prog, const char *binname, const char *cachedir,
1931 char *md5sum, int loaded_cached)
1932{
1933 if(prog < 0 || prog >= DT_OPENCL_MAX_PROGRAMS) return -1;
1935 cl_program program = cl->dev[dev].program[prog];
1936 cl_int err = (cl->dlocl->symbols->dt_clBuildProgram)(program, 1, &(cl->dev[dev].devid), cl->dev[dev].options, 0, 0);
1937
1938 if(err != CL_SUCCESS)
1939 dt_print(DT_DEBUG_OPENCL, "[opencl_build_program] could not build program: %i\n", err);
1940 else
1941 dt_vprint(DT_DEBUG_OPENCL, "[opencl_build_program] successfully built program\n");
1942
1943 cl_build_status build_status;
1944 (cl->dlocl->symbols->dt_clGetProgramBuildInfo)(program, cl->dev[dev].devid, CL_PROGRAM_BUILD_STATUS,
1945 sizeof(cl_build_status), &build_status, NULL);
1946 dt_vprint(DT_DEBUG_OPENCL, "[opencl_build_program] BUILD STATUS: %d\n", build_status);
1947
1948 char *build_log;
1949 size_t ret_val_size;
1950 (cl->dlocl->symbols->dt_clGetProgramBuildInfo)(program, cl->dev[dev].devid, CL_PROGRAM_BUILD_LOG, 0, NULL,
1951 &ret_val_size);
1952 if(ret_val_size != SIZE_MAX)
1953 {
1954 build_log = (char *)malloc(sizeof(char) * (ret_val_size + 1));
1955 if(build_log)
1956 {
1957 (cl->dlocl->symbols->dt_clGetProgramBuildInfo)(program, cl->dev[dev].devid, CL_PROGRAM_BUILD_LOG,
1958 ret_val_size, build_log, NULL);
1959
1960 build_log[ret_val_size] = '\0';
1961
1962 dt_vprint(DT_DEBUG_OPENCL, "BUILD LOG:\n");
1963 dt_vprint(DT_DEBUG_OPENCL, "%s\n", build_log);
1964
1965 dt_free(build_log);
1966 }
1967 }
1968
1969 if(err != CL_SUCCESS)
1970 return err;
1971 else
1972 {
1973 if(!loaded_cached)
1974 {
1975 dt_vprint(DT_DEBUG_OPENCL, "[opencl_build_program] saving binary\n");
1976
1977 cl_uint numdev = 0;
1978 err = (cl->dlocl->symbols->dt_clGetProgramInfo)(program, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint),
1979 &numdev, NULL);
1980 if(err != CL_SUCCESS)
1981 {
1982 dt_print(DT_DEBUG_OPENCL, "[opencl_build_program] CL_PROGRAM_NUM_DEVICES failed: %i\n", err);
1983 return CL_SUCCESS;
1984 }
1985
1986 cl_device_id *devices = malloc(sizeof(cl_device_id) * numdev);
1987 err = (cl->dlocl->symbols->dt_clGetProgramInfo)(program, CL_PROGRAM_DEVICES,
1988 sizeof(cl_device_id) * numdev, devices, NULL);
1989 if(err != CL_SUCCESS)
1990 {
1991 dt_print(DT_DEBUG_OPENCL, "[opencl_build_program] CL_PROGRAM_DEVICES failed: %i\n", err);
1992 dt_free(devices);
1993 return CL_SUCCESS;
1994 }
1995
1996 size_t *binary_sizes = malloc(sizeof(size_t) * numdev);
1997 err = (cl->dlocl->symbols->dt_clGetProgramInfo)(program, CL_PROGRAM_BINARY_SIZES,
1998 sizeof(size_t) * numdev, binary_sizes, NULL);
1999 if(err != CL_SUCCESS)
2000 {
2001 dt_print(DT_DEBUG_OPENCL, "[opencl_build_program] CL_PROGRAM_BINARY_SIZES failed: %i\n", err);
2002 dt_free(binary_sizes);
2003 dt_free(devices);
2004 return CL_SUCCESS;
2005 }
2006
2007 unsigned char **binaries = malloc(sizeof(unsigned char *) * numdev);
2008 for(int i = 0; i < numdev; i++) binaries[i] = (unsigned char *)malloc(binary_sizes[i]);
2009 err = (cl->dlocl->symbols->dt_clGetProgramInfo)(program, CL_PROGRAM_BINARIES,
2010 sizeof(unsigned char *) * numdev, binaries, NULL);
2011 if(err != CL_SUCCESS)
2012 {
2013 dt_print(DT_DEBUG_OPENCL, "[opencl_build_program] CL_PROGRAM_BINARIES failed: %i\n", err);
2014 goto ret;
2015 }
2016
2017 for(int i = 0; i < numdev; i++)
2018 if(cl->dev[dev].devid == devices[i])
2019 {
2020 // save opencl compiled binary as md5sum-named file
2021 char link_dest[PATH_MAX] = { 0 };
2022 snprintf(link_dest, sizeof(link_dest), "%s" G_DIR_SEPARATOR_S "%s", cachedir, md5sum);
2023 FILE *f = g_fopen(link_dest, "wb");
2024 if(IS_NULL_PTR(f)) goto ret;
2025 size_t bytes_written = fwrite(binaries[i], sizeof(char), binary_sizes[i], f);
2026 if(bytes_written != binary_sizes[i]) goto ret;
2027 fclose(f);
2028
2029 // create link (e.g. basic.cl.bin -> f1430102c53867c162bb60af6c163328)
2030 char cwd[PATH_MAX] = { 0 };
2031 if(!getcwd(cwd, sizeof(cwd))) goto ret;
2032 if(chdir(cachedir) != 0) goto ret;
2033 char dup[PATH_MAX] = { 0 };
2034 g_strlcpy(dup, binname, sizeof(dup));
2035 char *bname = basename(dup);
2036#if defined(_WIN32)
2037 //CreateSymbolicLink in Windows requires admin privileges, which we don't want/need
2038 //store has using a simple filerename
2039 char finalfilename[PATH_MAX] = { 0 };
2040 snprintf(finalfilename, sizeof(finalfilename), "%s" G_DIR_SEPARATOR_S "%s.%s", cachedir, bname, md5sum);
2041 rename(link_dest, finalfilename);
2042#else
2043 if(symlink(md5sum, bname) != 0) goto ret;
2044#endif
2045 if(chdir(cwd) != 0) goto ret;
2046 }
2047
2048 ret:
2049 for(int i = 0; i < numdev; i++) dt_free(binaries[i]);
2050 dt_free(binaries);
2051 dt_free(binary_sizes);
2052 dt_free(devices);
2053 }
2054 return CL_SUCCESS;
2055 }
2056}
2057
2058int dt_opencl_create_kernel(const int prog, const char *name)
2059{
2061 if(!cl->inited) return -1;
2062 if(prog < 0 || prog >= DT_OPENCL_MAX_PROGRAMS) return -1;
2064 int k = 0;
2065 for(int dev = 0; dev < cl->num_devs; dev++)
2066 {
2067 cl_int err;
2068 for(; k < DT_OPENCL_MAX_KERNELS; k++)
2069 if(!cl->dev[dev].kernel_used[k])
2070 {
2071 cl->dev[dev].kernel_used[k] = 1;
2072 cl->dev[dev].kernel[k]
2073 = (cl->dlocl->symbols->dt_clCreateKernel)(cl->dev[dev].program[prog], name, &err);
2074 if(err != CL_SUCCESS)
2075 {
2076 dt_print(DT_DEBUG_OPENCL, "[opencl_create_kernel] could not create kernel `%s'! (%i)\n", name, err);
2077 cl->dev[dev].kernel_used[k] = 0;
2078 goto error;
2079 }
2080 else
2081 break;
2082 }
2084 {
2085 dt_vprint(DT_DEBUG_OPENCL, "[opencl_create_kernel] successfully loaded kernel `%s' (%d) for device %d\n",
2086 name, k, dev);
2087 }
2088 else
2089 {
2090 dt_print(DT_DEBUG_OPENCL, "[opencl_create_kernel] too many kernels! can't create kernel `%s'\n", name);
2091 goto error;
2092 }
2093 }
2095 return k;
2096error:
2098 return -1;
2099}
2100
2102{
2104 if(!cl->inited) return;
2105 if(kernel < 0 || kernel >= DT_OPENCL_MAX_KERNELS) return;
2107 for(int dev = 0; dev < cl->num_devs; dev++)
2108 {
2109 cl->dev[dev].kernel_used[kernel] = 0;
2110 (cl->dlocl->symbols->dt_clReleaseKernel)(cl->dev[dev].kernel[kernel]);
2111 }
2113}
2114
2115int dt_opencl_get_max_work_item_sizes(const int dev, size_t *sizes)
2116{
2118 if(!cl->inited || dev < 0) return -1;
2119 return (cl->dlocl->symbols->dt_clGetDeviceInfo)(cl->dev[dev].devid, CL_DEVICE_MAX_WORK_ITEM_SIZES,
2120 sizeof(size_t) * 3, sizes, NULL);
2121}
2122
2123int dt_opencl_get_work_group_limits(const int dev, size_t *sizes, size_t *workgroupsize,
2124 unsigned long *localmemsize)
2125{
2127 if(!cl->inited || dev < 0) return -1;
2128 cl_ulong lmemsize;
2129 cl_int err = (cl->dlocl->symbols->dt_clGetDeviceInfo)(cl->dev[dev].devid, CL_DEVICE_LOCAL_MEM_SIZE,
2130 sizeof(cl_ulong), &lmemsize, NULL);
2131 if(err != CL_SUCCESS) return err;
2132
2133 *localmemsize = lmemsize;
2134
2135 err = (cl->dlocl->symbols->dt_clGetDeviceInfo)(cl->dev[dev].devid, CL_DEVICE_MAX_WORK_GROUP_SIZE,
2136 sizeof(size_t), workgroupsize, NULL);
2137 if(err != CL_SUCCESS) return err;
2138
2139 return dt_opencl_get_max_work_item_sizes(dev, sizes);
2140}
2141
2142
2143int dt_opencl_get_kernel_work_group_size(const int dev, const int kernel, size_t *kernelworkgroupsize)
2144{
2146 if(!cl->inited || dev < 0) return -1;
2147 if(kernel < 0 || kernel >= DT_OPENCL_MAX_KERNELS) return -1;
2148
2149 return (cl->dlocl->symbols->dt_clGetKernelWorkGroupInfo)(cl->dev[dev].kernel[kernel], cl->dev[dev].devid,
2150 CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t),
2151 kernelworkgroupsize, NULL);
2152}
2153
2154
2155int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size,
2156 const void *arg)
2157{
2159 if(!cl->inited || dev < 0) return -1;
2160 if(kernel < 0 || kernel >= DT_OPENCL_MAX_KERNELS) return -1;
2161 return (cl->dlocl->symbols->dt_clSetKernelArg)(cl->dev[dev].kernel[kernel], num, size, arg);
2162}
2163
2164int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
2165{
2166 return dt_opencl_enqueue_kernel_2d_with_local(dev, kernel, sizes, NULL);
2167}
2168
2169
2170int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes,
2171 const size_t *local)
2172{
2174 if(!cl->inited || dev < 0) return -1;
2175 if(kernel < 0 || kernel >= DT_OPENCL_MAX_KERNELS) return -1;
2176
2177 char buf[256];
2178 buf[0] = '\0';
2180 (cl->dlocl->symbols->dt_clGetKernelInfo)(cl->dev[dev].kernel[kernel], CL_KERNEL_FUNCTION_NAME, 256, buf, NULL);
2181 cl_event *eventp = dt_opencl_events_get_slot(dev, buf);
2182 cl_int err = (cl->dlocl->symbols->dt_clEnqueueNDRangeKernel)(cl->dev[dev].cmd_queue, cl->dev[dev].kernel[kernel],
2183 2, NULL, sizes, local, 0, NULL, eventp);
2184
2185 if(err != CL_SUCCESS)
2186 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_enqueue_kernel_2d_with_local] kernel %i (%s) on device %d: %i\n", kernel, buf, dev, err);
2187
2188 return err;
2189}
2190
2191int dt_opencl_copy_device_to_host(const int devid, void *host, void *device, const int width,
2192 const int height, const int bpp)
2193{
2194 return dt_opencl_read_host_from_device(devid, host, device, width, height, bpp);
2195}
2196
2197int dt_opencl_read_host_from_device(const int devid, void *host, void *device, const int width,
2198 const int height, const int bpp)
2199{
2200 return dt_opencl_read_host_from_device_rowpitch(devid, host, device, width, height, bpp * width);
2201}
2202
2203int dt_opencl_read_host_from_device_rowpitch(const int devid, void *host, void *device, const int width,
2204 const int height, const int rowpitch)
2205{
2206 if(!darktable.opencl->inited || devid < 0) return -1;
2207 const size_t origin[] = { 0, 0, 0 };
2208 const size_t region[] = { width, height, 1 };
2209 // blocking.
2210 return dt_opencl_read_host_from_device_raw(devid, host, device, origin, region, rowpitch, CL_TRUE);
2211}
2212
2213int dt_opencl_read_host_from_device_non_blocking(const int devid, void *host, void *device, const int width,
2214 const int height, const int bpp)
2215{
2217 bpp * width);
2218}
2219
2220int dt_opencl_read_host_from_device_rowpitch_non_blocking(const int devid, void *host, void *device,
2221 const int width, const int height,
2222 const int rowpitch)
2223{
2224 if(!darktable.opencl->inited || devid < 0) return -1;
2225 const size_t origin[] = { 0, 0, 0 };
2226 const size_t region[] = { width, height, 1 };
2227 // non-blocking.
2228 return dt_opencl_read_host_from_device_raw(devid, host, device, origin, region, rowpitch, CL_FALSE);
2229}
2230
2231
2232int dt_opencl_read_host_from_device_raw(const int devid, void *host, void *device, const size_t *origin,
2233 const size_t *region, const int rowpitch, const int blocking)
2234{
2235 if(!darktable.opencl->inited) return -1;
2236
2237 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Read Image (from device to host)]");
2238
2240 device, blocking ? CL_TRUE : CL_FALSE, origin, region, rowpitch,
2241 0, host, 0, NULL, eventp);
2242}
2243
2244int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width,
2245 const int height, const int bpp)
2246{
2247 return dt_opencl_write_host_to_device_rowpitch(devid, host, device, width, height, width * bpp);
2248}
2249
2250int dt_opencl_write_host_to_device_rowpitch(const int devid, void *host, void *device, const int width,
2251 const int height, const int rowpitch)
2252{
2253 if(!darktable.opencl->inited || devid < 0) return -1;
2254 const size_t origin[] = { 0, 0, 0 };
2255 const size_t region[] = { width, height, 1 };
2256 // blocking.
2257 return dt_opencl_write_host_to_device_raw(devid, host, device, origin, region, rowpitch, CL_TRUE);
2258}
2259
2260int dt_opencl_write_host_to_device_non_blocking(const int devid, void *host, void *device, const int width,
2261 const int height, const int bpp)
2262{
2264}
2265
2266int dt_opencl_write_host_to_device_rowpitch_non_blocking(const int devid, void *host, void *device,
2267 const int width, const int height,
2268 const int rowpitch)
2269{
2270 if(!darktable.opencl->inited || devid < 0) return -1;
2271 const size_t origin[] = { 0, 0, 0 };
2272 const size_t region[] = { width, height, 1 };
2273 // non-blocking.
2274 return dt_opencl_write_host_to_device_raw(devid, host, device, origin, region, rowpitch, CL_FALSE);
2275}
2276
2277int dt_opencl_write_host_to_device_raw(const int devid, const void *host, void *device, const size_t *origin,
2278 const size_t *region, const int rowpitch, const int blocking)
2279{
2280 if(!darktable.opencl->inited) return -1;
2281
2282 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Write Image (from host to device)]");
2283
2285 device, blocking ? CL_TRUE : CL_FALSE, origin, region,
2286 rowpitch, 0, host, 0, NULL, eventp);
2287}
2288
2289int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst,
2290 size_t *region)
2291{
2292 if(!darktable.opencl->inited || devid < 0) return -1;
2293 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Copy Image (on device)]");
2295 darktable.opencl->dev[devid].cmd_queue, src, dst, orig_src, orig_dst, region, 0, NULL, eventp);
2296 if(err != CL_SUCCESS) dt_print(DT_DEBUG_OPENCL, "[opencl copy_image] could not copy image on device %d: %i\n", devid, err);
2297 return err;
2298}
2299
2300int dt_opencl_enqueue_copy_image_to_buffer(const int devid, cl_mem src_image, cl_mem dst_buffer,
2301 size_t *origin, size_t *region, size_t offset)
2302{
2303 if(!darktable.opencl->inited) return -1;
2304 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Copy Image to Buffer (on device)]");
2306 darktable.opencl->dev[devid].cmd_queue, src_image, dst_buffer, origin, region, offset, 0, NULL, eventp);
2307 if(err != CL_SUCCESS)
2308 dt_print(DT_DEBUG_OPENCL, "[opencl copy_image_to_buffer] could not copy image on device %d: %i\n", devid, err);
2309 return err;
2310}
2311
2312int dt_opencl_enqueue_copy_buffer_to_image(const int devid, cl_mem src_buffer, cl_mem dst_image,
2313 size_t offset, size_t *origin, size_t *region)
2314{
2315 if(!darktable.opencl->inited) return -1;
2316 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Copy Buffer to Image (on device)]");
2318 darktable.opencl->dev[devid].cmd_queue, src_buffer, dst_image, offset, origin, region, 0, NULL, eventp);
2319 if(err != CL_SUCCESS)
2320 dt_print(DT_DEBUG_OPENCL, "[opencl copy_buffer_to_image] could not copy buffer on device %d: %i\n", devid, err);
2321 return err;
2322}
2323
2324int dt_opencl_enqueue_copy_buffer_to_buffer(const int devid, cl_mem src_buffer, cl_mem dst_buffer,
2325 size_t srcoffset, size_t dstoffset, size_t size)
2326{
2327 if(!darktable.opencl->inited) return -1;
2328 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Copy Buffer to Buffer (on device)]");
2330 src_buffer, dst_buffer, srcoffset,
2331 dstoffset, size, 0, NULL, eventp);
2332 if(err != CL_SUCCESS)
2333 dt_print(DT_DEBUG_OPENCL, "[opencl copy_buffer_to_buffer] could not copy buffer on device %d: %i\n", devid, err);
2334 return err;
2335}
2336
2337int dt_opencl_read_buffer_from_device(const int devid, void *host, void *device, const size_t offset,
2338 const size_t size, const int blocking)
2339{
2340 if(!darktable.opencl->inited) return -1;
2341
2342 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Read Buffer (from device to host)]");
2343
2345 darktable.opencl->dev[devid].cmd_queue, device, blocking ? CL_TRUE : CL_FALSE, offset, size, host, 0, NULL, eventp);
2346}
2347
2348int dt_opencl_write_buffer_to_device(const int devid, void *host, void *device, const size_t offset,
2349 const size_t size, const int blocking)
2350{
2351 if(!darktable.opencl->inited) return -1;
2352
2353 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Write Buffer (from host to device)]");
2354
2356 darktable.opencl->dev[devid].cmd_queue, device, blocking ? CL_TRUE : CL_FALSE, offset, size, host, 0, NULL, eventp);
2357}
2358
2359
2360void *dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
2361{
2362 if(!darktable.opencl->inited || devid < 0) return NULL;
2363 cl_int err;
2365 darktable.opencl->dev[devid].context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, size, host, &err);
2366 if(err != CL_SUCCESS)
2368 "[opencl copy_host_to_device_constant] could not alloc buffer on device %d: %i\n", devid, err);
2369
2370 if(err == CL_SUCCESS) dt_opencl_memory_statistics(devid, dev, size, OPENCL_MEMORY_ADD);
2371
2372 return dev;
2373}
2374
2375void *dt_opencl_copy_host_to_device(const int devid, void *host, const int width, const int height,
2376 const int bpp)
2377{
2378 return dt_opencl_copy_host_to_device_rowpitch(devid, host, width, height, bpp, 0);
2379}
2380
2381void *dt_opencl_copy_host_to_device_rowpitch(const int devid, void *host, const int width, const int height,
2382 const int bpp, const int rowpitch)
2383{
2384 if(!darktable.opencl->inited || devid < 0) return NULL;
2385 cl_int err;
2386 cl_image_format fmt;
2387 // guess pixel format from bytes per pixel
2388 if(bpp == 4 * sizeof(float))
2389 fmt = (cl_image_format){ CL_RGBA, CL_FLOAT };
2390 else if(bpp == sizeof(float))
2391 fmt = (cl_image_format){ CL_R, CL_FLOAT };
2392 else if(bpp == sizeof(uint16_t))
2393 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT16 };
2394 else
2395 return NULL;
2396
2397 // TODO: if fmt = uint16_t, blow up to 4xuint16_t and copy manually!
2399 darktable.opencl->dev[devid].context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, &fmt, width, height,
2400 rowpitch, host, &err);
2401 if(err != CL_SUCCESS)
2403 "[opencl copy_host_to_device] could not alloc/copy img buffer on device %d: %i\n", devid, err);
2404
2405 if(err == CL_SUCCESS)
2406 {
2407 const size_t bytes = (size_t)(rowpitch ? rowpitch : width * bpp) * height;
2409 }
2410
2411 return dev;
2412}
2413
2414
2416{
2417 if(!darktable.opencl->inited) return;
2418
2419 // the OpenCL specs are not absolutely clear if clReleaseMemObject(NULL) is a no-op. we take care of the
2420 // case in a centralized way at this place
2421 if(IS_NULL_PTR(mem)) return;
2422
2424
2426}
2427
2428void *dt_opencl_map_buffer(const int devid, cl_mem buffer, const int blocking, const int flags, size_t offset,
2429 size_t size)
2430{
2431 if(!darktable.opencl->inited) return NULL;
2432 cl_int err;
2433 void *ptr;
2434 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Map Buffer]");
2436 darktable.opencl->dev[devid].cmd_queue, buffer, blocking ? CL_TRUE : CL_FALSE, flags, offset, size, 0, NULL, eventp, &err);
2437 if(err != CL_SUCCESS) dt_print(DT_DEBUG_OPENCL, "[opencl map buffer] could not map buffer on device %d: %i\n", devid, err);
2438 return ptr;
2439}
2440
2441
2442void *dt_opencl_map_image(const int devid, cl_mem buffer, const int blocking, const int flags, size_t width, size_t height, int bpp)
2443{
2444 if(!darktable.opencl->inited) return NULL;
2445 cl_int err;
2446 void *ptr;
2447 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Map Image 2D]");
2448 size_t origin[3] = {0, 0, 0};
2449 size_t region[3] = {width, height, 1};
2450 size_t mapped_row_pitch;
2451
2453 darktable.opencl->dev[devid].cmd_queue, buffer, blocking ? CL_TRUE : CL_FALSE, flags, origin, region,
2454 &mapped_row_pitch, NULL, 0, NULL, eventp, &err);
2455
2456 if(err != CL_SUCCESS)
2457 dt_print(DT_DEBUG_OPENCL, "[opencl map buffer] could not map image on device %d: %i\n", devid, err);
2458 return ptr;
2459}
2460
2461
2462int dt_opencl_unmap_mem_object(const int devid, cl_mem mem_object, void *mapped_ptr)
2463{
2464 if(!darktable.opencl->inited) return -1;
2465 cl_event *eventp = dt_opencl_events_get_slot(devid, "[Unmap Mem Object]");
2467 darktable.opencl->dev[devid].cmd_queue, mem_object, mapped_ptr, 0, NULL, eventp);
2468 if(err != CL_SUCCESS)
2469 dt_print(DT_DEBUG_OPENCL, "[opencl unmap mem object] could not unmap mem object on device %d: %i\n", devid, err);
2470 return err;
2471}
2472
2473static inline void *_dt_opencl_alloc_image2d(const int devid, const int width, const int height,
2474 const size_t bytes, const cl_mem_flags flags,
2475 const cl_image_format fmt, void *host,
2476 const char *const context)
2477{
2478 if(!darktable.opencl->inited || devid < 0) return NULL;
2479 cl_int err;
2480 cl_mem dev = NULL;
2481 for(int attempt = 0; attempt < 2; attempt++)
2482 {
2484 &fmt, width, height, 0, host, &err);
2485 if(err == CL_SUCCESS) break;
2486 if(attempt == 0 && (err == CL_MEM_OBJECT_ALLOCATION_FAILURE || err == CL_OUT_OF_RESOURCES))
2487 {
2489 "[opencl %s] out of memory on device %d, flushing cached pinned buffers and retrying\n",
2490 context, devid);
2492 continue;
2493 }
2494 break;
2495 }
2496
2497 if(err != CL_SUCCESS)
2498 dt_print(DT_DEBUG_OPENCL, "[opencl %s] could not alloc img buffer on device %d: %i\n", context, devid, err);
2499
2500 if(err == CL_SUCCESS) dt_opencl_memory_statistics(devid, dev, bytes, OPENCL_MEMORY_ADD);
2501 return dev;
2502}
2503
2504void *dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
2505{
2506 const int effective_bpp = DT_OPENCL_BPP_DECODE(bpp);
2507 const gboolean rgba8 = DT_OPENCL_BPP_IS_RGBA8(bpp);
2508 cl_image_format fmt;
2509 // guess pixel format from bytes per pixel (+ optional format tag for ambiguous 4-byte formats)
2510 if(rgba8 && effective_bpp == 4 * sizeof(uint8_t))
2511 fmt = (cl_image_format){ CL_RGBA, CL_UNSIGNED_INT8 };
2512 else if(effective_bpp == 4 * sizeof(float))
2513 fmt = (cl_image_format){ CL_RGBA, CL_FLOAT };
2514 else if(effective_bpp == sizeof(float))
2515 fmt = (cl_image_format){ CL_R, CL_FLOAT };
2516 else if(effective_bpp == sizeof(uint16_t))
2517 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT16 };
2518 else if(effective_bpp == sizeof(uint8_t))
2519 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT8 };
2520 else
2521 return NULL;
2522
2523 const size_t bytes = (size_t)width * height * effective_bpp;
2524 return _dt_opencl_alloc_image2d(devid, width, height, bytes, CL_MEM_READ_WRITE, fmt, NULL, "alloc_device");
2525}
2526
2527void *dt_opencl_alloc_device_use_host_pointer(const int devid, const int width, const int height,
2528 const int bpp, void *host, const int flags)
2529{
2530 const int effective_bpp = DT_OPENCL_BPP_DECODE(bpp);
2531 const gboolean rgba8 = DT_OPENCL_BPP_IS_RGBA8(bpp);
2532 cl_image_format fmt;
2533 // guess pixel format from bytes per pixel (+ optional format tag for ambiguous 4-byte formats)
2534 if(rgba8 && effective_bpp == 4 * sizeof(uint8_t))
2535 fmt = (cl_image_format){ CL_RGBA, CL_UNSIGNED_INT8 };
2536 else if(effective_bpp == 4 * sizeof(float))
2537 fmt = (cl_image_format){ CL_RGBA, CL_FLOAT };
2538 else if(effective_bpp == sizeof(float))
2539 fmt = (cl_image_format){ CL_R, CL_FLOAT };
2540 else if(effective_bpp == sizeof(uint16_t))
2541 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT16 };
2542 else
2543 return NULL;
2544
2545 const size_t bytes = (size_t)width * height * effective_bpp;
2546 return _dt_opencl_alloc_image2d(devid, width, height, bytes, flags, fmt, host,
2547 "alloc_device_use_host_pointer");
2548}
2549
2550void *dt_opencl_alloc_device_buffer_with_flags(const int devid, const size_t size, const int flags, void *host_ptr)
2551{
2552 if(!darktable.opencl->inited) return NULL;
2553 cl_int err;
2554 cl_mem buf = NULL;
2555 for(int attempt = 0; attempt < 2; attempt++)
2556 {
2558 flags, size, host_ptr, &err);
2559 if(err == CL_SUCCESS) break;
2560 if(attempt == 0 && (err == CL_MEM_OBJECT_ALLOCATION_FAILURE || err == CL_OUT_OF_RESOURCES))
2561 {
2563 "[opencl alloc_device_buffer] out of memory on device %d, flushing cached pinned buffers and retrying\n",
2564 devid);
2566 continue;
2567 }
2568 break;
2569 }
2570 if(err != CL_SUCCESS)
2571 dt_print(DT_DEBUG_OPENCL, "[opencl alloc_device_buffer] could not alloc buffer on device %d: %d\n", devid,
2572 err);
2573
2574 if(err == CL_SUCCESS) dt_opencl_memory_statistics(devid, buf, size, OPENCL_MEMORY_ADD);
2575
2576 return buf;
2577}
2578
2579
2580void *dt_opencl_alloc_device_buffer(const int devid, const size_t size)
2581{
2582 return dt_opencl_alloc_device_buffer_with_flags(devid, size, CL_MEM_READ_WRITE, NULL);
2583}
2584
2585
2587{
2588 size_t size;
2589 if(IS_NULL_PTR(mem)) return 0;
2590
2591 cl_int err = (darktable.opencl->dlocl->symbols->dt_clGetMemObjectInfo)(mem, CL_MEM_SIZE, sizeof(size), &size, NULL);
2592
2593 return (err == CL_SUCCESS) ? size : 0;
2594}
2595
2597{
2598 cl_context context;
2599 if(IS_NULL_PTR(mem)) return -1;
2600
2601 cl_int err = (darktable.opencl->dlocl->symbols->dt_clGetMemObjectInfo)(mem, CL_MEM_CONTEXT, sizeof(context), &context, NULL);
2602 if(err != CL_SUCCESS)
2603 return -1;
2604
2605 for(int devid = 0; devid < darktable.opencl->num_devs; devid++)
2606 {
2607 if(darktable.opencl->dev[devid].context == context)
2608 return devid;
2609 }
2610
2611 return -1;
2612}
2613
2614cl_mem_flags dt_opencl_get_mem_flags(cl_mem mem)
2615{
2616 if(!darktable.opencl->inited || IS_NULL_PTR(mem)) return 0;
2617 cl_mem_flags flags = 0;
2618 cl_int err = (darktable.opencl->dlocl->symbols->dt_clGetMemObjectInfo)(mem, CL_MEM_FLAGS, sizeof(flags), &flags, NULL);
2619 if(err != CL_SUCCESS) return 0;
2620 return flags;
2621}
2622
2624{
2625 size_t size;
2626 if(IS_NULL_PTR(mem)) return 0;
2627
2628 cl_int err = (darktable.opencl->dlocl->symbols->dt_clGetImageInfo)(mem, CL_IMAGE_WIDTH, sizeof(size), &size, NULL);
2629 if(size > INT_MAX) size = 0;
2630
2631 return (err == CL_SUCCESS) ? (int)size : 0;
2632}
2633
2635{
2636 size_t size;
2637 if(IS_NULL_PTR(mem)) return 0;
2638
2639 cl_int err = (darktable.opencl->dlocl->symbols->dt_clGetImageInfo)(mem, CL_IMAGE_HEIGHT, sizeof(size), &size, NULL);
2640 if(size > INT_MAX) size = 0;
2641
2642 return (err == CL_SUCCESS) ? (int)size : 0;
2643}
2644
2646{
2647 size_t size;
2648 if(IS_NULL_PTR(mem)) return 0;
2649
2650 cl_int err = (darktable.opencl->dlocl->symbols->dt_clGetImageInfo)(mem, CL_IMAGE_ELEMENT_SIZE, sizeof(size), &size,
2651 NULL);
2652 if(size > INT_MAX) size = 0;
2653
2654 return (err == CL_SUCCESS) ? (int)size : 0;
2655}
2656
2662
2663void dt_opencl_memory_statistics(int devid, cl_mem mem, size_t size, dt_opencl_memory_t action)
2664{
2665 if(IS_NULL_PTR(mem)) return;
2666
2667 if(action == OPENCL_MEMORY_ADD)
2668 {
2669 // devid and size are known at allocation time -- record them so the release
2670 // path can undo the exact same amount without querying the driver.
2671 if(devid < 0) return;
2673 rec->devid = devid;
2674 rec->size = size;
2676 // g_hash_table_insert frees the previous value (g_free) if the key already
2677 // exists, so re-inserting the same cl_mem pointer never leaks.
2678 g_hash_table_insert(darktable.opencl->mem_sizes, mem, rec);
2680 }
2681 else
2682 {
2683 // Look up what we recorded on ADD. Never ask the driver about the object here
2684 // either: on some Windows drivers clGetMemObjectInfo faults under vRAM
2685 // pressure (issues #130221119 / #130557353), aborting the process.
2687 dt_opencl_mem_record_t *rec = (dt_opencl_mem_record_t *)g_hash_table_lookup(darktable.opencl->mem_sizes, mem);
2688 if(rec)
2689 {
2690 devid = rec->devid;
2691 size = rec->size;
2692 g_hash_table_remove(darktable.opencl->mem_sizes, mem);
2693 }
2694 else
2695 {
2696 // Untracked object (allocated before this bookkeeping, or via a path that
2697 // did not register). Nothing reliable to subtract; leave the counter be.
2698 devid = -1;
2699 }
2701 }
2702
2703 if(devid < 0)
2704 return;
2705
2706 if(action == OPENCL_MEMORY_ADD)
2708 else
2711 ? (darktable.opencl->dev[devid].memory_in_use - size)
2712 : 0;
2713
2716
2719 "[opencl memory] device %d: %" G_GSIZE_FORMAT " bytes (%.1f MB) in use\n", devid, darktable.opencl->dev[devid].memory_in_use,
2720 (float)darktable.opencl->dev[devid].memory_in_use/(1024*1024));
2721}
2722
2723void dt_opencl_check_tuning(const int devid)
2724{
2726 if(!cl->inited || devid < 0) return;
2727
2728 // Apply the headroom read from this device configuration. Older configs without
2729 // a per-device key are migrated from the global default during device init.
2730 size_t headroom = cl->dev[devid].forced_headroom;
2731
2732 cl->dev[devid].used_available = MAX(0ul, cl->dev[devid].max_global_mem - headroom * 1024 * 1024);
2733
2735 "[dt_opencl_check_tuning] use %" G_GSIZE_FORMAT " MiB on device `%s' id=%i\n",
2736 cl->dev[devid].used_available / (1024 * 1024),
2737 cl->dev[devid].name, devid);
2738}
2739
2740cl_ulong dt_opencl_get_device_available(const int devid)
2741{
2742 if(!darktable.opencl->inited || devid < 0) return 0;
2743 const cl_ulong limit = darktable.opencl->dev[devid].used_available;
2744 const size_t in_use = darktable.opencl->dev[devid].memory_in_use;
2745 return (limit > in_use) ? (limit - in_use) : 0;
2746}
2747
2748static cl_ulong _opencl_get_device_memalloc(const int devid)
2749{
2750 return darktable.opencl->dev[devid].max_mem_alloc;
2751}
2752
2753cl_ulong dt_opencl_get_device_memalloc(const int devid)
2754{
2755 if(!darktable.opencl->inited || devid < 0) return 0;
2756 return _opencl_get_device_memalloc(devid);
2757}
2758
2760 const size_t height, const unsigned bpp, const float factor,
2761 const size_t overhead, size_t *needed, size_t *limit)
2762{
2763 size_t n = 0, l = 0;
2765
2767 if(!cl->inited || devid < 0)
2768 {
2769 reason = DT_OPENCL_FIT_UNINITED;
2770 }
2771 else
2772 {
2773 const size_t required = width * height * bpp;
2774 const size_t total = (size_t)ceilf((float)required * factor) + overhead;
2775
2776 if(cl->dev[devid].max_image_width < width || cl->dev[devid].max_image_height < height)
2777 {
2778 // dimension limit: compared quantities are pixel counts, not bytes -> leave n/l at 0
2779 reason = DT_OPENCL_FIT_DIMENSION;
2780 }
2781 else if(_opencl_get_device_memalloc(devid) < required)
2782 {
2783 n = required;
2784 l = _opencl_get_device_memalloc(devid);
2786 "[opencl] trying to allocate %" PRIu64 " MiB of memory while the vRAM has %" PRIu64
2787 " MiB total\n",
2788 (uint64_t)(n / (1024 * 1024)), (uint64_t)(l / (1024 * 1024)));
2790 }
2791 else if(dt_opencl_get_device_available(devid) < total)
2792 {
2793 n = total;
2796 "[opencl] trying to allocate %" PRIu64 " MiB of memory while the vRAM has %" PRIu64
2797 " MiB left\n",
2798 (uint64_t)(n / (1024 * 1024)), (uint64_t)(l / (1024 * 1024)));
2799 reason = DT_OPENCL_FIT_AVAILABLE;
2800 }
2801 }
2802
2803 if(needed) *needed = n;
2804 if(limit) *limit = l;
2805 return reason;
2806}
2807
2808gboolean dt_opencl_image_fits_device(const int devid, const size_t width, const size_t height, const unsigned bpp,
2809 const float factor, const size_t overhead)
2810{
2811 return dt_opencl_image_fits_device_reason(devid, width, height, bpp, factor, overhead, NULL, NULL)
2813}
2814
2816int dt_opencl_dev_roundup_width(int size, const int devid)
2817{
2818 const int roundup = darktable.opencl->dev[devid].clroundup_wd;
2819 return (size % roundup == 0 ? size : (size / roundup + 1) * roundup);
2820}
2821int dt_opencl_dev_roundup_height(int size, const int devid)
2822{
2823 const int roundup = darktable.opencl->dev[devid].clroundup_ht;
2824 return (size % roundup == 0 ? size : (size / roundup + 1) * roundup);
2825}
2826
2829{
2830 return darktable.opencl->inited;
2831}
2832
2833
2836{
2837 if(!darktable.opencl->inited) return FALSE;
2838 return darktable.opencl->enabled;
2839}
2840
2841
2844{
2845 if(!darktable.opencl->inited) return;
2847 dt_conf_set_bool("opencl", FALSE);
2848}
2849
2850
2853{
2855 // FIXME: This pulls in prefs every time the pixelpipe runs. Instead have a callback for DT_SIGNAL_PREFERENCES_CHANGE?
2856 if(!cl->inited) return FALSE;
2857 const int prefs = dt_conf_get_bool("opencl");
2858
2859 if(cl->enabled != prefs)
2860 {
2861 cl->enabled = prefs;
2862 cl->stopped = 0;
2863 cl->error_count = 0;
2864 dt_print(DT_DEBUG_OPENCL, "[opencl_update_enabled] enabled flag set to %s\n", prefs ? "ON" : "OFF");
2865 }
2866
2867 return (cl->enabled && !cl->stopped);
2868}
2869
2870
2873{
2875 dt_print_nts(DT_DEBUG_OPENCL, "[opencl_synchronization_timeout] synchronization timeout set to %d\n", value);
2876}
2877
2886
2887
2891cl_event *dt_opencl_events_get_slot(const int devid, const char *tag)
2892{
2894 if(!cl->inited || devid < 0) return NULL;
2895 if(!cl->dev[devid].use_events) return NULL;
2896
2897 static const cl_event zeroevent[1]; // implicitly initialized to zero
2898 cl_event **eventlist = &(cl->dev[devid].eventlist);
2899 dt_opencl_eventtag_t **eventtags = &(cl->dev[devid].eventtags);
2900 int *numevents = &(cl->dev[devid].numevents);
2901 int *maxevents = &(cl->dev[devid].maxevents);
2902 int *eventsconsolidated = &(cl->dev[devid].eventsconsolidated);
2903 int *lostevents = &(cl->dev[devid].lostevents);
2904 int *totalevents = &(cl->dev[devid].totalevents);
2905 int *totallost = &(cl->dev[devid].totallost);
2906 int *maxeventslot = &(cl->dev[devid].maxeventslot);
2907 // if first time called: allocate initial buffers
2908 if(IS_NULL_PTR(*eventlist))
2909 {
2910 int newevents = DT_OPENCL_EVENTLISTSIZE;
2911 *eventlist = calloc(newevents, sizeof(cl_event));
2912 *eventtags = calloc(newevents, sizeof(dt_opencl_eventtag_t));
2913 if(!*eventlist || !*eventtags)
2914 {
2915 dt_free(*eventlist);
2916 dt_free(*eventtags);
2917 *eventlist = NULL;
2918 *eventtags = NULL;
2919 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_events_get_slot] NO eventlist for device %i\n", devid);
2920 return NULL;
2921 }
2922 *maxevents = newevents;
2923 }
2924
2925 // check if currently highest event slot was actually consumed. If not use it again
2926 if(*numevents > 0 && !memcmp((*eventlist) + *numevents - 1, zeroevent, sizeof(cl_event)))
2927 {
2928 (*lostevents)++;
2929 (*totallost)++;
2930 if(!IS_NULL_PTR(tag))
2931 {
2932 g_strlcpy((*eventtags)[*numevents - 1].tag, tag, DT_OPENCL_EVENTNAMELENGTH);
2933 }
2934 else
2935 {
2936 (*eventtags)[*numevents - 1].tag[0] = '\0';
2937 }
2938
2939 (*totalevents)++;
2940 return (*eventlist) + *numevents - 1;
2941 }
2942
2943 // check if we would exceed the number of available event handles. In that case first flush existing handles
2944 if((*numevents - *eventsconsolidated + 1 > cl->dev[devid].event_handles) || (*numevents == *maxevents))
2945 (void)dt_opencl_events_flush(devid, 0);
2946
2947 // if no more space left in eventlist: grow buffer
2948 if(*numevents == *maxevents)
2949 {
2950 int newevents = *maxevents + DT_OPENCL_EVENTLISTSIZE;
2951 cl_event *neweventlist = calloc(newevents, sizeof(cl_event));
2952 dt_opencl_eventtag_t *neweventtags = calloc(newevents, sizeof(dt_opencl_eventtag_t));
2953 if(!neweventlist || IS_NULL_PTR(neweventtags))
2954 {
2955 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_events_get_slot] NO new eventlist with size %i for device %i\n",
2956 newevents, devid);
2957 dt_free(neweventlist);
2958 dt_free(neweventtags);
2959 return NULL;
2960 }
2961 memcpy(neweventlist, *eventlist, sizeof(cl_event) * *maxevents);
2962 memcpy(neweventtags, *eventtags, sizeof(dt_opencl_eventtag_t) * *maxevents);
2963 dt_free(*eventlist);
2964 dt_free(*eventtags);
2965 *eventlist = neweventlist;
2966 *eventtags = neweventtags;
2967 *maxevents = newevents;
2968 }
2969
2970 // init next event slot and return it
2971 (*numevents)++;
2972 memcpy((*eventlist) + *numevents - 1, zeroevent, sizeof(cl_event));
2973 if(!IS_NULL_PTR(tag))
2974 {
2975 g_strlcpy((*eventtags)[*numevents - 1].tag, tag, DT_OPENCL_EVENTNAMELENGTH);
2976 }
2977 else
2978 {
2979 (*eventtags)[*numevents - 1].tag[0] = '\0';
2980 }
2981
2982 (*totalevents)++;
2983 *maxeventslot = MAX(*maxeventslot, *numevents - 1);
2984 return (*eventlist) + *numevents - 1;
2985}
2986
2987
2989void dt_opencl_events_reset(const int devid)
2990{
2992 if(!cl->inited || devid < 0) return;
2993 if(!cl->dev[devid].use_events) return;
2994
2995 cl_event **eventlist = &(cl->dev[devid].eventlist);
2996 dt_opencl_eventtag_t **eventtags = &(cl->dev[devid].eventtags);
2997 int *numevents = &(cl->dev[devid].numevents);
2998 int *maxevents = &(cl->dev[devid].maxevents);
2999 int *eventsconsolidated = &(cl->dev[devid].eventsconsolidated);
3000 int *lostevents = &(cl->dev[devid].lostevents);
3001 cl_int *summary = &(cl->dev[devid].summary);
3002
3003 if(IS_NULL_PTR(*eventlist) || *numevents == 0) return; // nothing to do
3004
3005 static const cl_event zeroevent[1]; // implicitly initialized to zero
3006
3007 // release all remaining events in eventlist, not to waste resources.
3008 // Skip NULL handles left behind by failed enqueues: releasing them is
3009 // pointless and crashes some drivers.
3010 for(int k = *eventsconsolidated; k < *numevents; k++)
3011 {
3012 if(memcmp((*eventlist) + k, zeroevent, sizeof(cl_event)))
3013 (cl->dlocl->symbols->dt_clReleaseEvent)((*eventlist)[k]);
3014 }
3015
3016 memset(*eventtags, 0, sizeof(dt_opencl_eventtag_t) * *maxevents);
3017 *numevents = 0;
3018 *eventsconsolidated = 0;
3019 *lostevents = 0;
3020 *summary = CL_COMPLETE;
3021 return;
3022}
3023
3024
3027void dt_opencl_events_wait_for(const int devid)
3028{
3030 if(!cl->inited || devid < 0) return;
3031 if(!cl->dev[devid].use_events) return;
3032
3033 static const cl_event zeroevent[1]; // implicitly initialized to zero
3034 cl_event **eventlist = &(cl->dev[devid].eventlist);
3035 int *numevents = &(cl->dev[devid].numevents);
3036 int *lostevents = &(cl->dev[devid].lostevents);
3037 int *totallost = &(cl->dev[devid].totallost);
3038 int *eventsconsolidated = &(cl->dev[devid].eventsconsolidated);
3039
3040 if(IS_NULL_PTR(*eventlist) || *numevents == 0) return; // nothing to do
3041
3042 // check if last event slot was actually used and correct numevents if needed
3043 if(!memcmp((*eventlist) + *numevents - 1, zeroevent, sizeof(cl_event)))
3044 {
3045 (*numevents)--;
3046 (*lostevents)++;
3047 (*totallost)++;
3048 }
3049
3050 if(*numevents == *eventsconsolidated) return; // nothing to do
3051
3052 assert(*numevents > *eventsconsolidated);
3053
3054 // Wait for all remaining events to terminate, skipping NULL handles. A reserved
3055 // slot can hold a NULL handle when its enqueue failed (the event is never
3056 // created, but get_slot had already counted the slot). Passing NULL to
3057 // clWaitForEvents crashes some drivers and, on those that merely return an
3058 // error, would abort a batched wait and leave the valid events that follow
3059 // un-waited-for before flush checks/releases them. We wait on each handle
3060 // individually rather than gathering them into a temporary array: a heap
3061 // allocation could fail under the very memory pressure that creates these NULL
3062 // slots, and returning early on that failure would skip the wait entirely.
3063 // Risk: might never return in case of OpenCL blocks or endless loops
3064 // TODO: run clWaitForEvents in separate thread and implement watchdog timer
3065 for(int k = *eventsconsolidated; k < *numevents; k++)
3066 {
3067 if(!memcmp((*eventlist) + k, zeroevent, sizeof(cl_event)))
3068 continue; // NULL handle from a failed enqueue
3069
3070 cl_int err = (cl->dlocl->symbols->dt_clWaitForEvents)(1, &((*eventlist)[k]));
3071 if((err != CL_SUCCESS) && (err != CL_INVALID_VALUE))
3072 dt_vprint(DT_DEBUG_OPENCL, "[dt_opencl_events_wait_for] reported %i for device %i\n",
3073 err, devid);
3074 }
3075}
3076
3077
3084cl_int dt_opencl_events_flush(const int devid, const int reset)
3085{
3087 if(!cl->inited || devid < 0) return FALSE;
3088 if(!cl->dev[devid].use_events) return FALSE;
3089
3090 cl_event **eventlist = &(cl->dev[devid].eventlist);
3091 dt_opencl_eventtag_t **eventtags = &(cl->dev[devid].eventtags);
3092 int *numevents = &(cl->dev[devid].numevents);
3093 int *eventsconsolidated = &(cl->dev[devid].eventsconsolidated);
3094 int *lostevents = &(cl->dev[devid].lostevents);
3095 int *totalsuccess = &(cl->dev[devid].totalsuccess);
3096
3097 cl_int *summary = &(cl->dev[devid].summary);
3098
3099 static const cl_event zeroevent[1]; // implicitly initialized to zero
3100
3101 if(IS_NULL_PTR(*eventlist) || *numevents == 0) return CL_COMPLETE; // nothing to do, no news is good news
3102
3103 // Wait for command queue to terminate (side effect: might adjust *numevents)
3105
3106 // now check return status and profiling data of all newly terminated events
3107 for(int k = *eventsconsolidated; k < *numevents; k++)
3108 {
3109 // A reserved slot can still hold a NULL handle when the matching enqueue
3110 // failed: OpenCL does not create the event in that case, but get_slot had
3111 // already counted the slot. Passing such a NULL handle to the driver
3112 // crashes some implementations (e.g. NVIDIA on Windows), so treat it as a
3113 // lost event and skip it.
3114 if(!memcmp((*eventlist) + k, zeroevent, sizeof(cl_event)))
3115 {
3116 (*lostevents)++;
3117 (*eventsconsolidated)++;
3118 continue;
3119 }
3120
3121 cl_int err;
3122 char *tag = (*eventtags)[k].tag;
3123 cl_int *retval = &((*eventtags)[k].retval);
3124
3125 // get return value of event
3126 err = (cl->dlocl->symbols->dt_clGetEventInfo)((*eventlist)[k], CL_EVENT_COMMAND_EXECUTION_STATUS,
3127 sizeof(cl_int), retval, NULL);
3128 if(err != CL_SUCCESS)
3129 {
3130 dt_print(DT_DEBUG_OPENCL, "[opencl_events_flush] could not get event info for '%s': %i\n",
3131 tag[0] == '\0' ? "<?>" : tag, err);
3132 }
3133 else if(*retval != CL_COMPLETE)
3134 {
3135 dt_print(DT_DEBUG_OPENCL, "[opencl_events_flush] execution of '%s' %s: %d\n",
3136 tag[0] == '\0' ? "<?>" : tag, *retval == CL_COMPLETE ? "was successful" : "failed", *retval);
3137 *summary = *retval;
3138 }
3139 else
3140 (*totalsuccess)++;
3141
3143 {
3144 // get profiling info of event (only if darktable was called with '-d perf')
3145 cl_ulong start;
3146 cl_ulong end;
3147 cl_int errs = (cl->dlocl->symbols->dt_clGetEventProfilingInfo)(
3148 (*eventlist)[k], CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &start, NULL);
3149 cl_int erre = (cl->dlocl->symbols->dt_clGetEventProfilingInfo)((*eventlist)[k], CL_PROFILING_COMMAND_END,
3150 sizeof(cl_ulong), &end, NULL);
3151 if(errs == CL_SUCCESS && erre == CL_SUCCESS)
3152 {
3153 (*eventtags)[k].timelapsed = end - start;
3154 }
3155 else
3156 {
3157 (*eventtags)[k].timelapsed = 0;
3158 (*lostevents)++;
3159 }
3160 }
3161 else
3162 (*eventtags)[k].timelapsed = 0;
3163
3164 // finally release event to be re-used by driver
3165 (cl->dlocl->symbols->dt_clReleaseEvent)((*eventlist)[k]);
3166 (*eventsconsolidated)++;
3167 }
3168
3169 cl_int result = *summary;
3170
3171 // do we want to get rid of all stored info?
3172 if(reset)
3173 {
3174 // output profiling info if wanted
3176
3177 // reset eventlist structures to empty state
3179 }
3180
3181 return result == CL_COMPLETE ? 0 : result;
3182}
3183
3184
3187void dt_opencl_events_profiling(const int devid, const int aggregated)
3188{
3190 if(!cl->inited || devid < 0) return;
3191 if(!cl->dev[devid].use_events) return;
3192
3193 cl_event **eventlist = &(cl->dev[devid].eventlist);
3194 dt_opencl_eventtag_t **eventtags = &(cl->dev[devid].eventtags);
3195 int *numevents = &(cl->dev[devid].numevents);
3196 int *eventsconsolidated = &(cl->dev[devid].eventsconsolidated);
3197 int *lostevents = &(cl->dev[devid].lostevents);
3198
3199 if(IS_NULL_PTR(*eventlist) || *numevents == 0 || IS_NULL_PTR(*eventtags) || *eventsconsolidated == 0)
3200 return; // nothing to do
3201
3202 char **tags = malloc(sizeof(char *) * (*eventsconsolidated + 1));
3203 float *timings = malloc(sizeof(float) * (*eventsconsolidated + 1));
3204 int items = 1;
3205 tags[0] = "";
3206 timings[0] = 0.0f;
3207
3208 // get profiling info and arrange it
3209 for(int k = 0; k < *eventsconsolidated; k++)
3210 {
3211 // if aggregated is TRUE, try to sum up timings for multiple runs of each kernel
3212 if(aggregated)
3213 {
3214 // linear search: this is not efficient at all but acceptable given the limited
3215 // number of events (ca. 10 - 20)
3216 int tagfound = -1;
3217 for(int i = 0; i < items; i++)
3218 {
3219 if(!strncmp(tags[i], (*eventtags)[k].tag, DT_OPENCL_EVENTNAMELENGTH))
3220 {
3221 tagfound = i;
3222 break;
3223 }
3224 }
3225
3226 if(tagfound >= 0) // tag was already detected before
3227 {
3228 // sum up timings
3229 timings[tagfound] += (*eventtags)[k].timelapsed * 1e-9;
3230 }
3231 else // tag is new
3232 {
3233 // make new entry
3234 items++;
3235 tags[items - 1] = (*eventtags)[k].tag;
3236 timings[items - 1] = (*eventtags)[k].timelapsed * 1e-9;
3237 }
3238 }
3239
3240 else // no aggregated info wanted -> arrange event by event
3241 {
3242 items++;
3243 tags[items - 1] = (*eventtags)[k].tag;
3244 timings[items - 1] = (*eventtags)[k].timelapsed * 1e-9;
3245 }
3246 }
3247
3248 // now display profiling info
3250 "[opencl_profiling] profiling device %d ('%s'):\n", devid, cl->dev[devid].name);
3251
3252 float total = 0.0f;
3253 for(int i = 1; i < items; i++)
3254 {
3255 dt_print(DT_DEBUG_OPENCL, "[opencl_profiling] spent %7.4f seconds in %s\n", (double)timings[i],
3256 tags[i][0] == '\0' ? "<?>" : tags[i]);
3257 total += timings[i];
3258 }
3259 // aggregated timing info for items without tag (if any)
3260 if(timings[0] != 0.0f)
3261 {
3262 dt_print(DT_DEBUG_OPENCL, "[opencl_profiling] spent %7.4f seconds (unallocated)\n", (double)timings[0]);
3263 total += timings[0];
3264 }
3265
3267 "[opencl_profiling] spent %7.4f seconds totally in command queue (with %d event%s missing)\n",
3268 (double)total, *lostevents, *lostevents == 1 ? "" : "s");
3269
3270 dt_free(timings);
3271 dt_free(tags);
3272
3273 return;
3274}
3275
3276static int nextpow2(int n)
3277{
3278 int k = 1;
3279 while (k < n)
3280 k <<= 1;
3281 return k;
3282}
3283
3284// utility function to calculate optimal work group dimensions for a given kernel
3285// taking device specific restrictions and local memory limitations into account
3286int dt_opencl_local_buffer_opt(const int devid, const int kernel, dt_opencl_local_buffer_t *factors)
3287{
3289 if(!cl->inited || devid < 0) return FALSE;
3290
3291 size_t maxsizes[3] = { 0 }; // the maximum dimensions for a work group
3292 size_t workgroupsize = 0; // the maximum number of items in a work group
3293 unsigned long localmemsize = 0; // the maximum amount of local memory we can use
3294 size_t kernelworkgroupsize = 0; // the maximum amount of items in work group for this kernel
3295
3296 int *blocksizex = &factors->sizex;
3297 int *blocksizey = &factors->sizey;
3298
3299 // initial values must be supplied in sizex and sizey.
3300 // we make sure that these are a power of 2 and lie within reasonable limits.
3301 *blocksizex = CLAMP(nextpow2(*blocksizex), 1, 1 << 16);
3302 *blocksizey = CLAMP(nextpow2(*blocksizey), 1, 1 << 16);
3303
3304 if(dt_opencl_get_work_group_limits(devid, maxsizes, &workgroupsize, &localmemsize) == CL_SUCCESS
3305 && dt_opencl_get_kernel_work_group_size(devid, kernel, &kernelworkgroupsize) == CL_SUCCESS)
3306 {
3307 while(maxsizes[0] < *blocksizex || maxsizes[1] < *blocksizey
3308 || localmemsize < ((factors->xfactor * (*blocksizex) + factors->xoffset) *
3309 (factors->yfactor * (*blocksizey) + factors->yoffset)) * factors->cellsize + factors->overhead
3310 || workgroupsize < (size_t)(*blocksizex) * (*blocksizey) || kernelworkgroupsize < (size_t)(*blocksizex) * (*blocksizey))
3311 {
3312 if(*blocksizex == 1 && *blocksizey == 1) return FALSE;
3313
3314 if(*blocksizex > *blocksizey)
3315 *blocksizex >>= 1;
3316 else
3317 *blocksizey >>= 1;
3318 }
3319 }
3320 else
3321 {
3322 dt_print(DT_DEBUG_OPENCL, "[dt_opencl_local_buffer_opt] can not identify resource limits for device %d\n", devid);
3323 return FALSE;
3324 }
3325
3326 return TRUE;
3327}
3328
3329
3330#endif
3331
3332// clang-format off
3333// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
3334// vim: shiftwidth=2 expandtab tabstop=2 cindent
3335// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
3336// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
dt_bilateral_cl_global_t * dt_bilateral_init_cl_global()
Definition bilateralcl.c:38
void dt_bilateral_free_cl_global(dt_bilateral_cl_global_t *b)
dt_blendop_cl_global_t * dt_develop_blend_init_cl_global(void)
Definition blend.c:1591
void dt_develop_blend_free_cl_global(dt_blendop_cl_global_t *b)
Definition blend.c:1624
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
char * key
int type
char * name
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
int dt_conf_key_exists(const char *key)
gchar * dt_conf_get_string(const char *name)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
int64_t dt_conf_get_int64(const char *name)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
void dt_conf_save(dt_conf_t *cf)
gboolean dt_conf_key_not_empty(const char *name)
void reset(dt_view_t *self)
Definition darkroom.c:1062
void dt_vprint(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1625
void dt_concat_path_file(char destination[PATH_MAX], const char path[PATH_MAX], const char *const file)
Definition darktable.c:1947
darktable_t darktable
Definition darktable.c:183
void dt_print_nts(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1613
void dt_capabilities_add(char *capability)
Definition darktable.c:1831
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1600
@ DT_DEBUG_OPENCL
Definition darktable.h:744
@ DT_DEBUG_MEMORY
Definition darktable.h:746
@ DT_DEBUG_PERF
Definition darktable.h:741
#define dt_free(ptr)
Definition darktable.h:478
static const dt_aligned_pixel_simd_t value
Definition darktable.h:599
static double dt_get_wtime(void)
Definition darktable.h:976
#define PATH_MAX
Definition darktable.h:1189
#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:293
dt_dlopencl_t * dt_dlopencl_init(const char *name)
Definition dlopencl.c:63
static int dt_pthread_mutex_BAD_trylock(dt_pthread_mutex_t *mutex)
Definition dtpthread.h:607
static int dt_pthread_mutex_BAD_unlock(dt_pthread_mutex_t *mutex)
Definition dtpthread.h:612
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:384
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Definition dtpthread.h:369
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
Definition dtpthread.h:389
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:374
dt_dwt_cl_global_t * dt_dwt_init_cl_global()
Definition dwt.c:538
void dt_dwt_free_cl_global(dt_dwt_cl_global_t *g)
Definition dwt.c:551
void dt_loc_get_user_cache_dir(char *cachedir, size_t bufsize)
void dt_loc_get_kerneldir(char *kerneldir, size_t bufsize)
const dt_collection_sort_t items[]
Definition filter.c:95
void dt_gaussian_free_cl_global(dt_gaussian_cl_global_t *g)
Definition gaussian.c:574
dt_gaussian_cl_global_t * dt_gaussian_init_cl_global()
Definition gaussian.c:341
dt_guided_filter_cl_global_t * dt_guided_filter_init_cl_global()
void dt_guided_filter_free_cl_global(dt_guided_filter_cl_global_t *g)
void dt_heal_free_cl_global(dt_heal_cl_global_t *g)
Definition heal.c:422
dt_heal_cl_global_t * dt_heal_init_cl_global()
Definition heal.c:415
int bpp
void dt_iop_nap(int32_t usec)
Definition imageop.c:2973
void dt_interpolation_free_cl_global(dt_interpolation_cl_global_t *g)
dt_interpolation_cl_global_t * dt_interpolation_init_cl_global()
static float kernel(const float *x, const float *y)
void dt_colorspaces_free_cl_global(dt_colorspaces_cl_global_t *g)
dt_colorspaces_cl_global_t * dt_colorspaces_init_cl_global()
dt_local_laplacian_cl_global_t * dt_local_laplacian_init_cl_global()
void dt_local_laplacian_free_cl_global(dt_local_laplacian_cl_global_t *g)
float *const restrict const size_t k
size_t size
Definition mipmap_cache.c:3
dt_mipmap_buffer_dsc_flags flags
Definition mipmap_cache.c:4
static int dt_nvidia_gpu_supports_sm_20(const char *model)
cl_ulong dt_opencl_get_device_available(const int devid)
Definition opencl.c:2740
int dt_opencl_get_kernel_work_group_size(const int dev, const int kernel, size_t *kernelworkgroupsize)
Definition opencl.c:2143
cl_event * dt_opencl_events_get_slot(const int devid, const char *tag)
Definition opencl.c:2891
static void * _dt_opencl_alloc_image2d(const int devid, const int width, const int height, const size_t bytes, const cl_mem_flags flags, const cl_image_format fmt, void *host, const char *const context)
Definition opencl.c:2473
int dt_opencl_local_buffer_opt(const int devid, const int kernel, dt_opencl_local_buffer_t *factors)
Definition opencl.c:3286
void dt_opencl_unlock_device(const int dev)
Definition opencl.c:1676
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2164
static void dt_opencl_update_priorities()
Definition opencl.c:1556
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
Definition opencl.c:2580
dt_opencl_fit_reason_t dt_opencl_image_fits_device_reason(const int devid, const size_t width, const size_t height, const unsigned bpp, const float factor, const size_t overhead, size_t *needed, size_t *limit)
Definition opencl.c:2759
int dt_opencl_read_host_from_device_rowpitch(const int devid, void *host, void *device, const int width, const int height, const int rowpitch)
Definition opencl.c:2203
void * dt_opencl_alloc_device_use_host_pointer(const int devid, const int width, const int height, const int bpp, void *host, const int flags)
Definition opencl.c:2527
size_t dt_opencl_get_mem_object_size(cl_mem mem)
Definition opencl.c:2586
gboolean dt_opencl_is_pinned_memory(cl_mem mem)
Definition opencl.c:190
static char * _ascii_str_canonical(const char *in, char *out, int maxlen)
Definition opencl.c:1435
void dt_opencl_cleanup_device(dt_opencl_t *cl, int i)
Definition opencl.c:1261
int dt_opencl_enqueue_copy_buffer_to_image(const int devid, cl_mem src_buffer, cl_mem dst_image, size_t offset, size_t *origin, size_t *region)
Definition opencl.c:2312
void dt_opencl_init(dt_opencl_t *cl, const gboolean exclude_opencl, const gboolean print_statistics)
Definition opencl.c:1019
void dt_opencl_events_reset(const int devid)
Definition opencl.c:2989
cl_int dt_opencl_events_flush(const int devid, const int reset)
Definition opencl.c:3084
int dt_opencl_copy_device_to_host(const int devid, void *host, void *device, const int width, const int height, const int bpp)
Definition opencl.c:2191
int dt_opencl_lock_device(const int pipetype)
Definition opencl.c:1591
gboolean dt_opencl_read_device_config(const int devid)
Definition opencl.c:246
void dt_opencl_check_tuning(const int devid)
Definition opencl.c:2723
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
Definition opencl.c:2504
int dt_opencl_is_inited(void)
Definition opencl.c:2828
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2058
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
Definition opencl.c:2360
int dt_opencl_dev_roundup_height(int size, const int devid)
Definition opencl.c:2821
void * dt_opencl_copy_host_to_device_rowpitch(const int devid, void *host, const int width, const int height, const int bpp, const int rowpitch)
Definition opencl.c:2381
int dt_opencl_write_host_to_device_rowpitch(const int devid, void *host, void *device, const int width, const int height, const int rowpitch)
Definition opencl.c:2250
int dt_opencl_dev_roundup_width(int size, const int devid)
Definition opencl.c:2816
void dt_opencl_write_device_config(const int devid)
Definition opencl.c:196
static void dt_opencl_set_synchronization_timeout(int value)
Definition opencl.c:2872
static int dt_opencl_device_init(dt_opencl_t *cl, const int dev, cl_device_id *devices, const int k)
Definition opencl.c:443
int dt_opencl_get_mem_context_id(cl_mem mem)
Definition opencl.c:2596
int dt_opencl_write_host_to_device_non_blocking(const int devid, void *host, void *device, const int width, const int height, const int bpp)
Definition opencl.c:2260
int dt_opencl_load_program(const int dev, const int prog, const char *filename, const char *binname, const char *cachedir, char *md5sum, char **includemd5, int *loaded_cached)
Definition opencl.c:1756
void * dt_opencl_map_buffer(const int devid, cl_mem buffer, const int blocking, const int flags, size_t offset, size_t size)
Definition opencl.c:2428
static void dt_opencl_apply_scheduling_profile()
Definition opencl.c:2879
static int _dt_opencl_get_conf_int(const gchar *key_device, const gchar *conf_name, gboolean *safety_ok)
Definition opencl.c:229
int dt_opencl_get_image_height(cl_mem mem)
Definition opencl.c:2634
int dt_opencl_read_host_from_device_rowpitch_non_blocking(const int devid, void *host, void *device, const int width, const int height, const int rowpitch)
Definition opencl.c:2220
int dt_opencl_write_buffer_to_device(const int devid, void *host, void *device, const size_t offset, const size_t size, const int blocking)
Definition opencl.c:2348
int dt_opencl_micro_nap(const int devid)
Definition opencl.c:177
static cl_ulong _opencl_get_device_memalloc(const int devid)
Definition opencl.c:2748
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
Definition opencl.c:2289
static int _take_from_list(int *list, int value)
Definition opencl.c:1396
int dt_opencl_set_detected_device_enabled(const int detected, const gboolean enabled)
Definition opencl.c:339
int dt_opencl_read_buffer_from_device(const int devid, void *host, void *device, const size_t offset, const size_t size, const int blocking)
Definition opencl.c:2337
int dt_opencl_build_program(const int dev, const int prog, const char *binname, const char *cachedir, char *md5sum, int loaded_cached)
Definition opencl.c:1930
int dt_opencl_get_max_work_item_sizes(const int dev, size_t *sizes)
Definition opencl.c:2115
int dt_opencl_enqueue_barrier(const int devid)
Definition opencl.c:1389
static FILE * fopen_stat(const char *filename, struct stat *st)
Definition opencl.c:1684
gboolean dt_opencl_image_fits_device(const int devid, const size_t width, const size_t height, const unsigned bpp, const float factor, const size_t overhead)
Definition opencl.c:2808
int dt_opencl_unmap_mem_object(const int devid, cl_mem mem_object, void *mapped_ptr)
Definition opencl.c:2462
int dt_opencl_read_host_from_device_raw(const int devid, void *host, void *device, const size_t *origin, const size_t *region, const int rowpitch, const int blocking)
Definition opencl.c:2232
gboolean dt_opencl_detected_device_pinned_memory(const int detected)
Definition opencl.c:371
int dt_opencl_set_detected_device_headroom(const int detected, const size_t headroom)
Definition opencl.c:417
int dt_opencl_is_enabled(void)
Definition opencl.c:2835
void dt_opencl_memory_statistics(int devid, cl_mem mem, size_t size, dt_opencl_memory_t action)
Definition opencl.c:2663
void dt_opencl_md5sum(const char **files, char **md5sums)
Definition opencl.c:1702
static int nextpow2(int n)
Definition opencl.c:3276
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2101
static gboolean _opencl_splash_active
Definition opencl.c:86
gboolean dt_opencl_use_pinned_memory(const int devid)
Definition opencl.c:183
void dt_opencl_cleanup(dt_opencl_t *cl)
Definition opencl.c:1310
int dt_opencl_get_image_width(cl_mem mem)
Definition opencl.c:2623
cl_ulong dt_opencl_get_device_memalloc(const int devid)
Definition opencl.c:2753
int dt_opencl_read_host_from_device_non_blocking(const int devid, void *host, void *device, const int width, const int height, const int bpp)
Definition opencl.c:2213
int dt_opencl_get_detected_device_count(void)
Definition opencl.c:310
void * dt_opencl_map_image(const int devid, cl_mem buffer, const int blocking, const int flags, size_t width, size_t height, int bpp)
Definition opencl.c:2442
void * dt_opencl_alloc_device_buffer_with_flags(const int devid, const size_t size, const int flags, void *host_ptr)
Definition opencl.c:2550
int dt_opencl_write_host_to_device_rowpitch_non_blocking(const int devid, void *host, void *device, const int width, const int height, const int rowpitch)
Definition opencl.c:2266
static void dt_opencl_priority_parse(dt_opencl_t *cl, char *configstr, int *priority_list, int *mandatory)
Definition opencl.c:1461
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
Definition opencl.c:2155
gboolean dt_opencl_finish(const int devid)
Definition opencl.c:1375
int dt_opencl_enqueue_copy_image_to_buffer(const int devid, cl_mem src_image, cl_mem dst_buffer, size_t *origin, size_t *region, size_t offset)
Definition opencl.c:2300
static void _opencl_splash_update_compile(const char *programname)
Definition opencl.c:88
int dt_opencl_update_settings(void)
Definition opencl.c:2852
void dt_opencl_events_wait_for(const int devid)
Definition opencl.c:3027
int dt_opencl_set_detected_device_pinned_memory(const int detected, const gboolean enabled)
Definition opencl.c:384
int dt_opencl_read_host_from_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
Definition opencl.c:2197
void dt_opencl_events_profiling(const int devid, const int aggregated)
Definition opencl.c:3187
int dt_opencl_get_work_group_limits(const int dev, size_t *sizes, size_t *workgroupsize, unsigned long *localmemsize)
Definition opencl.c:2123
int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
Definition opencl.c:2170
cl_mem_flags dt_opencl_get_mem_flags(cl_mem mem)
Definition opencl.c:2614
int dt_opencl_enqueue_copy_buffer_to_buffer(const int devid, cl_mem src_buffer, cl_mem dst_buffer, size_t srcoffset, size_t dstoffset, size_t size)
Definition opencl.c:2324
const dt_opencl_detected_device_t * dt_opencl_get_detected_device(const int detected)
Definition opencl.c:318
void * dt_opencl_copy_host_to_device(const int devid, void *host, const int width, const int height, const int bpp)
Definition opencl.c:2375
int dt_opencl_write_host_to_device_raw(const int devid, const void *host, void *device, const size_t *origin, const size_t *region, const int rowpitch, const int blocking)
Definition opencl.c:2277
size_t dt_opencl_detected_device_headroom(const int detected)
Definition opencl.c:405
void dt_opencl_release_mem_object(cl_mem mem)
Definition opencl.c:2415
static int _device_by_cname(const char *name)
Definition opencl.c:1413
int dt_opencl_get_image_element_size(cl_mem mem)
Definition opencl.c:2645
gboolean dt_opencl_detected_device_enabled(const int detected)
Definition opencl.c:326
static const char * dt_opencl_get_vendor_by_id(unsigned int id)
Definition opencl.c:1353
int dt_opencl_get_device_info(dt_opencl_t *cl, cl_device_id device, cl_device_info param_name, void **param_value, size_t *param_value_size)
Definition opencl.c:114
int dt_opencl_avoid_atomics(const int devid)
Definition opencl.c:171
int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
Definition opencl.c:2244
void dt_opencl_disable(void)
Definition opencl.c:2843
#define DT_OPENCL_MAX_INCLUDES
Definition opencl.h:50
dt_opencl_memory_t
Definition opencl.h:96
@ OPENCL_MEMORY_ADD
Definition opencl.h:97
@ OPENCL_MEMORY_SUB
Definition opencl.h:98
#define DT_OPENCL_EVENTLISTSIZE
Definition opencl.h:47
#define DT_OPENCL_BPP_DECODE(bpp)
Definition opencl.h:87
@ DT_OPENCL_PINNING_DISABLED
Definition opencl.h:115
@ DT_OPENCL_PINNING_OFF
Definition opencl.h:113
@ DT_OPENCL_PINNING_ON
Definition opencl.h:114
dt_opencl_fit_reason_t
Definition opencl.h:123
@ DT_OPENCL_FIT_ALLOC_LIMIT
Definition opencl.h:126
@ DT_OPENCL_FIT_AVAILABLE
Definition opencl.h:127
@ DT_OPENCL_FIT_DIMENSION
Definition opencl.h:125
@ DT_OPENCL_FIT_UNINITED
Definition opencl.h:128
@ DT_OPENCL_FIT_OK
Definition opencl.h:124
#define DT_OPENCL_DEFAULT_COMPILE
Definition opencl.h:92
#define DT_OPENCL_DEFAULT_COMPILE_INTEL
Definition opencl.h:89
#define DT_OPENCL_BPP_IS_RGBA8(bpp)
Definition opencl.h:86
#define DT_OPENCL_CBUFFSIZE
Definition opencl.h:54
#define DT_OPENCL_EVENTNAMELENGTH
Definition opencl.h:48
#define DT_OPENCL_VENDOR_INTEL
Definition opencl.h:53
#define DT_OPENCL_MAX_PROGRAMS
Definition opencl.h:45
#define DT_OPENCL_MAX_PLATFORMS
Definition opencl.h:44
#define DT_CLDEVICE_HEAD
Definition opencl.h:93
#define DT_OPENCL_DEFAULT_COMPILE_AMD
Definition opencl.h:90
#define DT_OPENCL_DEFAULT_COMPILE_NVIDIA
Definition opencl.h:91
#define DT_OPENCL_VENDOR_NVIDIA
Definition opencl.h:52
#define DT_OPENCL_VENDOR_AMD
Definition opencl.h:51
#define DT_OPENCL_MAX_KERNELS
Definition opencl.h:46
static gboolean dt_opencl_check_driver_blacklist(const char *device_version)
const float factor
Definition pdf.h:90
@ DT_DEV_PIXELPIPE_THUMBNAIL
Definition pixelpipe.h:41
@ DT_DEV_PIXELPIPE_EXPORT
Definition pixelpipe.h:38
@ DT_DEV_PIXELPIPE_PREVIEW
Definition pixelpipe.h:40
@ DT_DEV_PIXELPIPE_FULL
Definition pixelpipe.h:39
void dt_dev_pixelpipe_cache_flush_clmem(dt_dev_pixelpipe_cache_t *cache, const int devid)
Release cached OpenCL buffers for a single device.
Pixelpipe cache for storing intermediate results in the pixelpipe.
void dt_gui_splash_init(void)
Definition splash.c:509
void dt_gui_splash_updatef(const char *format,...)
Definition splash.c:684
unsigned __int64 uint64_t
Definition strptime.c:75
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:818
struct dt_gui_gtk_t * gui
Definition darktable.h:803
struct dt_opencl_t * opencl
Definition darktable.h:813
int32_t unmuted
Definition darktable.h:788
struct dt_conf_t * conf
Definition darktable.h:797
dt_clEnqueueReadImage_t dt_clEnqueueReadImage
Definition dlopencl.h:210
dt_clGetEventInfo_t dt_clGetEventInfo
Definition dlopencl.h:195
dt_clReleaseCommandQueue_t dt_clReleaseCommandQueue
Definition dlopencl.h:162
dt_clEnqueueUnmapMemObject_t dt_clEnqueueUnmapMemObject
Definition dlopencl.h:217
dt_clGetKernelInfo_t dt_clGetKernelInfo
Definition dlopencl.h:192
dt_clGetEventProfilingInfo_t dt_clGetEventProfilingInfo
Definition dlopencl.h:201
dt_clCreateCommandQueue_t dt_clCreateCommandQueue
Definition dlopencl.h:160
dt_clCreateImage2D_t dt_clCreateImage2D
Definition dlopencl.h:167
dt_clEnqueueCopyBuffer_t dt_clEnqueueCopyBuffer
Definition dlopencl.h:208
dt_clGetPlatformInfo_t dt_clGetPlatformInfo
Definition dlopencl.h:152
dt_clBuildProgram_t dt_clBuildProgram
Definition dlopencl.h:183
dt_clEnqueueWriteBuffer_t dt_clEnqueueWriteBuffer
Definition dlopencl.h:206
dt_clCreateContext_t dt_clCreateContext
Definition dlopencl.h:155
dt_clGetDeviceIDs_t dt_clGetDeviceIDs
Definition dlopencl.h:153
dt_clGetMemObjectInfo_t dt_clGetMemObjectInfo
Definition dlopencl.h:172
dt_clEnqueueCopyImage_t dt_clEnqueueCopyImage
Definition dlopencl.h:212
dt_clReleaseContext_t dt_clReleaseContext
Definition dlopencl.h:158
dt_clFinish_t dt_clFinish
Definition dlopencl.h:203
dt_clGetDeviceInfo_t dt_clGetDeviceInfo
Definition dlopencl.h:154
dt_clEnqueueCopyImageToBuffer_t dt_clEnqueueCopyImageToBuffer
Definition dlopencl.h:213
dt_clGetImageInfo_t dt_clGetImageInfo
Definition dlopencl.h:173
dt_clCreateBuffer_t dt_clCreateBuffer
Definition dlopencl.h:165
dt_clCreateProgramWithBinary_t dt_clCreateProgramWithBinary
Definition dlopencl.h:180
dt_clReleaseKernel_t dt_clReleaseKernel
Definition dlopencl.h:190
dt_clEnqueueWriteImage_t dt_clEnqueueWriteImage
Definition dlopencl.h:211
dt_clSetKernelArg_t dt_clSetKernelArg
Definition dlopencl.h:191
dt_clReleaseEvent_t dt_clReleaseEvent
Definition dlopencl.h:198
dt_clEnqueueMapImage_t dt_clEnqueueMapImage
Definition dlopencl.h:216
dt_clEnqueueBarrier_t dt_clEnqueueBarrier
Definition dlopencl.h:223
dt_clGetPlatformIDs_t dt_clGetPlatformIDs
Definition dlopencl.h:151
dt_clGetProgramInfo_t dt_clGetProgramInfo
Definition dlopencl.h:185
dt_clGetKernelWorkGroupInfo_t dt_clGetKernelWorkGroupInfo
Definition dlopencl.h:193
dt_clReleaseMemObject_t dt_clReleaseMemObject
Definition dlopencl.h:170
dt_clGetProgramBuildInfo_t dt_clGetProgramBuildInfo
Definition dlopencl.h:186
dt_clReleaseProgram_t dt_clReleaseProgram
Definition dlopencl.h:182
dt_clEnqueueNDRangeKernel_t dt_clEnqueueNDRangeKernel
Definition dlopencl.h:218
dt_clWaitForEvents_t dt_clWaitForEvents
Definition dlopencl.h:194
dt_clEnqueueReadBuffer_t dt_clEnqueueReadBuffer
Definition dlopencl.h:204
dt_clEnqueueCopyBufferToImage_t dt_clEnqueueCopyBufferToImage
Definition dlopencl.h:214
dt_clEnqueueMapBuffer_t dt_clEnqueueMapBuffer
Definition dlopencl.h:215
dt_clCreateKernel_t dt_clCreateKernel
Definition dlopencl.h:187
dt_clCreateProgramWithSource_t dt_clCreateProgramWithSource
Definition dlopencl.h:179
dt_dlopencl_symbols_t * symbols
Definition dlopencl.h:231
char * library
Definition dlopencl.h:232
size_t forced_headroom
Definition opencl.h:228
gboolean host_unified_memory
Definition opencl.h:224
unsigned int cltype
Definition opencl.h:201
const char * name
Definition opencl.h:162
size_t used_available
Definition opencl.h:169
cl_event * eventlist
Definition opencl.h:150
cl_command_queue cmd_queue
Definition opencl.h:140
cl_context context
Definition opencl.h:139
const char * options_md5
Definition opencl.h:165
cl_ulong max_mem_alloc
Definition opencl.h:143
cl_ulong max_global_mem
Definition opencl.h:144
size_t max_image_width
Definition opencl.h:141
cl_ulong used_global_mem
Definition opencl.h:145
cl_device_id devid
Definition opencl.h:138
int program_used[256]
Definition opencl.h:148
dt_pthread_mutex_t lock
Definition opencl.h:137
size_t peak_memory
Definition opencl.h:168
cl_kernel kernel[512]
Definition opencl.h:147
int kernel_used[512]
Definition opencl.h:149
size_t max_image_height
Definition opencl.h:142
cl_program program[256]
Definition opencl.h:146
size_t memory_in_use
Definition opencl.h:167
const char * vendor
Definition opencl.h:161
dt_opencl_eventtag_t * eventtags
Definition opencl.h:151
const char * options
Definition opencl.h:164
const char * cname
Definition opencl.h:163
const size_t cellsize
Definition opencl.h:320
const size_t overhead
Definition opencl.h:321
int num_devs
Definition opencl.h:263
int print_statistics
Definition opencl.h:260
struct dt_gaussian_cl_global_t * gaussian
Definition opencl.h:284
int * dev_priority_image
Definition opencl.h:269
int error_count
Definition opencl.h:265
int opencl_synchronization_timeout
Definition opencl.h:266
int * dev_priority_preview
Definition opencl.h:270
dt_opencl_device_t * dev
Definition opencl.h:273
GHashTable * mem_sizes
Definition opencl.h:307
struct dt_bilateral_cl_global_t * bilateral
Definition opencl.h:281
int stopped
Definition opencl.h:262
struct dt_colorspaces_cl_global_t * colorspaces
Definition opencl.h:299
struct dt_guided_filter_cl_global_t * guided_filter
Definition opencl.h:302
int enabled
Definition opencl.h:261
struct dt_interpolation_cl_global_t * interpolation
Definition opencl.h:287
struct dt_local_laplacian_cl_global_t * local_laplacian
Definition opencl.h:290
int mandatory[5]
Definition opencl.h:268
dt_pthread_mutex_t lock
Definition opencl.h:258
struct dt_blendop_cl_global_t * blendop
Definition opencl.h:278
struct dt_dwt_cl_global_t * dwt
Definition opencl.h:293
int * dev_priority_export
Definition opencl.h:271
int inited
Definition opencl.h:259
dt_pthread_mutex_t mem_sizes_lock
Definition opencl.h:308
dt_opencl_detected_device_t * detected_devs
Definition opencl.h:274
dt_dlopencl_t * dlocl
Definition opencl.h:275
int num_detected_devs
Definition opencl.h:264
int * dev_priority_thumbnail
Definition opencl.h:272
uint32_t crc
Definition opencl.h:267
struct dt_heal_cl_global_t * heal
Definition opencl.h:296
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29
gchar * dt_util_str_replace(const gchar *string, const gchar *pattern, const gchar *substitute)
Definition utility.c:136