40 float *
const restrict interp = ctx->
interp;
41 const float *
const restrict mask = ctx->
mask;
42 const float *
const restrict depth = ctx->
depth;
48 float *
const restrict estimate = ctx->
estimate;
49 float *
const restrict valid = ctx->
valid;
50 float *
const restrict clip_depth = ctx->
clip_depth;
51 float *
const restrict clip0 = ctx->
clip0;
55 for(
int y = 0; y < region_h; y++)
56 for(
int x = 0;
x < region_w;
x++)
58 const size_t pixel_index = (size_t)(region->
ry0 + y) *
width + (region->
rx0 +
x);
59 const size_t src_offset = pixel_index * 4;
60 const size_t dst_offset = ((size_t)y * region_w +
x) * 4;
61 clip_depth[(size_t)y * region_w +
x] = depth[pixel_index];
62 for(
int k = 0;
k < 4;
k++)
64 estimate[dst_offset +
k] = interp[src_offset +
k];
65 clip0[dst_offset +
k] = interp[src_offset +
k];
66 valid[dst_offset +
k] = fmaxf(1.f - mask[src_offset +
k], 0.f);
75 for(
size_t i = 0;
i < region_pixels;
i++)
76 for(
int c = 0; c < 3; c++)
77 if(valid[
i * 4 + c] < 0.5f) estimate[
i * 4 + c] = fmaxf(estimate[
i * 4 + c], clip0[
i * 4 + c]);
85 float *
const restrict interp = ctx->
interp;
86 const float *
const restrict mask = ctx->
mask;
92 float *
const restrict estimate = ctx->
estimate;
93 float *
const restrict valid = ctx->
valid;
101 for(
int y = 0; y < region_h; y++)
103 for(
int x = 0;
x < region_w;
x++)
105 const size_t i = ((size_t)y * region_w +
x) * 4;
117 dt_aligned_pixel_t nsigma = { current[0] * noise_level, current[1] * noise_level, current[2] * noise_level,
118 current[3] * noise_level };
124 for(
int c = 0; c < 3; c++)
125 if(valid[
i + c] < 0.5f) estimate[
i + c] = fmaxf(current[c] + fabsf(
noise[c] - current[c]), 0.f);
137 for(
int y = 0; y < region_h; y++)
139 for(
int x = 0;
x < region_w;
x++)
141 const size_t src_offset = ((size_t)y * region_w +
x) * 4;
142 const size_t dst_offset = ((size_t)(region->
ry0 + y) *
width + (region->
rx0 +
x)) * 4;
145 for(
int c = 0; c < 3; c++)
146 if(mask[dst_offset + c] > 0.5f) interp[dst_offset + c] = fmaxf(estimate[src_offset + c], 0.f);
152 const float *
const restrict depth,
const int width,
const _hl_region_t *
const region,
154 const float noise_level,
const float floor_gate,
const float module_scale)
156 const int region_w = region->
rx1 - region->
rx0 + 1;
157 const int region_h = region->
ry1 - region->
ry0 + 1;
158 if(region_w < 2 || region_h < 2)
return;
159 const size_t region_pixels = (size_t)region_w * region_h;
162 if(region_pixels > (
size_t)64 * 1024 * 1024)
return;
164 float *
const restrict estimate
166 float *
const restrict prev_scale
168 float *
const restrict valid
170 float *
const restrict blur_in
172 float *
const restrict plane1
174 float *
const restrict plane2
176 float *
const restrict plane3
178 float *
const restrict valid_variance
180 float *
const restrict guide_score
182 float *
const restrict clip_depth
184 float *
const restrict clip0
186 if(!estimate || !prev_scale || !valid || !blur_in || !plane1 || !plane2 || !plane3 || !valid_variance
187 || !guide_score || !clip_depth || !clip0)
203 const int extent =
MAX(region->
x1 - region->
x0, region->
y1 - region->
y0) + 1;
204 const float epsilon = 1e-6f;
205 const int max_cg_iter = CLAMP(2 * extent, 200, 2000);
213 float *
const restrict solver_field
215 float *
const restrict fill_planes
218 float *
const restrict lum_accum
220 float *
const restrict reaction_weight
222 float *
const restrict flat_target
237 .region_w = region_w,
238 .region_h = region_h,
239 .region_pixels = region_pixels,
241 .scale = module_scale,
243 .max_cg_iter = max_cg_iter,
244 .solid_color = solid_color,
245 .noise_level = noise_level,
246 .floor_gate = floor_gate,
247 .estimate = estimate,
248 .prev_scale = prev_scale,
254 .valid_variance = valid_variance,
255 .guide_score = guide_score,
256 .clip_depth = clip_depth,
259 .solver_field = solver_field,
260 .fill_planes = fill_planes,
261 .dome_lum = dome_lum,
262 .lum_accum = lum_accum,
263 .reaction_weight = reaction_weight,
264 .flat_target = flat_target,
265 .cg_residual = cg_residual,
267 .cg_operator = cg_operator,
274 if(hole && solver_field && fill_planes && dome_lum && lum_accum && reaction_weight && flat_target && cg_residual
275 && cg_dir && cg_operator && cg_tmp1 && cg_tmp2)
321#if defined(HAVE_OPENCL) && DT_HL_COEFF_FIELD && DT_HL_SPARSE_SOLVE && (DT_HL_ANISO_SOLVER == 2)
336cl_int _region_cpu_offload_cl(
const int devid,
void *gd_void, cl_mem interp, cl_mem mask, cl_mem depth,
338 const float solid_color,
const int max_iter,
const float noise_level,
339 const float floor_gate,
const float module_scale)
342 const int region_w = region->
rx1 - region->
rx0 + 1;
343 const int region_h = region->
ry1 - region->
ry0 + 1;
344 if(region_w < 2 || region_h < 2)
return CL_SUCCESS;
345 const size_t region_pixels = (size_t)region_w * region_h;
366 if(cl_err != CL_SUCCESS)
goto out;
370 if(cl_err != CL_SUCCESS)
goto out;
373 float *
const hw_interp = host;
374 const float *
const hw_mask = host + region_pixels * 4;
375 const float *
const hw_depth = host + region_pixels * 8;
378 translated_region.
x0 -= region->
rx0;
379 translated_region.
x1 -= region->
rx0;
380 translated_region.
y0 -= region->
ry0;
381 translated_region.
y1 -= region->
ry0;
382 translated_region.
rx1 -= region->
rx0;
383 translated_region.
ry1 -= region->
ry0;
384 translated_region.
rx0 = 0;
385 translated_region.
ry0 = 0;
387 _region_guided_filter(hw_interp, hw_mask, hw_depth, region_w, &translated_region, pipe, solid_color, max_iter,
388 noise_level, floor_gate, module_scale);
392 if(cl_err != CL_SUCCESS)
goto out;
412cl_int _region_guided_filter_cl(
const int devid,
void *gd_void, cl_mem interp, cl_mem mask, cl_mem depth,
414 const float solid_color,
const float floor_gate,
const float module_scale)
417 const int region_w = region->
rx1 - region->
rx0 + 1;
418 const int region_h = region->
ry1 - region->
ry0 + 1;
419 if(region_w < 2 || region_h < 2)
return CL_SUCCESS;
420 const size_t region_pixels = (size_t)region_w * region_h;
421 if(region_pixels > (
size_t)64 * 1024 * 1024)
return CL_SUCCESS;
436 cl_mem region_worth_dev = NULL;
441 if(!estimate || !valid || !clip0 || !model_quality || !clip_depth || !lsb0 || !partials)
goto out;
461 if(cl_err != CL_SUCCESS)
goto out;
465 const float cf_sigma = CLAMP(region->
radius / 6.f, 8.f, 64.f);
466 const float cf_fmin = 0.05f;
468 float channel_means[3] = { 0.f, 0.f, 0.f };
469 int cdeep, ds_shared;
471 const int local_size = 64, n_groups = 256;
472 const int pixel_count = (int)region_pixels;
474 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
475 size_t local[3] = { local_size, 1, 1 };
482 if(cl_err != CL_SUCCESS)
goto out;
484 float partials_host[8 * 256];
487 if(cl_err != CL_SUCCESS)
goto out;
488 double lsum = 0.0, lcnt = 0.0, clip_count_r = 0.0, clip_count_g = 0.0, clip_count_b = 0.0;
489 double msum[3] = { 0.0, 0.0, 0.0 };
490 for(
int group = 0; group < n_groups; group++)
492 lsum += (
double)partials_host[8 * group + 0];
493 lcnt += (
double)partials_host[8 * group + 1];
494 clip_count_r += (
double)partials_host[8 * group + 2];
495 clip_count_g += (
double)partials_host[8 * group + 3];
496 clip_count_b += (
double)partials_host[8 * group + 4];
497 msum[0] += (
double)partials_host[8 * group + 5];
498 msum[1] += (
double)partials_host[8 * group + 6];
499 msum[2] += (
double)partials_host[8 * group + 7];
506 const float cf_lref = (float)(lsum / lcnt);
507 cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
508 cdeep = (clip_count_r >= clip_count_g && clip_count_r >= clip_count_b)
510 : ((clip_count_g >= clip_count_b) ? 1 : 2);
514 const double valid_count_r = (
double)region_pixels - clip_count_r,
515 valid_count_g = (
double)region_pixels - clip_count_g,
516 valid_count_b = (
double)region_pixels - clip_count_b;
517 channel_means[0] = valid_count_r > 0.5 ? (float)(msum[0] / valid_count_r) : 0.f;
518 channel_means[1] = valid_count_g > 0.5 ? (float)(msum[1] / valid_count_g) : 0.f;
519 channel_means[2] = valid_count_b > 0.5 ? (float)(msum[2] / valid_count_b) : 0.f;
534 const int pixel_count = (int)region_pixels;
535 size_t work_size_1d[3] = {
ROUNDUPDWD(pixel_count, devid), 1, 1 };
541 if(cl_err != CL_SUCCESS)
goto out;
545 cl_err =
_cf_stage_cl(devid, gd_void, estimate, valid, model_quality, lsb0, steer, channel_means, cf_gaussian,
546 region_w, region_h, cf_sigma, cf_fmin, cf_binv, cdeep);
548 if(cl_err != CL_SUCCESS)
goto out;
549 cl_err =
_hf_stage_cl(devid, gd_void, estimate, valid, model_quality, lsb0, steer, cf_gaussian, region_w,
550 region_h, cf_sigma, cf_fmin, cf_binv);
552 if(cl_err != CL_SUCCESS)
goto out;
558 if(!region_worth_dev)
564 const int local_size = 64, n_groups = 256;
565 const int pixel_count = (int)region_pixels;
572 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
573 size_t local[3] = { local_size, 1, 1 };
582 if(cl_err == CL_SUCCESS)
591 size_t one[3] = { 1, 1, 1 };
595 if(cl_err != CL_SUCCESS)
goto out;
603 const int local_size = 64, n_groups = 256;
604 const int pixel_count = (int)region_pixels;
606 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
607 size_t local[3] = { local_size, 1, 1 };
616 if(cl_err != CL_SUCCESS)
goto out;
617 float partials_host[256];
620 if(cl_err != CL_SUCCESS)
goto out;
621 for(
int group = 0; group < n_groups; group++)
622 if(partials_host[group] > 0.f) need_self = 1;
627 cl_err = _selfdome_stage_cl(devid, gd_void, estimate, valid, model_quality, clip0, clip_depth,
628 region_worth_dev, region_w, region_h, cf_sigma, region->
radius, ds_shared,
630 if(cl_err != CL_SUCCESS)
goto out;
645 if(cl_err != CL_SUCCESS)
goto out;
650 const int extent =
MAX(region->
x1 - region->
x0, region->
y1 - region->
y0) + 1;
651 cl_err = _joint_core_stage_cl(devid, gd_void, estimate, valid, clip0, region_w, region_h, solid_color,
652 region->
radius, extent, floor_gate, pipe);
655 if(cl_err != CL_SUCCESS)
goto out;
657 cl_err = _aniso_stage_cl(devid, gd_void, estimate, valid, clip0, region_w, region_h, region->
radius,
658 floor_gate, solid_color, pipe);
660 if(cl_err != CL_SUCCESS)
goto out;
663 cl_err = _chromaticity_gradient_stage_cl(devid, gd_void, estimate, valid, clip0, clip_depth, region_w,
664 region_h, region->
radius, floor_gate, module_scale, pipe);
666 if(cl_err != CL_SUCCESS)
goto out;
dt_gaussian_cl_t * _region_blur_handle(const int devid, const int region_w, const int region_h, const float sigma)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
__DT_CLONE_TARGETS__ void _aniso_chroma(_hl_region_ctx_t *const ctx)
cl_int _cf_stage_cl(const int devid, void *gd_void, cl_mem estimate, cl_mem valid, cl_mem model_quality, cl_mem luminance, cl_mem steer, const float *const restrict channel_means, dt_gaussian_cl_t *gaussian, const int region_w, const int region_h, const float cf_sigma, const float cf_fmin, const float cf_binv, const int cdeep)
__DT_CLONE_TARGETS__ void _cf_reconstruct(_hl_region_ctx_t *const ctx)
cl_int _hf_stage_cl(const int devid, void *gd_void, cl_mem estimate, cl_mem valid, cl_mem model_quality, cl_mem luminance, cl_mem steer, dt_gaussian_cl_t *gaussian, const int region_w, const int region_h, const float cf_sigma, const float cf_fmin, const float cf_binv)
const dt_colormatrix_t dt_aligned_pixel_t out
void _chromaticity_gradient(_hl_region_ctx_t *const ctx)
__DT_CLONE_TARGETS__ void _joint_core(_hl_region_ctx_t *const ctx)
__DT_CLONE_TARGETS__ void _selfdome(_hl_region_ctx_t *const ctx)
static float4 dt_noise_generator_simd(const dt_noise_distribution_t distribution, const float4 mu, const float4 param, uint state[4])
static unsigned int splitmix32(const unsigned long seed)
static float xoshiro128plus(uint state[4])
void dt_gaussian_free_cl(dt_gaussian_cl_t *g)
static float kernel(const float *x, const float *y)
float *const restrict const size_t k
#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_ALIGNED_ARRAY
Align an object on a cacheline boundary, so AVX2 can load it whole.
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_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_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_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_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
void dt_opencl_release_mem_object(cl_mem mem)
#define DT_OPENCL_DEFAULT_ERROR
#define dt_pixelpipe_cache_alloc_align(size, pipe)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
static __DT_CLONE_TARGETS__ void _region_composite(_hl_region_ctx_t *const ctx)
static __DT_CLONE_TARGETS__ void _region_gather(_hl_region_ctx_t *const ctx)
void _region_guided_filter(float *const restrict interp, const float *const restrict mask, const float *const restrict depth, const int width, const _hl_region_t *const region, const dt_dev_pixelpipe_t *pipe, const float solid_color, const int max_iter, const float noise_level, const float floor_gate, const float module_scale)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
#define DT_HL_DOME_NMAX_SPARSE
const float uint32_t state[4]
const float const int flip
const _hl_region_t * region
int kernel_hl_window_unpack
int kernel_hl_region_benefit
int kernel_hl_region_gather
int kernel_hl_region_stats
int kernel_hl_region_worth_finalize
int kernel_hl_window_pack
int kernel_hl_region_scatter
#define __DT_CLONE_TARGETS__
typedef double((*spd)(unsigned long int wavelength, double TempK))