24#include <glib/gstdio.h>
25#include <json-glib/json-glib.h>
34#define NN_MIN(a, b) ((a) < (b) ? (a) : (b))
44#define NN_MAX_DEVICES 16
135 const size_t want = (
part == 0 ? (size_t)out_ch * in_ch *
k *
k : (size_t)out_ch) *
sizeof(float);
136 const float *found =
NULL;
137 for(guint
i = 0;
i <
n;
i++)
156 found = (
const float *)((
const uint8_t *)h->
payload + offset);
188 for(
int l = 0; l < depth && !
bad; l++)
190 const int w = base << l;
199 const int wb = base << depth;
206 for(
int i = 0;
i < depth && !
bad;
i++)
208 const int w_skip = base << (depth - 1 -
i);
274 float *blob =
malloc(payload_size);
276 const int payload_ok = blob &&
fread(blob, 1, payload_size,
f) == payload_size;
309 int bin_bayer = 1, bin_xtrans = 1;
340 if(payload_size /
sizeof(
float) > (
size_t)
INT_MAX)
355 m->bin_bayer = bin_bayer;
356 m->bin_xtrans = bin_xtrans;
360 if(anchor >= 8 && anchor <= 256)
m->anchor = anchor;
363 m->blob_floats = payload_size /
sizeof(float);
397 if(
m->dev_weights[
d])
418 return m->fine.in_ch;
423 return m->fine.out_ch;
428 if(!
m->has_coarse)
return 1;
434 return m->has_coarse ?
m->coarse.in_ch : 0;
439 return m->has_coarse ?
m->coarse.out_ch : 0;
449 if(a <= 0 || b <= 0)
return a > b ? a : b;
465 int align = 1 <<
m->fine.depth;
468 align =
_lcm(align,
m->bin_bayer <<
m->coarse.depth);
469 align =
_lcm(align,
m->bin_xtrans <<
m->coarse.depth);
515 const int ow = (w + 2 * pad -
k) / stride + 1;
516 const int oh = (h + 2 * pad -
k) / stride + 1;
517 const size_t inhw = (size_t)w * h;
525#pragma omp for collapse(2) schedule(static)
531 for(
int r = 0;
r <
nb;
r++)
533 float *
const ar =
acc + (size_t)
r *
ow;
534 const float bias =
cv->b[
ocb +
r];
537 for(
int ic = 0;
ic <
cv->in_ch;
ic++)
539 const float *
const ip =
in + (size_t)
ic *
inhw;
542 const int iy =
oy * stride +
ky - pad;
544 const float *
const irow =
ip + (size_t)
iy * w;
558 float *
const a2 =
acc + 2 *
ow, *
const a3 =
acc + 3 *
ow;
585 for(
int r = 0;
r <
nb;
r++)
588 float *
const ar =
acc + (size_t)
r *
ow;
603 for(
int r = 0;
r <
nb;
r++)
615#pragma omp parallel for schedule(static)
630 const size_t base = (size_t)u->
base;
632#define NN_LEDGER(delta) \
636 if(live > peak) peak = live; \
639 for(
int l = 0; l < u->
depth; l++)
641 const size_t lvl = base *
wh >> l;
659 const int l = u->
depth - 1 -
i;
660 const size_t half = base *
wh >> l;
695 const size_t ref = (size_t)1 << 24;
699 const int bin =
NN_MIN(
m->bin_bayer,
m->bin_xtrans);
726 float per_px = (float)
m->fine.base;
729 const int bin =
NN_MIN(
m->bin_bayer,
m->bin_xtrans);
730 const float coarse = (float)
m->coarse.base / (
float)(
bin *
bin);
742 const int bin =
NN_MIN(
m->bin_bayer,
m->bin_xtrans);
746 return floats *
sizeof(float);
764 const int ow = w,
oh = h;
765 const int bw = w / 2;
766 const size_t inhw = (size_t)w * h;
767 const size_t bhw = (size_t)
bw * (h / 2);
775#pragma omp for collapse(2) schedule(static)
781 for(
int r = 0;
r <
nb;
r++)
783 float *
const ar =
acc + (size_t)
r *
ow;
784 const float bias =
cv->b[
ocb +
r];
787 for(
int ic = 0;
ic <
cv->in_ch;
ic++)
793 const int iy =
oy +
ky - pad;
810 float *
const a2 =
acc + 2 *
ow, *
const a3 =
acc + 3 *
ow;
837 for(
int r = 0;
r <
nb;
r++)
840 float *
const ar =
acc + (size_t)
r *
ow;
855 for(
int r = 0;
r <
nb;
r++)
883 const int align = 1 << u->
depth;
887 const size_t base = (size_t)u->
base;
891 const float *src =
in;
895 for(
int l = 0; l < u->
depth && ok; l++)
897 const size_t lvl = base *
wh >> l;
950 for(
int i = 0;
i < u->
depth && ok;
i++)
952 const int l = u->
depth - 1 -
i;
953 const size_t w_skip = base << l;
954 const size_t half =
w_skip * (size_t)(2 * cw) * (size_t)(2 *
chh);
956 if(!
v) { ok = 0;
break; }
989#pragma omp parallel for schedule(static)
1014 if(!
m->has_coarse)
return 1;
1029 const size_t plane = (size_t)
pw *
ph;
1031 const float *
const mosaic = planes;
1033#pragma omp parallel for schedule(static) collapse(2)
1035 for(
int c = 0; c < 3; c++)
1036 for(
int cy = 0; cy <
chh; cy++)
1038 const float *
const onehot = planes + (size_t)(1 + c) * plane;
1039 float *
const orow =
out_rgb + (size_t)c * cw *
chh + (
size_t)cy * cw;
1040 float *
const crow =
out_cnt + (size_t)c * cw *
chh + (
size_t)cy * cw;
1041 for(
int cx = 0; cx < cw; cx++)
1043 float sum = 0.0f,
cnt = 0.0f;
1044 for(
int y = cy *
bin; y < (cy + 1) *
bin; y++)
1045 for(
int x = cx *
bin;
x < (cx + 1) *
bin;
x++)
1047 const size_t i = (size_t)y *
pw +
x;
1061#pragma omp parallel for schedule(static)
1063 for(
int c = 0; c <
ch; c++)
1065 const float *
const ip =
in + (size_t)c * w * h;
1067 for(
int y = 0; y < h *
factor; y++)
1069 const float *
const irow =
ip + (size_t)(y /
factor) * w;
1070 float *
const orow = op + (size_t)y * w *
factor;
1091 if(!cl)
return NULL;
1114 if(!
mm->dev_weights[devid])
1116 const size_t bytes =
m->blob_floats *
sizeof(float);
1119 mm->dev_weights[devid] = buf;
1123 cl_mem w =
mm->dev_weights[devid];
1132 const int ow = (w + 2 * pad -
cv->k) / stride + 1;
1133 const int oh = (h + 2 * pad -
cv->k) / stride + 1;
1138 const size_t lx = 128;
1140 if(
cv->k == 3 && stride == 1)
1146 const int chunk =
NN_MIN(
cv->in_ch, (24 << 10) / (
int)(
sizeof(
float) * 4 * 9));
1160 const size_t quads = (size_t)((w + 1) / 2) * ((h + 1) / 2);
1161 size_t sizes3[3] = { (
quads + lx - 1) / lx * lx, ((
size_t)
cv->out_ch + 3) / 4, 1 };
1162 size_t local3[3] = { lx, 1, 1 };
1191 size_t sizes[3] = { ((size_t)
ow *
oh + lx - 1) / lx * lx, ((size_t)
cv->out_ch + 3) / 4, 1 };
1192 size_t local[3] = { lx, 1, 1 };
1227 const int align = 1 << u->
depth;
1234 const size_t base = (size_t)u->
base;
1239#define NN_CL_ALLOC(var, floats) \
1242 var = dt_opencl_alloc_device_buffer(devid, (floats) * sizeof(float)); \
1249#define NN_CL_FREE(var) \
1252 if(var) dt_opencl_release_mem_object(var); \
1261 const size_t lvl = base *
wh >> l;
1266 err |=
_conv_cl(cl, devid,
weights,
m->blob, src,
tmp, cw,
chh, &u->
enc1[l], 1, 1, 1);
1267 err |=
_conv_cl(cl, devid,
weights,
m->blob,
tmp,
skips[l], cw,
chh, &u->
enc2[l], 1, 1, 1);
1269 err |=
_conv_cl(cl, devid,
weights,
m->blob,
skips[l], next, cw,
chh, &u->
down[l], 2, 0, 0);
1283 err |=
_conv_cl(cl, devid,
weights,
m->blob, src,
tmp, cw,
chh, &u->
bot1, 1, 1, 1);
1284 err |=
_conv_cl(cl, devid,
weights,
m->blob,
tmp,
v, cw,
chh, &u->
bot2, 1, 1, 1);
1295 const int l = u->
depth - 1 -
i;
1296 const size_t w_skip = base << l;
1297 const size_t half =
w_skip * (size_t)(2 * cw) * (size_t)(2 *
chh);
1299 err |=
_conv_cl(cl, devid,
weights,
m->blob,
cur,
v, cw,
chh, &u->
up[
i], 1, 0, 0);
1308 half *
sizeof(
float));
1313 err |=
_conv_cl(cl, devid,
weights,
m->blob,
cat,
d1, cw,
chh, &u->
dec1[
i], 1, 1, 1);
1316 err |=
_conv_cl(cl, devid,
weights,
m->blob,
d1,
cur, cw,
chh, &u->
dec2[
i], 1, 1, 1);
1322 err |=
_conv_cl(cl, devid,
weights,
m->blob,
cur,
dev_out,
width,
height, &u->
head, 1, 1, 0);
1325 for(
int l = 0; l < u->
depth; l++)
1343 if(!
m->has_coarse)
return -1;
void cleanup(dt_imageio_module_format_t *self)
const dt_colormatrix_t dt_aligned_pixel_t out
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
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
void dt_nn_cl_destroy(dt_nn_cl_t *cl)
int dt_nn_unet_apply_stage_cl(const dt_nn_model_t *m, int stage, dt_nn_cl_t *cl, int devid, cl_mem dev_in, cl_mem dev_out, int width, int height)
int dt_nn_model_anchor(const dt_nn_model_t *m)
#define NN_CL_ALLOC(var, floats)
void dt_nn_model_free(dt_nn_model_t *m)
static dt_nn_alloc_f _nn_alloc_fn
float dt_nn_unet_scratch_maxblock_per_px(const dt_nn_model_t *m)
static size_t _unet_peak_floats(const nn_unet_t *u, size_t wh, int cl_variant)
static cl_mem _weights_cl(const dt_nn_model_t *m, int devid)
int dt_nn_model_in_channels(const dt_nn_model_t *m)
static void _err(char *err, size_t err_len, const char *msg)
int dt_nn_model_coarse_in_channels(const dt_nn_model_t *m)
dt_nn_cl_t * dt_nn_cl_create(int program)
static int _conv_cl(dt_nn_cl_t *cl, int devid, cl_mem weights, const float *blob_base, cl_mem in, cl_mem out, int w, int h, const nn_conv_t *cv, int stride, int pad, int do_gelu)
static int _wire_conv(const nn_header_t *h, const char *prefix, int out_ch, int in_ch, int k, nn_conv_t *cv, char *err, size_t err_len)
static int _unet_forward(const nn_unet_t *u, const float *in, float *out, int width, int height, int residual_ch)
static int _unet_forward_cl(const dt_nn_model_t *m, const nn_unet_t *u, dt_nn_cl_t *cl, int devid, cl_mem dev_in, cl_mem dev_out, int width, int height)
size_t dt_nn_unet_scratch_bytes(const dt_nn_model_t *m, int width, int height)
int dt_nn_unet_apply_stage(const dt_nn_model_t *m, int stage, const float *in, float *out, int width, int height, int apply_residual)
static __DT_CLONE_TARGETS__ void _conv2d_cat2(const nn_conv_t *cv, const float *a, int in_ch_a, const float *b, int w, int h, float *out)
static __DT_CLONE_TARGETS__ void _conv2d(const nn_conv_t *cv, const float *in, int w, int h, int stride, int pad, float *out)
static void dt_nn_model_free_cl(dt_nn_model_t *m)
static void * _nn_alloc(size_t floats, int long_lived)
static dt_nn_free_f _nn_free_fn
static void _nn_free(void *p)
float dt_nn_unet_scratch_per_px(const dt_nn_model_t *m)
dt_nn_model_t * dt_nn_model_load(const char *path, char *err, size_t err_len)
__DT_CLONE_TARGETS__ void dt_nn_upsample_nearest(const float *in, int ch, int w, int h, int factor, float *out)
static __DT_CLONE_TARGETS__ void _gelu(float *x, size_t n)
int dt_nn_model_coarse_out_channels(const dt_nn_model_t *m)
static int _lcm(int a, int b)
float dt_nn_unet_scratch_per_px_cl(const dt_nn_model_t *m)
int dt_nn_model_alignment(const dt_nn_model_t *m)
int dt_nn_unet_apply(const dt_nn_model_t *m, const float *in, float *out, int width, int height)
static int _read_net_cfg(JsonObject *cfg, int out_ch_max, int *base, int *depth, int *in_ch, int *out_ch)
__DT_CLONE_TARGETS__ void dt_nn_bin_planes(const float *planes, int pw, int ph, int bin, float *out_rgb, float *out_cnt)
int dt_nn_model_bin(const dt_nn_model_t *m, const int is_xtrans)
static int _wire_unet(const nn_header_t *h, const char *stage_prefix, int base, int depth, int in_ch, int out_ch, nn_unet_t *u, char *err, size_t err_len)
static float _scratch_per_px(const dt_nn_model_t *m, int cl_variant)
static int _upsample_cl(dt_nn_cl_t *cl, int devid, cl_mem in, cl_mem out, int w, int h, int ch)
int dt_nn_model_out_channels(const dt_nn_model_t *m)
void dt_nn_set_allocator(dt_nn_alloc_f alloc_fn, dt_nn_free_f free_fn)
void *(* dt_nn_alloc_f)(size_t bytes, int long_lived)
void(* dt_nn_free_f)(void *ptr)
#define DT_NN_FUSION_COARSEST
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
int dt_opencl_create_kernel(const int prog, const char *name)
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)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
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)
void dt_opencl_release_mem_object(cl_mem mem)
dt_pthread_mutex_t cl_lock
#define __DT_CLONE_TARGETS__