58#define GF_TILE_SIZE 512
63#if defined(_OPENMP) && defined(OPENMP_SIMD_)
72#if !(defined(__x86_64__) || defined(__i386__))
73# define _mm_prefetch(where,hint)
124 const float eps,
const float guide_weight,
const float min,
const float max)
134#define GUIDE_MEAN_R 1
135#define GUIDE_MEAN_G 2
136#define GUIDE_MEAN_B 3
151 if(new_color_image(&variance,
width,
height, 9) != 0)
153 free_color_image(&mean);
156 const size_t img_dimen = mean.
width;
161 free_color_image(&variance);
162 free_color_image(&mean);
167 for(
int j_imgg = source.
lower; j_imgg < source.
upper; j_imgg++)
169 int j = j_imgg - source.
lower;
170 float *
const restrict meanpx = mean.
data + 4 * j * mean.
width;
171 float *
const restrict varpx = variance.
data + 9 * j * variance.
width;
172 for(
int i_imgg = source.
left; i_imgg < source.
right; i_imgg++)
174 size_t i = i_imgg - source.
left;
177 { pixel_[0] * guide_weight, pixel_[1] * guide_weight, pixel_[2] * guide_weight, pixel_[3] * guide_weight };
178 const float input = img.
data[i_imgg + (size_t)j_imgg * img.
width];
183 varpx[9*
i+
COV_R] = pixel[0] * input;
184 varpx[9*
i+
COV_G] = pixel[1] * input;
185 varpx[9*
i+
COV_B] = pixel[2] * input;
186 varpx[9*
i+
VAR_RR] = pixel[0] * pixel[0];
187 varpx[9*
i+
VAR_RG] = pixel[0] * pixel[1];
188 varpx[9*
i+
VAR_RB] = pixel[0] * pixel[2];
189 varpx[9*
i+
VAR_GG] = pixel[1] * pixel[1];
190 varpx[9*
i+
VAR_GB] = pixel[1] * pixel[2];
191 varpx[9*
i+
VAR_BB] = pixel[2] * pixel[2];
200#pragma omp atomic write
213 free_color_image(&variance);
214 free_color_image(&mean);
224 for(
size_t i = 0;
i <
size;
i++)
227 const float inp_mean = meanpx[
INP_MEAN];
234 const float Sigma_0_0 = varpx[
VAR_RR] - (guide_r * guide_r) +
eps;
235 const float Sigma_0_1 = varpx[
VAR_RG] - (guide_r * guide_g);
236 const float Sigma_0_2 = varpx[
VAR_RB] - (guide_r * guide_b);
237 const float Sigma_1_1 = varpx[
VAR_GG] - (guide_g * guide_g) +
eps;;
238 const float Sigma_1_2 = varpx[
VAR_GB] - (guide_g * guide_b);
239 const float Sigma_2_2 = varpx[
VAR_BB] - (guide_b * guide_b) +
eps;
240 const float det0 = Sigma_0_0 * (Sigma_1_1 * Sigma_2_2 - Sigma_1_2 * Sigma_1_2)
241 - Sigma_0_1 * (Sigma_0_1 * Sigma_2_2 - Sigma_0_2 * Sigma_1_2)
242 + Sigma_0_2 * (Sigma_0_1 * Sigma_1_2 - Sigma_0_2 * Sigma_1_1);
243 float a_r_, a_g_, a_b_, b_;
244 if(fabsf(det0) > 4.f * FLT_EPSILON)
246 const float cov_r = varpx[
COV_R] - guide_r * inp_mean;
247 const float cov_g = varpx[
COV_G] - guide_g * inp_mean;
248 const float cov_b = varpx[
COV_B] - guide_b * inp_mean;
249 const float det1 = cov_r * (Sigma_1_1 * Sigma_2_2 - Sigma_1_2 * Sigma_1_2)
250 - Sigma_0_1 * (cov_g * Sigma_2_2 - cov_b * Sigma_1_2)
251 + Sigma_0_2 * (cov_g * Sigma_1_2 - cov_b * Sigma_1_1);
252 const float det2 = Sigma_0_0 * (cov_g * Sigma_2_2 - cov_b * Sigma_1_2)
253 - cov_r * (Sigma_0_1 * Sigma_2_2 - Sigma_0_2 * Sigma_1_2)
254 + Sigma_0_2 * (Sigma_0_1 * cov_b - Sigma_0_2 * cov_g);
255 const float det3 = Sigma_0_0 * (Sigma_1_1 * cov_b - Sigma_1_2 * cov_g)
256 - Sigma_0_1 * (Sigma_0_1 * cov_b - Sigma_0_2 * cov_g)
257 + cov_r * (Sigma_0_1 * Sigma_1_2 - Sigma_0_2 * Sigma_1_1);
261 b_ = inp_mean - a_r_ * guide_r - a_g_ * guide_g - a_b_ * guide_b;
277 free_color_image(&variance);
281 free_color_image(&mean);
285 for(
int j_imgg = target.
lower; j_imgg < target.
upper; j_imgg++)
288 size_t l = target.
left + (size_t)j_imgg * imgg.
width;
293 for(
int i_imgg = target.
left; i_imgg < target.
right; i_imgg++,
k++, l++)
297 float res = guide_weight * (px_ab[
A_RED] * pixel[0] + px_ab[
A_GREEN] * pixel[1] + px_ab[
A_BLUE] * pixel[2]);
302 free_color_image(&mean);
306static inline __attribute__((always_inline))
int compute_tile_height(
const int height,
const int w)
331static inline __attribute__((always_inline))
int compute_tile_width(
const int width,
const int w)
360 const float sqrt_eps,
361 const float guide_weight,
362 const float min,
const float max)
370 const int tile_width = compute_tile_width(
width,w);
371 const int tile_height = compute_tile_height(
height,w);
372 const float eps = sqrt_eps * sqrt_eps;
374 for(
int j = 0; j <
height; j += tile_height)
376 for(
int i = 0;
i <
width;
i += tile_width)
398 const int program = 26;
402 g->kernel_guided_filter_guided_filter_covariances
431 cl_mem imgg_g, cl_mem imgg_b,
const float guide_weight)
457 if(err != CL_SUCCESS)
return err;
471 cl_mem cov_imgg_img_r, cl_mem cov_imgg_img_g, cl_mem cov_imgg_img_b,
472 const float guide_weight)
489 cl_mem var_imgg_rg, cl_mem var_imgg_rb, cl_mem var_imgg_gg, cl_mem var_imgg_gb,
490 cl_mem var_imgg_bb,
const float guide_weight)
509 cl_mem a, cl_mem b,
float eps)
524static int cl_solve(
const int devid,
const int width,
const int height, cl_mem img_mean, cl_mem imgg_mean_r,
525 cl_mem imgg_mean_g, cl_mem imgg_mean_b, cl_mem cov_imgg_img_r, cl_mem cov_imgg_img_g,
526 cl_mem cov_imgg_img_b, cl_mem var_imgg_rr, cl_mem var_imgg_rg, cl_mem var_imgg_rb,
527 cl_mem var_imgg_gg, cl_mem var_imgg_gb, cl_mem var_imgg_bb, cl_mem a_r, cl_mem a_g, cl_mem a_b,
556 cl_mem a_g, cl_mem a_b, cl_mem b, cl_mem
out,
const float guide_weight,
557 const float min,
const float max)
579 const float sqrt_eps,
580 const float guide_weight,
582 const float min,
const float max)
584 const float eps = sqrt_eps * sqrt_eps;
606 int err = CL_SUCCESS;
614 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
619 if(err != CL_SUCCESS)
goto error;
622 if(err != CL_SUCCESS)
goto error;
624 if(err != CL_SUCCESS)
goto error;
626 if(err != CL_SUCCESS)
goto error;
628 if(err != CL_SUCCESS)
goto error;
632 if(err != CL_SUCCESS)
goto error;
634 err =
cl_variances(devid,
width,
height, guide, var_imgg_rr, var_imgg_rg, var_imgg_rb, var_imgg_gg, var_imgg_gb,
635 var_imgg_bb, guide_weight);
636 if(err != CL_SUCCESS)
goto error;
639 if(err != CL_SUCCESS)
goto error;
641 if(err != CL_SUCCESS)
goto error;
643 if(err != CL_SUCCESS)
goto error;
645 if(err != CL_SUCCESS)
goto error;
647 if(err != CL_SUCCESS)
goto error;
649 if(err != CL_SUCCESS)
goto error;
651 if(err != CL_SUCCESS)
goto error;
653 if(err != CL_SUCCESS)
goto error;
655 if(err != CL_SUCCESS)
goto error;
657 if(err != CL_SUCCESS)
goto error;
659 if(err != CL_SUCCESS)
goto error;
661 if(err != CL_SUCCESS)
goto error;
663 if(err != CL_SUCCESS)
goto error;
665 if(err != CL_SUCCESS)
goto error;
667 if(err != CL_SUCCESS)
goto error;
669 if(err != CL_SUCCESS)
goto error;
671 if(err != CL_SUCCESS)
goto error;
673 if(err != CL_SUCCESS)
goto error;
675 err =
cl_solve(devid,
width,
height, img_mean, imgg_mean_r, imgg_mean_g, imgg_mean_b, cov_imgg_img_r,
676 cov_imgg_img_g, cov_imgg_img_b, var_imgg_rr, var_imgg_rg, var_imgg_rb, var_imgg_gg, var_imgg_gb,
677 var_imgg_bb, a_r, a_g, a_b, b);
678 if(err != CL_SUCCESS)
goto error;
681 if(err != CL_SUCCESS)
goto error;
683 if(err != CL_SUCCESS)
goto error;
685 if(err != CL_SUCCESS)
goto error;
687 if(err != CL_SUCCESS)
goto error;
689 err =
cl_generate_result(devid,
width,
height, guide, a_r, a_g, a_b, b,
out, guide_weight,
min,
max);
718 const float sqrt_eps,
719 const float guide_weight,
721 const float min,
const float max)
743 if(err != CL_SUCCESS)
goto error;
745 if(err != CL_SUCCESS)
goto error;
746 if(
guided_filter(guide_host, in_host, out_host,
width,
height,
ch, w, sqrt_eps, guide_weight,
min,
max) != 0)
748 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
752 if(err != CL_SUCCESS)
goto error;
757 return err == CL_SUCCESS ? 0 : 1;
764 const float sqrt_eps,
765 const float guide_weight,
767 const float min,
const float max)
788 int err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
790 err =
guided_filter_cl_impl(devid, guide, in,
out,
width,
height,
ch, w, sqrt_eps, guide_weight,
min,
max);
791 if(err != CL_SUCCESS)
793 if(
guided_filter_cl_fallback(devid, guide, in,
out,
width,
height,
ch, w, sqrt_eps, guide_weight,
min,
max) != 0)
static void error(char *msg)
int dt_box_mean_horizontal(float *const restrict buf, const size_t width, const int ch, const int radius, float *const restrict user_scratch)
int dt_box_mean(float *const buf, const size_t height, const size_t width, const int ch, const int radius, const unsigned iterations)
int dt_box_mean_vertical(float *const buf, const size_t height, const size_t width, const int ch, const int radius)
#define BOXFILTER_KAHAN_SUM
static const float const float const float min
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_guided_filter_init_cl_global(void)
static int cl_generate_result(const int devid, const int width, const int height, cl_mem guide, cl_mem a_r, cl_mem a_g, cl_mem a_b, cl_mem b, cl_mem out, const float guide_weight, const float min, const float max)
static int cl_variances(const int devid, const int width, const int height, cl_mem guide, cl_mem var_imgg_rr, cl_mem var_imgg_rg, cl_mem var_imgg_rb, cl_mem var_imgg_gg, cl_mem var_imgg_gb, cl_mem var_imgg_bb, const float guide_weight)
static int cl_box_mean(const int devid, const int width, const int height, const int w, cl_mem in, cl_mem out, cl_mem temp)
static int guided_filter_cl_fallback(int devid, cl_mem guide, cl_mem in, cl_mem out, const int width, const int height, const int ch, const int w, const float sqrt_eps, const float guide_weight, const float min, const float max)
void dt_guided_filter_free_cl_global(void)
static dt_guided_filter_cl_global_t * _guided_filter_cl_global
static int cl_split_rgb(const int devid, const int width, const int height, cl_mem guide, cl_mem imgg_r, cl_mem imgg_g, cl_mem imgg_b, const float guide_weight)
static float * get_color_pixel(color_image img, size_t i)
static int cl_solve(const int devid, const int width, const int height, cl_mem img_mean, cl_mem imgg_mean_r, cl_mem imgg_mean_g, cl_mem imgg_mean_b, cl_mem cov_imgg_img_r, cl_mem cov_imgg_img_g, cl_mem cov_imgg_img_b, cl_mem var_imgg_rr, cl_mem var_imgg_rg, cl_mem var_imgg_rb, cl_mem var_imgg_gg, cl_mem var_imgg_gb, cl_mem var_imgg_bb, cl_mem a_r, cl_mem a_g, cl_mem a_b, cl_mem b)
static int cl_update_covariance(const int devid, const int width, const int height, cl_mem in, cl_mem out, cl_mem a, cl_mem b, float eps)
static int cl_covariances(const int devid, const int width, const int height, cl_mem guide, cl_mem in, cl_mem cov_imgg_img_r, cl_mem cov_imgg_img_g, cl_mem cov_imgg_img_b, const float guide_weight)
static __DT_CLONE_TARGETS__ int guided_filter_tiling(color_image imgg, gray_image img, gray_image img_out, tile target, const int w, const float eps, const float guide_weight, const float min, const float max)
int guided_filter_cl(int devid, cl_mem guide, cl_mem in, cl_mem out, const int width, const int height, const int ch, const int w, const float sqrt_eps, const float guide_weight, const float min, const float max)
static int guided_filter_cl_impl(int devid, cl_mem guide, cl_mem in, cl_mem out, const int width, const int height, const int ch, const int w, const float sqrt_eps, const float guide_weight, const float min, const float max)
__DT_CLONE_TARGETS__ int guided_filter(const float *const guide, const float *const in, float *const out, const int width, const int height, const int ch, const int w, const float sqrt_eps, const float guide_weight, const float min, const float max)
static int max_i(int a, int b)
static int min_i(int a, int b)
static float kernel(const float *x, const float *y)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
int dt_opencl_create_kernel(const int prog, const char *name)
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)
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_read_host_from_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
void dt_opencl_release_mem_object(cl_mem mem)
int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
#define __OMP_PARALLEL_FOR__(...)
void dt_dev_pixelpipe_cache_flush_clmem(const int devid)
Release cached OpenCL buffers for a single device.
Pixelpipe cache for storing intermediate results in the pixelpipe.
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_get_perthread(buf, padsize)
#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
int kernel_guided_filter_guided_filter_covariances
int kernel_guided_filter_box_mean_x
int kernel_guided_filter_solve
int kernel_guided_filter_generate_result
int kernel_guided_filter_box_mean_y
int kernel_guided_filter_update_covariance
int kernel_guided_filter_guided_filter_variances
int kernel_guided_filter_split_rgb
#define __DT_CLONE_TARGETS__