115 size_t *param_value_size)
117 *param_value_size = SIZE_MAX;
121 if(err != CL_SUCCESS)
124 "[dt_opencl_get_device_info] could not query the actual size in bytes of info %d: %i\n", param_name, err);
129 if(*param_value_size == SIZE_MAX || *param_value_size == 0)
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;
141 void *ptr = realloc(*param_value, *param_value_size);
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;
157 if(err != CL_SUCCESS)
167 *param_value_size = 0;
193 return (
flags & CL_MEM_USE_HOST_PTR) || (
flags & CL_MEM_ALLOC_HOST_PTR);
198 if(devid < 0)
return;
200 gchar buf[256] = { 0 };
201 gchar key_device[256] = { 0 };
204 g_snprintf(buf,
sizeof(buf),
"%s/avoid_atomics", key_device);
207 g_snprintf(buf,
sizeof(buf),
"%s/micro_nap", key_device);
210 g_snprintf(buf,
sizeof(buf),
"%s/pinned_memory", key_device);
213 g_snprintf(buf,
sizeof(buf),
"%s/wd", key_device);
216 g_snprintf(buf,
sizeof(buf),
"%s/ht", key_device);
219 g_snprintf(buf,
sizeof(buf),
"%s/event_handles", key_device);
222 g_snprintf(buf,
sizeof(buf),
"%s/disabled", key_device);
225 g_snprintf(buf,
sizeof(buf),
"%s/id%i/forced_headroom", key_device, devid);
232 gchar *
key = g_strconcat(key_device,
"/", conf_name, NULL);
248 if(devid < 0)
return FALSE;
250 gchar key_device[256] = { 0 };
252 gboolean safety_ok =
TRUE;
263 safety_ok |= (wd > 1) && (wd < 513) && (ht > 1) && (ht < 513);
329 gchar
key[256] = { 0 };
342 gchar
key[256] = { 0 };
350 gboolean opencl_enabled = enabled;
355 for(
int dev = 0; dev < cl->num_detected_devs; dev++)
359 opencl_enabled =
TRUE;
374 gchar
key[256] = { 0 };
387 gchar
key[256] = { 0 };
403 gchar
key[256] = { 0 };
415 gchar
key[256] = { 0 };
418 const int clamped_headroom = (int)
MIN(headroom, (
size_t)G_MAXINT);
431 gboolean lock_initialized =
FALSE;
471 cl_device_id devid = cl->
dev[dev].
devid = devices[
k];
473 char *infostr = NULL;
482 char *driverversion = NULL;
483 size_t driverversion_size;
485 char *deviceversion = NULL;
486 size_t deviceversion_size;
489 size_t *infointtab = NULL;
491 cl_bool image_support = 0;
492 cl_bool device_available = 0;
493 cl_uint vendor_id = 0;
494 cl_bool little_endian = 0;
495 cl_platform_id platform_id = 0;
497 char *dtcache = calloc(
PATH_MAX,
sizeof(
char));
498 char *cachedir = calloc(
PATH_MAX,
sizeof(
char));
505 char *filename = calloc(
PATH_MAX,
sizeof(
char));
506 char *confentry = calloc(
PATH_MAX,
sizeof(
char));
507 char *binname = calloc(
PATH_MAX,
sizeof(
char));
514 if(err != CL_SUCCESS)
524 if(err != CL_SUCCESS)
532 cname_size = infostr_size;
533 cname = malloc(cname_size);
535 cl->
dev[dev].
name = strdup(infostr);
539 cl->
crc = crc32(cl->
crc, (
const unsigned char *)infostr, strlen(infostr));
542 if(err != CL_SUCCESS)
551 if(err != CL_SUCCESS)
558 if(err != CL_SUCCESS)
571 if(err != CL_SUCCESS)
580 if(err != CL_SUCCESS)
589 cl->
crc = crc32(cl->
crc, (
const unsigned char *)deviceversion, deviceversion_size);
604 if(!strncasecmp(vendor,
"NVIDIA", 6))
611 const gboolean is_cpu_device = (
type & CL_DEVICE_TYPE_CPU) == CL_DEVICE_TYPE_CPU;
621 ((
type & CL_DEVICE_TYPE_CPU) == CL_DEVICE_TYPE_CPU) ?
"CPU" :
"",
622 ((
type & CL_DEVICE_TYPE_GPU) == CL_DEVICE_TYPE_GPU) ?
"GPU" :
"",
623 (
type & CL_DEVICE_TYPE_ACCELERATOR) ?
", Accelerator" :
"" );
625 if(is_cpu_device && newdevice)
633 if(!device_available)
672 if(newdevice && is_blacklisted)
675 const gboolean old_blacklist =
dt_conf_get_bool(
"opencl_disable_drivers_blacklist");
691 size_t infointtab_size;
693 if(err == CL_SUCCESS)
718 if(
type & CL_DEVICE_TYPE_GPU)
746 lock_initialized =
TRUE;
749 if(err != CL_SUCCESS)
758 if(err != CL_SUCCESS)
768 double tstart, tend, tdiff;
771 int len =
MIN(strlen(infostr),1024 *
sizeof(
char));;
774 for(
int i = 0;
i < len;
i++)
775 if(isalnum(infostr[
i])) devname[j++] = infostr[
i];
777 len =
MIN(strlen(driverversion), 1024 *
sizeof(
char));
780 for(
int i = 0;
i < len;
i++)
781 if(isalnum(driverversion[
i])) drvversion[j++] = driverversion[
i];
783 snprintf(cachedir,
PATH_MAX *
sizeof(
char),
"%s" G_DIR_SEPARATOR_S
"cached_kernels_for_%s_%s", dtcache, devname, drvversion);
787 if(g_mkdir_with_parents(cachedir, 0700) == -1)
796 char *escapedkerneldir = NULL;
798 escapedkerneldir = g_strdup_printf(
"\"%s\"", kerneldir);
804 const char* compile_opt = NULL;
825 gchar *my_option = g_strdup(compile_opt);
828 cl->
dev[dev].
options = g_strdup_printf(
"-w %s %s -D%s=1 -I%s",
833 const char *kerneldir_token =
"<ansel-kernels>";
834 char *escapedkerneldir_md5 = NULL;
836 escapedkerneldir_md5 = g_strdup_printf(
"\"%s\"", kerneldir_token);
838 escapedkerneldir_md5 = g_strdup(kerneldir_token);
840 cl->
dev[dev].
options_md5 = g_strdup_printf(
"-w %s %s -D%s=1 -I%s",
847 dt_free(compile_option_name_cname);
851 escapedkerneldir = NULL;
853 const char *clincludes[
DT_OPENCL_MAX_INCLUDES] = {
"rgb_norms.h",
"noise_generator.h",
"color_conversion.h",
"colorspaces.cl",
"colorspace.h",
"common.h", NULL };
866 FILE *
f = g_fopen(filename,
"rb");
872 gchar *confline_pattern = g_strdup_printf(
"%%%" G_GSIZE_FORMAT
"[^\n]\n",
PATH_MAX *
sizeof(
char) - 1);
873 int rd = fscanf(
f, confline_pattern, confentry);
875 if(rd != 1)
continue;
877 size_t end = strlen(confentry);
878 for(
size_t pos = 0; pos < end; pos++)
879 if(confentry[pos] ==
'#')
881 confentry[pos] =
'\0';
882 for(
int l = pos - 1; l >= 0; l--)
884 if(confentry[l] ==
' ')
891 if(confentry[0] ==
'\0')
continue;
893 const char *programname = NULL, *programnumber = NULL;
894 gchar **tokens = g_strsplit_set(confentry,
" \t", 2);
897 programname = tokens[0];
899 programnumber = tokens[1];
902 prog = programnumber ? strtol(programnumber, NULL, 10) : -1;
904 if(
IS_NULL_PTR(programname) || programname[0] ==
'\0' || prog < 0)
906 dt_print(
DT_DEBUG_OPENCL,
"[dt_opencl_device_init] malformed entry in programs.conf `%s'; ignoring it!\n", confentry);
910 gchar *program_bin = g_strdup_printf(
"%s.bin", programname);
937 tdiff = tend - tstart;
1010 char *locale = strdup(setlocale(LC_ALL, NULL));
1011 setlocale(LC_ALL,
"C");
1022 if(exclude_opencl)
return;
1024 cl_platform_id *all_platforms = NULL;
1025 cl_uint *all_num_devices = NULL;
1042 "[opencl_init] no working opencl library found. Continue with opencl disabled\n");
1056 if(err != CL_SUCCESS)
1062 if(num_platforms == 0)
1068 num_platforms > 1 ?
"s" :
"");
1070 for(
int n = 0;
n < num_platforms;
n++)
1072 cl_platform_id platform = all_platforms[
n];
1076 if(err != CL_SUCCESS)
1080 if((errn == CL_SUCCESS) && (errv == CL_SUCCESS))
1085 all_num_devices[
n] = 0;
1089 char profile[64] = { 0 };
1090 size_t profile_size;
1092 if(err != CL_SUCCESS)
1094 all_num_devices[
n] = 0;
1100 if(strcmp(
"FULL_PROFILE", profile) != 0)
1102 all_num_devices[
n] = 0;
1109 cl_uint num_devices = 0;
1110 for(
int n = 0;
n < num_platforms;
n++) num_devices += all_num_devices[
n];
1113 cl_device_id *devices = 0;
1117 devices = (cl_device_id *)malloc(
sizeof(cl_device_id) * num_devices);
1127 cl_device_id *devs = devices;
1128 for(
int n = 0;
n < num_platforms;
n++)
1130 if(all_num_devices[
n])
1132 cl_platform_id platform = all_platforms[
n];
1135 if(err != CL_SUCCESS)
1137 num_devices -= all_num_devices[
n];
1140 devs += all_num_devices[
n];
1146 if(num_devices == 0)
1156 for(
int k = 0;
k < num_devices;
k++)
1193 cl->
inited ?
"" :
"NOT ");
1198 snprintf(checksum,
sizeof(checksum),
"%u", cl->
crc);
1228 setlocale(LC_ALL, locale);
1249 dt_print_nts(
DT_DEBUG_OPENCL,
" [opencl_summary_statistics] device '%s' (%d): peak memory usage %" G_GSIZE_FORMAT
" bytes (%.1f MB)\n",
1258 "successful and %d events lost. max event=%d%s\n",
1358 return (err == CL_SUCCESS && success == CL_COMPLETE);
1364 if(!cl->
inited || devid < 0)
return -1;
1372 while(*list != -1 && *list !=
value) list++;
1377 *list = *(list + 1);
1389 char tmp[2048] = { 0 };
1394 for(
int i = 0;
i < devs;
i++)
1411 maxlen = strlen(in) + 1;
1412 out = malloc(maxlen);
1418 while(*in !=
'\0' && len < maxlen - 1)
1420 int n = strcspn(in,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
1422 if(
n != 0)
continue;
1423 out[len] = tolower(*in);
1437 int *full = malloc(
sizeof(
int) * (devs + 1));
1443 priority_list[0] = -1;
1450 if(configstr[0] ==
'+')
1457 for(
int i = 0;
i < devs;
i++) full[
i] =
i;
1460 gchar **tokens = g_strsplit(configstr,
",", 0);
1461 gchar **tokens_ptr = tokens;
1465 gchar *str = *tokens_ptr;
1476 while(*str ==
'!') str++;
1483 for(
int i = 0;
i < devs && full[
i] != -1;
i++)
1485 priority_list[count] = full[
i];
1490 else if(*str !=
'\0')
1492 char *endptr = NULL;
1498 if(number < 0) number = strtol(str, &endptr, 10);
1501 if(number < 0 || (number == 0 && endptr == str)) number = -1;
1506 if(!not&&dev_number != -1)
1508 priority_list[count] = dev_number;
1519 while(count < devs + 1) priority_list[count++] = -1;
1522 *mandatory = (priority_list[0] != -1) ? mnd : 0;
1566 if(!cl->
inited)
return -1;
1571 size_t prio_size =
sizeof(int) * (cl->
num_devs + 1);
1572 int *priority = (
int *)malloc(prio_size);
1602 const int usec = 5000;
1606 for(
int n = 0;
n < nloop;
n++)
1608 const int *prio = priority;
1629 dt_print(
DT_DEBUG_OPENCL,
"[opencl_lock_device] reached opencl_mandatory_timeout trying to lock mandatory device, fallback to CPU\n");
1634 for(
int try_dev = 0; try_dev < cl->
num_devs; try_dev++)
1652 if(dev < 0 || dev >= cl->
num_devs)
return;
1658 FILE *
f = g_fopen(filename,
"rb");
1665 if(fstat(fd, st) < 0)
1690 struct stat filestat;
1700 size_t filesize = filestat.st_size;
1701 char *file = (
char *)malloc(filesize);
1711 size_t rd = fread(file,
sizeof(
char), filesize,
f);
1722 *md5sums = g_compute_checksum_for_data(G_CHECKSUM_MD5, (guchar *)file, filesize);
1729 const char *cachedir,
char *md5sum,
char **includemd5,
int *loaded_cached)
1734 struct stat filestat, cachedstat;
1747 "[opencl_load_source] program number `%d' already in use when loading file `%s'!\n", prog,
1755 size_t filesize = filestat.st_size;
1756 char *file = (
char *)malloc(filesize + 2048);
1757 size_t rd = fread(file,
sizeof(
char), filesize,
f);
1766 char *start = file + filesize;
1767 char *end = start + 2048;
1770 cl_device_id devid = cl->
dev[dev].
devid;
1774 cl_platform_id platform;
1781 len = g_strlcpy(start, options_md5, end - start);
1787 if(!includemd5[
n])
continue;
1788 len = g_strlcpy(start, includemd5[
n], end - start);
1792 char *source_md5 = g_compute_checksum_for_data(G_CHECKSUM_MD5, (guchar *)file, start - file);
1793 g_strlcpy(md5sum, source_md5, 33);
1796 file[filesize] =
'\0';
1799 ssize_t linkedfile_len = 0;
1805 snprintf(dup,
sizeof(dup),
"%s.%s", binname, md5sum);
1807 g_strlcpy(linkedfile, md5sum,
sizeof(linkedfile));
1808 linkedfile_len = strlen(md5sum);
1810 FILE *cached =
fopen_stat(binname, &cachedstat);
1816 linkedfile_len = readlink(binname, linkedfile,
sizeof(linkedfile) - 1);
1818 if(linkedfile_len > 0)
1820 linkedfile[linkedfile_len] =
'\0';
1822 if(strncmp(linkedfile, md5sum, 33) == 0)
1825 size_t cached_filesize = cachedstat.st_size;
1827 unsigned char *cached_content = (
unsigned char *)malloc(cached_filesize + 1);
1828 rd = fread(cached_content,
sizeof(
char), cached_filesize, cached);
1829 if(rd != cached_filesize)
1831 dt_print(
DT_DEBUG_OPENCL,
"[opencl_load_program] could not read all of file '%s' MD5: %s!\n", binname, md5sum);
1837 (
const unsigned char **)&cached_content, NULL, &err);
1838 if(err != CL_SUCCESS)
1841 "[opencl_load_program] could not load cached binary program from file '%s' MD5: '%s'! (%i)\n",
1842 binname, md5sum, err);
1857 if(*loaded_cached == 0)
1862 if(linkedfile_len > 0)
1866 g_unlink(link_dest);
1875 "[opencl_load_program] could not load cached binary program, trying to compile source\n");
1878 cl->
dev[dev].
context, 1, (
const char **)&file, &filesize, &err);
1880 if((err != CL_SUCCESS) || (cl->
dev[dev].
program[prog] == NULL))
1894 dt_vprint(
DT_DEBUG_OPENCL,
"[opencl_load_program] loaded cached binary program from file '%s' MD5: '%s' \n", binname, md5sum);
1897 dt_vprint(
DT_DEBUG_OPENCL,
"[opencl_load_program] successfully loaded program from '%s' MD5: '%s'\n", filename, md5sum);
1903 char *md5sum,
int loaded_cached)
1907 cl_program program = cl->
dev[dev].
program[prog];
1910 if(err != CL_SUCCESS)
1915 cl_build_status build_status;
1917 sizeof(cl_build_status), &build_status, NULL);
1921 size_t ret_val_size;
1924 if(ret_val_size != SIZE_MAX)
1926 build_log = (
char *)malloc(
sizeof(
char) * (ret_val_size + 1));
1930 ret_val_size, build_log, NULL);
1932 build_log[ret_val_size] =
'\0';
1941 if(err != CL_SUCCESS)
1952 if(err != CL_SUCCESS)
1958 cl_device_id *devices = malloc(
sizeof(cl_device_id) * numdev);
1960 sizeof(cl_device_id) * numdev, devices, NULL);
1961 if(err != CL_SUCCESS)
1968 size_t *binary_sizes = malloc(
sizeof(
size_t) * numdev);
1970 sizeof(
size_t) * numdev, binary_sizes, NULL);
1971 if(err != CL_SUCCESS)
1979 unsigned char **binaries = malloc(
sizeof(
unsigned char *) * numdev);
1980 for(
int i = 0;
i < numdev;
i++) binaries[
i] = (
unsigned char *)malloc(binary_sizes[
i]);
1982 sizeof(
unsigned char *) * numdev, binaries, NULL);
1983 if(err != CL_SUCCESS)
1989 for(
int i = 0;
i < numdev;
i++)
1994 snprintf(link_dest,
sizeof(link_dest),
"%s" G_DIR_SEPARATOR_S
"%s", cachedir, md5sum);
1995 FILE *
f = g_fopen(link_dest,
"wb");
1997 size_t bytes_written = fwrite(binaries[
i],
sizeof(
char), binary_sizes[
i],
f);
1998 if(bytes_written != binary_sizes[
i])
goto ret;
2003 if(!getcwd(cwd,
sizeof(cwd)))
goto ret;
2004 if(chdir(cachedir) != 0)
goto ret;
2006 g_strlcpy(dup, binname,
sizeof(dup));
2007 char *bname = basename(dup);
2011 char finalfilename[
PATH_MAX] = { 0 };
2012 snprintf(finalfilename,
sizeof(finalfilename),
"%s" G_DIR_SEPARATOR_S
"%s.%s", cachedir, bname, md5sum);
2013 rename(link_dest, finalfilename);
2015 if(symlink(md5sum, bname) != 0)
goto ret;
2017 if(chdir(cwd) != 0)
goto ret;
2021 for(
int i = 0;
i < numdev;
i++)
dt_free(binaries[
i]);
2033 if(!cl->
inited)
return -1;
2037 for(
int dev = 0; dev < cl->
num_devs; dev++)
2046 if(err != CL_SUCCESS)
2079 for(
int dev = 0; dev < cl->
num_devs; dev++)
2090 if(!cl->
inited || dev < 0)
return -1;
2092 sizeof(size_t) * 3, sizes, NULL);
2096 unsigned long *localmemsize)
2099 if(!cl->
inited || dev < 0)
return -1;
2102 sizeof(cl_ulong), &lmemsize, NULL);
2103 if(err != CL_SUCCESS)
return err;
2105 *localmemsize = lmemsize;
2108 sizeof(
size_t), workgroupsize, NULL);
2109 if(err != CL_SUCCESS)
return err;
2118 if(!cl->
inited || dev < 0)
return -1;
2122 CL_KERNEL_WORK_GROUP_SIZE,
sizeof(size_t),
2123 kernelworkgroupsize, NULL);
2131 if(!cl->
inited || dev < 0)
return -1;
2143 const size_t *local)
2146 if(!cl->
inited || dev < 0)
return -1;
2155 2, NULL, sizes, local, 0, NULL, eventp);
2157 if(err != CL_SUCCESS)
2176 const int height,
const int rowpitch)
2179 const size_t origin[] = { 0, 0, 0 };
2197 const size_t origin[] = { 0, 0, 0 };
2205 const size_t *region,
const int rowpitch,
const int blocking)
2212 device, blocking ? CL_TRUE : CL_FALSE, origin, region, rowpitch,
2213 0, host, 0, NULL, eventp);
2223 const int height,
const int rowpitch)
2226 const size_t origin[] = { 0, 0, 0 };
2243 const size_t origin[] = { 0, 0, 0 };
2250 const size_t *region,
const int rowpitch,
const int blocking)
2257 device, blocking ? CL_TRUE : CL_FALSE, origin, region,
2258 rowpitch, 0, host, 0, NULL, eventp);
2268 if(err != CL_SUCCESS)
dt_print(
DT_DEBUG_OPENCL,
"[opencl copy_image] could not copy image on device %d: %i\n", devid, err);
2273 size_t *origin,
size_t *region,
size_t offset)
2279 if(err != CL_SUCCESS)
2280 dt_print(
DT_DEBUG_OPENCL,
"[opencl copy_image_to_buffer] could not copy image on device %d: %i\n", devid, err);
2285 size_t offset,
size_t *origin,
size_t *region)
2291 if(err != CL_SUCCESS)
2292 dt_print(
DT_DEBUG_OPENCL,
"[opencl copy_buffer_to_image] could not copy buffer on device %d: %i\n", devid, err);
2297 size_t srcoffset,
size_t dstoffset,
size_t size)
2302 src_buffer, dst_buffer, srcoffset,
2303 dstoffset,
size, 0, NULL, eventp);
2304 if(err != CL_SUCCESS)
2305 dt_print(
DT_DEBUG_OPENCL,
"[opencl copy_buffer_to_buffer] could not copy buffer on device %d: %i\n", devid, err);
2310 const size_t size,
const int blocking)
2321 const size_t size,
const int blocking)
2338 if(err != CL_SUCCESS)
2340 "[opencl copy_host_to_device_constant] could not alloc buffer on device %d: %i\n", devid, err);
2354 const int bpp,
const int rowpitch)
2358 cl_image_format fmt;
2360 if(
bpp == 4 *
sizeof(
float))
2361 fmt = (cl_image_format){ CL_RGBA, CL_FLOAT };
2362 else if(
bpp ==
sizeof(
float))
2363 fmt = (cl_image_format){ CL_R, CL_FLOAT };
2364 else if(
bpp ==
sizeof(uint16_t))
2365 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT16 };
2372 rowpitch, host, &err);
2373 if(err != CL_SUCCESS)
2375 "[opencl copy_host_to_device] could not alloc/copy img buffer on device %d: %i\n", devid, err);
2405 if(err != CL_SUCCESS)
dt_print(
DT_DEBUG_OPENCL,
"[opencl map buffer] could not map buffer on device %d: %i\n", devid, err);
2416 size_t origin[3] = {0, 0, 0};
2418 size_t mapped_row_pitch;
2422 &mapped_row_pitch, NULL, 0, NULL, eventp, &err);
2424 if(err != CL_SUCCESS)
2436 if(err != CL_SUCCESS)
2437 dt_print(
DT_DEBUG_OPENCL,
"[opencl unmap mem object] could not unmap mem object on device %d: %i\n", devid, err);
2442 const cl_mem_flags
flags,
const cl_image_format fmt,
void *host,
2443 const char *
const context)
2448 for(
int attempt = 0; attempt < 2; attempt++)
2452 if(err == CL_SUCCESS)
break;
2453 if(attempt == 0 && (err == CL_MEM_OBJECT_ALLOCATION_FAILURE || err == CL_OUT_OF_RESOURCES))
2456 "[opencl %s] out of memory on device %d, flushing cached pinned buffers and retrying\n",
2464 if(err != CL_SUCCESS)
2475 cl_image_format fmt;
2477 if(rgba8 && effective_bpp == 4 *
sizeof(uint8_t))
2478 fmt = (cl_image_format){ CL_RGBA, CL_UNSIGNED_INT8 };
2479 else if(effective_bpp == 4 *
sizeof(
float))
2480 fmt = (cl_image_format){ CL_RGBA, CL_FLOAT };
2481 else if(effective_bpp ==
sizeof(
float))
2482 fmt = (cl_image_format){ CL_R, CL_FLOAT };
2483 else if(effective_bpp ==
sizeof(uint16_t))
2484 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT16 };
2485 else if(effective_bpp ==
sizeof(uint8_t))
2486 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT8 };
2494 const int bpp,
void *host,
const int flags)
2498 cl_image_format fmt;
2500 if(rgba8 && effective_bpp == 4 *
sizeof(uint8_t))
2501 fmt = (cl_image_format){ CL_RGBA, CL_UNSIGNED_INT8 };
2502 else if(effective_bpp == 4 *
sizeof(
float))
2503 fmt = (cl_image_format){ CL_RGBA, CL_FLOAT };
2504 else if(effective_bpp ==
sizeof(
float))
2505 fmt = (cl_image_format){ CL_R, CL_FLOAT };
2506 else if(effective_bpp ==
sizeof(uint16_t))
2507 fmt = (cl_image_format){ CL_R, CL_UNSIGNED_INT16 };
2519 for(
int attempt = 0; attempt < 2; attempt++)
2523 if(err == CL_SUCCESS)
break;
2524 if(attempt == 0 && (err == CL_MEM_OBJECT_ALLOCATION_FAILURE || err == CL_OUT_OF_RESOURCES))
2527 "[opencl alloc_device_buffer] out of memory on device %d, flushing cached pinned buffers and retrying\n",
2534 if(err != CL_SUCCESS)
2557 return (err == CL_SUCCESS) ?
size : 0;
2566 if(err != CL_SUCCESS)
2581 cl_mem_flags
flags = 0;
2583 if(err != CL_SUCCESS)
return 0;
2595 return (err == CL_SUCCESS) ? (int)
size : 0;
2606 return (err == CL_SUCCESS) ? (int)
size : 0;
2618 return (err == CL_SUCCESS) ? (int)
size : 0;
2650 if(!cl->
inited || devid < 0)
return;
2659 "[dt_opencl_check_tuning] use %" G_GSIZE_FORMAT
" MiB on device `%s' id=%i\n",
2669 return (limit > in_use) ? (limit - in_use) : 0;
2684 const float factor,
const size_t overhead)
2690 const size_t total = (size_t)ceilf((
float)required *
factor) + overhead;
2698 "[opencl] trying to allocate %" PRIu64
" MiB of memory while the vRAM has %" PRIu64
2700 (
uint64_t)(required / (1024 * 1024)),
2709 "[opencl] trying to allocate %" PRIu64
" MiB of memory while the vRAM has %" PRIu64
2721 return (
size % roundup == 0 ?
size : (
size / roundup + 1) * roundup);
2726 return (
size % roundup == 0 ?
size : (
size / roundup + 1) * roundup);
2796 if(!cl->
inited || devid < 0)
return NULL;
2799 static const cl_event zeroevent[1];
2813 *eventlist = calloc(newevents,
sizeof(cl_event));
2815 if(!*eventlist || !*eventtags)
2824 *maxevents = newevents;
2828 if(*numevents > 0 && !memcmp((*eventlist) + *numevents - 1, zeroevent,
sizeof(cl_event)))
2838 (*eventtags)[*numevents - 1].tag[0] =
'\0';
2842 return (*eventlist) + *numevents - 1;
2846 if((*numevents - *eventsconsolidated + 1 > cl->
dev[devid].
event_handles) || (*numevents == *maxevents))
2850 if(*numevents == *maxevents)
2853 cl_event *neweventlist = calloc(newevents,
sizeof(cl_event));
2863 memcpy(neweventlist, *eventlist,
sizeof(cl_event) * *maxevents);
2867 *eventlist = neweventlist;
2868 *eventtags = neweventtags;
2869 *maxevents = newevents;
2874 memcpy((*eventlist) + *numevents - 1, zeroevent,
sizeof(cl_event));
2881 (*eventtags)[*numevents - 1].tag[0] =
'\0';
2885 *maxeventslot =
MAX(*maxeventslot, *numevents - 1);
2886 return (*eventlist) + *numevents - 1;
2894 if(!cl->
inited || devid < 0)
return;
2905 if(
IS_NULL_PTR(*eventlist) || *numevents == 0)
return;
2908 for(
int k = *eventsconsolidated;
k < *numevents;
k++)
2915 *eventsconsolidated = 0;
2917 *summary = CL_COMPLETE;
2927 if(!cl->
inited || devid < 0)
return;
2930 static const cl_event zeroevent[1];
2937 if(
IS_NULL_PTR(*eventlist) || *numevents == 0)
return;
2940 if(!memcmp((*eventlist) + *numevents - 1, zeroevent,
sizeof(cl_event)))
2947 if(*numevents == *eventsconsolidated)
return;
2949 assert(*numevents > *eventsconsolidated);
2955 (*eventlist) + *eventsconsolidated);
2956 if((err != CL_SUCCESS) && (err != CL_INVALID_VALUE))
2983 if(
IS_NULL_PTR(*eventlist) || *numevents == 0)
return CL_COMPLETE;
2989 for(
int k = *eventsconsolidated;
k < *numevents;
k++)
2992 char *tag = (*eventtags)[
k].tag;
2993 cl_int *retval = &((*eventtags)[
k].retval);
2997 sizeof(cl_int), retval, NULL);
2998 if(err != CL_SUCCESS)
3001 tag[0] ==
'\0' ?
"<?>" : tag, err);
3003 else if(*retval != CL_COMPLETE)
3006 tag[0] ==
'\0' ?
"<?>" : tag, *retval == CL_COMPLETE ?
"was successful" :
"failed", *retval);
3018 (*eventlist)[
k], CL_PROFILING_COMMAND_START,
sizeof(cl_ulong), &start, NULL);
3020 sizeof(cl_ulong), &end, NULL);
3021 if(errs == CL_SUCCESS && erre == CL_SUCCESS)
3023 (*eventtags)[
k].timelapsed = end - start;
3027 (*eventtags)[
k].timelapsed = 0;
3032 (*eventtags)[
k].timelapsed = 0;
3036 (*eventsconsolidated)++;
3039 cl_int result = *summary;
3051 return result == CL_COMPLETE ? 0 : result;
3060 if(!cl->
inited || devid < 0)
return;
3072 char **tags = malloc(
sizeof(
char *) * (*eventsconsolidated + 1));
3073 float *timings = malloc(
sizeof(
float) * (*eventsconsolidated + 1));
3079 for(
int k = 0;
k < *eventsconsolidated;
k++)
3099 timings[tagfound] += (*eventtags)[
k].timelapsed * 1e-9;
3105 tags[
items - 1] = (*eventtags)[
k].tag;
3106 timings[
items - 1] = (*eventtags)[
k].timelapsed * 1e-9;
3113 tags[
items - 1] = (*eventtags)[
k].tag;
3114 timings[
items - 1] = (*eventtags)[
k].timelapsed * 1e-9;
3120 "[opencl_profiling] profiling device %d ('%s'):\n", devid, cl->
dev[devid].
name);
3126 tags[
i][0] ==
'\0' ?
"<?>" : tags[
i]);
3127 total += timings[
i];
3130 if(timings[0] != 0.0f)
3133 total += timings[0];
3137 "[opencl_profiling] spent %7.4f seconds totally in command queue (with %d event%s missing)\n",
3138 (
double)total, *lostevents, *lostevents == 1 ?
"" :
"s");
3161 size_t maxsizes[3] = { 0 };
3162 size_t workgroupsize = 0;
3163 unsigned long localmemsize = 0;
3164 size_t kernelworkgroupsize = 0;
3166 int *blocksizex = &factors->
sizex;
3167 int *blocksizey = &factors->
sizey;
3171 *blocksizex = CLAMP(
nextpow2(*blocksizex), 1, 1 << 16);
3172 *blocksizey = CLAMP(
nextpow2(*blocksizey), 1, 1 << 16);
3177 while(maxsizes[0] < *blocksizex || maxsizes[1] < *blocksizey
3178 || localmemsize < ((factors->
xfactor * (*blocksizex) + factors->
xoffset) *
3180 || workgroupsize < (
size_t)(*blocksizex) * (*blocksizey) || kernelworkgroupsize < (
size_t)(*blocksizex) * (*blocksizey))
3182 if(*blocksizex == 1 && *blocksizey == 1)
return FALSE;
3184 if(*blocksizex > *blocksizey)
3192 dt_print(
DT_DEBUG_OPENCL,
"[dt_opencl_local_buffer_opt] can not identify resource limits for device %d\n", devid);
static void error(char *msg)
dt_bilateral_cl_global_t * dt_bilateral_init_cl_global()
void dt_bilateral_free_cl_global(dt_bilateral_cl_global_t *b)
dt_blendop_cl_global_t * dt_develop_blend_init_cl_global(void)
void dt_develop_blend_free_cl_global(dt_blendop_cl_global_t *b)
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))
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)
void dt_vprint(dt_debug_thread_t thread, const char *msg,...)
void dt_concat_path_file(char destination[PATH_MAX], const char path[PATH_MAX], const char *const file)
void dt_print_nts(dt_debug_thread_t thread, const char *msg,...)
void dt_capabilities_add(char *capability)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
static const dt_aligned_pixel_simd_t value
static double dt_get_wtime(void)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
dt_dlopencl_t * dt_dlopencl_init(const char *name)
static int dt_pthread_mutex_BAD_trylock(dt_pthread_mutex_t *mutex)
static int dt_pthread_mutex_BAD_unlock(dt_pthread_mutex_t *mutex)
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
dt_dwt_cl_global_t * dt_dwt_init_cl_global()
void dt_dwt_free_cl_global(dt_dwt_cl_global_t *g)
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[]
void dt_gaussian_free_cl_global(dt_gaussian_cl_global_t *g)
dt_gaussian_cl_global_t * dt_gaussian_init_cl_global()
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)
dt_heal_cl_global_t * dt_heal_init_cl_global()
void dt_iop_nap(int32_t usec)
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
dt_mipmap_buffer_dsc_flags flags
static int dt_nvidia_gpu_supports_sm_20(const char *model)
cl_ulong dt_opencl_get_device_available(const int devid)
int dt_opencl_get_kernel_work_group_size(const int dev, const int kernel, size_t *kernelworkgroupsize)
cl_event * dt_opencl_events_get_slot(const int devid, const char *tag)
int dt_opencl_local_buffer_opt(const int devid, const int kernel, dt_opencl_local_buffer_t *factors)
void dt_opencl_unlock_device(const int dev)
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
static void dt_opencl_update_priorities()
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
int dt_opencl_read_host_from_device_rowpitch(const int devid, void *host, void *device, const int width, const int height, const int rowpitch)
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)
size_t dt_opencl_get_mem_object_size(cl_mem mem)
gboolean dt_opencl_is_pinned_memory(cl_mem mem)
static char * _ascii_str_canonical(const char *in, char *out, int maxlen)
void dt_opencl_cleanup_device(dt_opencl_t *cl, int i)
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)
void dt_opencl_init(dt_opencl_t *cl, const gboolean exclude_opencl, const gboolean print_statistics)
void dt_opencl_events_reset(const int devid)
cl_int dt_opencl_events_flush(const int devid, const int reset)
int dt_opencl_copy_device_to_host(const int devid, void *host, void *device, const int width, const int height, const int bpp)
int dt_opencl_lock_device(const int pipetype)
gboolean dt_opencl_read_device_config(const int devid)
void dt_opencl_check_tuning(const int devid)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
int dt_opencl_is_inited(void)
int dt_opencl_create_kernel(const int prog, const char *name)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
int dt_opencl_dev_roundup_height(int size, const int devid)
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)
int dt_opencl_write_host_to_device_rowpitch(const int devid, void *host, void *device, const int width, const int height, const int rowpitch)
int dt_opencl_dev_roundup_width(int size, const int devid)
void dt_opencl_write_device_config(const int devid)
static void dt_opencl_set_synchronization_timeout(int value)
static int dt_opencl_device_init(dt_opencl_t *cl, const int dev, cl_device_id *devices, const int k)
int dt_opencl_get_mem_context_id(cl_mem mem)
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)
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)
static void * _dt_opencl_alloc_image2d(const int devid, const int width, const int height, const cl_mem_flags flags, const cl_image_format fmt, void *host, const char *const context)
void * dt_opencl_map_buffer(const int devid, cl_mem buffer, const int blocking, const int flags, size_t offset, size_t size)
static void dt_opencl_apply_scheduling_profile()
static int _dt_opencl_get_conf_int(const gchar *key_device, const gchar *conf_name, gboolean *safety_ok)
int dt_opencl_get_image_height(cl_mem mem)
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)
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)
int dt_opencl_micro_nap(const int devid)
static cl_ulong _opencl_get_device_memalloc(const int devid)
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)
static int _take_from_list(int *list, int value)
int dt_opencl_set_detected_device_enabled(const int detected, const gboolean enabled)
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)
int dt_opencl_build_program(const int dev, const int prog, const char *binname, const char *cachedir, char *md5sum, int loaded_cached)
int dt_opencl_get_max_work_item_sizes(const int dev, size_t *sizes)
int dt_opencl_enqueue_barrier(const int devid)
static FILE * fopen_stat(const char *filename, struct stat *st)
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)
int dt_opencl_unmap_mem_object(const int devid, cl_mem mem_object, void *mapped_ptr)
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)
gboolean dt_opencl_detected_device_pinned_memory(const int detected)
int dt_opencl_set_detected_device_headroom(const int detected, const size_t headroom)
int dt_opencl_is_enabled(void)
void dt_opencl_md5sum(const char **files, char **md5sums)
static int nextpow2(int n)
void dt_opencl_free_kernel(const int kernel)
static gboolean _opencl_splash_active
gboolean dt_opencl_use_pinned_memory(const int devid)
void dt_opencl_cleanup(dt_opencl_t *cl)
int dt_opencl_get_image_width(cl_mem mem)
cl_ulong dt_opencl_get_device_memalloc(const int devid)
void dt_opencl_memory_statistics(int devid, cl_mem mem, dt_opencl_memory_t action)
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)
int dt_opencl_get_detected_device_count(void)
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)
void * dt_opencl_alloc_device_buffer_with_flags(const int devid, const size_t size, const int flags, void *host_ptr)
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)
static void dt_opencl_priority_parse(dt_opencl_t *cl, char *configstr, int *priority_list, int *mandatory)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
gboolean dt_opencl_finish(const int devid)
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)
static void _opencl_splash_update_compile(const char *programname)
int dt_opencl_update_settings(void)
void dt_opencl_events_wait_for(const int devid)
int dt_opencl_set_detected_device_pinned_memory(const int detected, const gboolean enabled)
int dt_opencl_read_host_from_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
void dt_opencl_events_profiling(const int devid, const int aggregated)
int dt_opencl_get_work_group_limits(const int dev, size_t *sizes, size_t *workgroupsize, unsigned long *localmemsize)
int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
cl_mem_flags dt_opencl_get_mem_flags(cl_mem mem)
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)
const dt_opencl_detected_device_t * dt_opencl_get_detected_device(const int detected)
void * dt_opencl_copy_host_to_device(const int devid, void *host, const int width, const int height, const int bpp)
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)
size_t dt_opencl_detected_device_headroom(const int detected)
void dt_opencl_release_mem_object(cl_mem mem)
static int _device_by_cname(const char *name)
int dt_opencl_get_image_element_size(cl_mem mem)
gboolean dt_opencl_detected_device_enabled(const int detected)
static const char * dt_opencl_get_vendor_by_id(unsigned int id)
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)
int dt_opencl_avoid_atomics(const int devid)
int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
void dt_opencl_disable(void)
#define DT_OPENCL_MAX_INCLUDES
#define DT_OPENCL_EVENTLISTSIZE
#define DT_OPENCL_BPP_DECODE(bpp)
@ DT_OPENCL_PINNING_DISABLED
#define DT_OPENCL_DEFAULT_COMPILE
#define DT_OPENCL_DEFAULT_COMPILE_INTEL
#define DT_OPENCL_BPP_IS_RGBA8(bpp)
#define DT_OPENCL_CBUFFSIZE
#define DT_OPENCL_EVENTNAMELENGTH
#define DT_OPENCL_VENDOR_INTEL
#define DT_OPENCL_MAX_PROGRAMS
#define DT_OPENCL_MAX_PLATFORMS
#define DT_OPENCL_DEFAULT_COMPILE_AMD
#define DT_OPENCL_DEFAULT_COMPILE_NVIDIA
#define DT_OPENCL_VENDOR_NVIDIA
#define DT_OPENCL_VENDOR_AMD
#define DT_OPENCL_MAX_KERNELS
static gboolean dt_opencl_check_driver_blacklist(const char *device_version)
@ DT_DEV_PIXELPIPE_THUMBNAIL
@ DT_DEV_PIXELPIPE_EXPORT
@ DT_DEV_PIXELPIPE_PREVIEW
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)
void dt_gui_splash_updatef(const char *format,...)
unsigned __int64 uint64_t
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
struct dt_gui_gtk_t * gui
struct dt_opencl_t * opencl
dt_clEnqueueReadImage_t dt_clEnqueueReadImage
dt_clGetEventInfo_t dt_clGetEventInfo
dt_clReleaseCommandQueue_t dt_clReleaseCommandQueue
dt_clEnqueueUnmapMemObject_t dt_clEnqueueUnmapMemObject
dt_clGetKernelInfo_t dt_clGetKernelInfo
dt_clGetEventProfilingInfo_t dt_clGetEventProfilingInfo
dt_clCreateCommandQueue_t dt_clCreateCommandQueue
dt_clCreateImage2D_t dt_clCreateImage2D
dt_clEnqueueCopyBuffer_t dt_clEnqueueCopyBuffer
dt_clGetPlatformInfo_t dt_clGetPlatformInfo
dt_clBuildProgram_t dt_clBuildProgram
dt_clEnqueueWriteBuffer_t dt_clEnqueueWriteBuffer
dt_clCreateContext_t dt_clCreateContext
dt_clGetDeviceIDs_t dt_clGetDeviceIDs
dt_clGetMemObjectInfo_t dt_clGetMemObjectInfo
dt_clEnqueueCopyImage_t dt_clEnqueueCopyImage
dt_clReleaseContext_t dt_clReleaseContext
dt_clFinish_t dt_clFinish
dt_clGetDeviceInfo_t dt_clGetDeviceInfo
dt_clEnqueueCopyImageToBuffer_t dt_clEnqueueCopyImageToBuffer
dt_clGetImageInfo_t dt_clGetImageInfo
dt_clCreateBuffer_t dt_clCreateBuffer
dt_clCreateProgramWithBinary_t dt_clCreateProgramWithBinary
dt_clReleaseKernel_t dt_clReleaseKernel
dt_clEnqueueWriteImage_t dt_clEnqueueWriteImage
dt_clSetKernelArg_t dt_clSetKernelArg
dt_clReleaseEvent_t dt_clReleaseEvent
dt_clEnqueueMapImage_t dt_clEnqueueMapImage
dt_clEnqueueBarrier_t dt_clEnqueueBarrier
dt_clGetPlatformIDs_t dt_clGetPlatformIDs
dt_clGetProgramInfo_t dt_clGetProgramInfo
dt_clGetKernelWorkGroupInfo_t dt_clGetKernelWorkGroupInfo
dt_clReleaseMemObject_t dt_clReleaseMemObject
dt_clGetProgramBuildInfo_t dt_clGetProgramBuildInfo
dt_clReleaseProgram_t dt_clReleaseProgram
dt_clEnqueueNDRangeKernel_t dt_clEnqueueNDRangeKernel
dt_clWaitForEvents_t dt_clWaitForEvents
dt_clEnqueueReadBuffer_t dt_clEnqueueReadBuffer
dt_clEnqueueCopyBufferToImage_t dt_clEnqueueCopyBufferToImage
dt_clEnqueueMapBuffer_t dt_clEnqueueMapBuffer
dt_clCreateKernel_t dt_clCreateKernel
dt_clCreateProgramWithSource_t dt_clCreateProgramWithSource
dt_dlopencl_symbols_t * symbols
cl_command_queue cmd_queue
dt_opencl_eventtag_t * eventtags
struct dt_gaussian_cl_global_t * gaussian
int opencl_synchronization_timeout
int * dev_priority_preview
struct dt_bilateral_cl_global_t * bilateral
struct dt_colorspaces_cl_global_t * colorspaces
struct dt_guided_filter_cl_global_t * guided_filter
struct dt_interpolation_cl_global_t * interpolation
struct dt_local_laplacian_cl_global_t * local_laplacian
struct dt_blendop_cl_global_t * blendop
struct dt_dwt_cl_global_t * dwt
int * dev_priority_export
dt_opencl_detected_device_t * detected_devs
int * dev_priority_thumbnail
struct dt_heal_cl_global_t * heal
gchar * dt_util_str_replace(const gchar *string, const gchar *pattern, const gchar *substitute)