44 const float epsilon = ctx->
epsilon;
45 float *
const restrict estimate = ctx->
estimate;
46 float *
const restrict valid = ctx->
valid;
47 float *
const restrict plane1 = ctx->
plane1;
49 float *
const restrict clip0 = ctx->
clip0;
50 uint8_t *
const restrict hole = ctx->
hole;
52 float *
const restrict dome_lum = ctx->
dome_lum;
53 float *
const restrict lum_accum = ctx->
lum_accum;
54 float *
const restrict flat_target = ctx->
flat_target;
61 for(
size_t i = 0;
i < region_pixels;
i++)
63 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
64 if(!anyvalid)
continue;
65 for(
int c = 0; c < 3; c++)
66 if(valid[
i * 4 + c] < 0.5f && valid_variance[
i * 4 + c] * valid_variance[
i * 4 + c] < 0.9f) need_self = 1;
77 for(
size_t i = 0;
i < region_pixels;
i++)
78 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f) nh_union++;
89 for(
size_t i = 0;
i < region_pixels;
i++)
91 hole[
i] = (valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f);
92 lum_accum[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
93 solver_field[
i] = lum_accum[
i];
100 memcpy(dome_lum, solver_field, region_pixels *
sizeof(
float));
106 const int cf_base = (int)(CLAMP(region->
radius / 6.f, 8.f, 64.f) / 4.f);
108 for(
int c = 0; c < 3; c++)
111 for(
size_t i = 0;
i < region_pixels;
i++)
112 flat_target[
i] = estimate[
i * 4 + c] / fmaxf(lum_accum[
i], epsilon);
117 for(
size_t i = 0;
i < region_pixels;
i++) plane1[
i * 4 + c] = fmaxf(flat_target[
i], 0.f);
124 for(
size_t i = 0;
i < region_pixels;
i++)
126 if(!hole[
i])
continue;
128 const float caccum = fmaxf(plane1[
i * 4 + 0] + plane1[
i * 4 + 1] + plane1[
i * 4 + 2], epsilon);
129 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
131 for(
int c = 0; c < 3; c++)
132 if(valid[
i * 4 + c] < 0.5f)
134 const float dome = dome_lum[
i] * (plane1[
i * 4 + c] / caccum);
135 const float conf_weight = valid_variance[
i * 4 + c] * valid_variance[
i * 4 + c];
136 estimate[
i * 4 + c] = anyvalid ? (conf_weight * estimate[
i * 4 + c] + (1.f - conf_weight) * dome) : dome;
144 for(
size_t i = 0;
i < region_pixels;
i++)
145 for(
int c = 0; c < 3; c++)
146 if(valid[
i * 4 + c] < 0.5f) estimate[
i * 4 + c] = fmaxf(estimate[
i * 4 + c], clip0[
i * 4 + c]);
158 const float epsilon = ctx->
epsilon;
161 float *
const restrict estimate = ctx->
estimate;
162 float *
const restrict valid = ctx->
valid;
163 float *
const restrict plane1 = ctx->
plane1;
164 float *
const restrict clip0 = ctx->
clip0;
165 uint8_t *
const restrict hole = ctx->
hole;
167 float *
const restrict dome_lum = ctx->
dome_lum;
168 float *
const restrict lum_accum = ctx->
lum_accum;
170 float *
const restrict flat_target = ctx->
flat_target;
171 float *
const restrict cg_residual = ctx->
cg_residual;
172 float *
const restrict cg_dir = ctx->
cg_dir;
173 float *
const restrict cg_operator = ctx->
cg_operator;
174 float *
const restrict cg_tmp1 = ctx->
cg_tmp1;
175 float *
const restrict cg_tmp2 = ctx->
cg_tmp2;
192 for(
size_t i = 0;
i < region_pixels;
i++)
194 hole[
i] = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
195 if(hole[
i]) has_allc = 1;
203 for(
size_t i = 0;
i < region_pixels;
i++)
205 lum_accum[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
206 solver_field[
i] = lum_accum[
i];
213 memcpy(dome_lum, solver_field, region_pixels *
sizeof(
float));
221 for(
size_t i = 0;
i < region_pixels;
i++)
226 const float lsat = clip0[
i * 4 + 0] + clip0[
i * 4 + 1] + clip0[
i * 4 + 2];
227 dome_lum[
i] = fmaxf(dome_lum[
i], lsat);
237 double cacc[3] = { 0.0, 0.0, 0.0 };
239 for(
size_t i = 0;
i < region_pixels;
i++)
241 if(!(valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f))
continue;
242 const float invL = 1.f / fmaxf(lum_accum[
i], epsilon);
243 cacc[0] += (
double)(estimate[
i * 4 + 0] * invL);
244 cacc[1] += (
double)(estimate[
i * 4 + 1] * invL);
245 cacc[2] += (
double)(estimate[
i * 4 + 2] * invL);
249 for(
int c = 0; c < 3; c++) cmean[c] = (
float)(cacc[c] / count);
255 const float react = solid_color * solid_color * 4.f;
257 for(
size_t i = 0;
i < region_pixels;
i++) reaction_weight[
i] = react;
261 int *sp_pgrid = NULL;
264 &sp_pgrid, &sp_nh, pipe);
272 for(
int c = 0; c < 3; c++)
275 for(
size_t i = 0;
i < region_pixels;
i++)
280 solver_field[
i] = hole[
i] ? cmean[c] : (estimate[
i * 4 + c] / fmaxf(lum_accum[
i], epsilon));
281 flat_target[
i] = cmean[c];
286 _sp_pde_solve(sp_S, sp_pgrid, solver_field, hole, (react > 0.f) ? reaction_weight : NULL,
287 (react > 0.f) ? flat_target : NULL, NULL, 1, 1.f, region_w, region_h, sp_b, cg_tmp1, cg_tmp2,
291 (react > 0.f) ? flat_target : NULL, NULL, 1, 1.f, region_w, region_h, cg_residual,
292 cg_dir, cg_operator, cg_tmp1, cg_tmp2, max_cg_iter);
295 for(
size_t i = 0;
i < region_pixels;
i++) plane1[
i * 4 + c] = fmaxf(solver_field[
i], 0.f);
309 for(
size_t i = 0;
i < region_pixels;
i++) solver_field[
i] = hole[
i] ? 1.f : 0.f;
311 _knee_blur(solver_field, reaction_weight, region_w, region_h,
312 fmaxf(4.f, CLAMP(region->
radius / 6.f, 8.f, 64.f) / 4.f));
315 for(
size_t i = 0;
i < region_pixels;
i++)
317 const float fit_weight = CLAMP(reaction_weight[
i], 0.f, 1.f);
318 const float caccum = fmaxf(plane1[
i * 4 + 0] + plane1[
i * 4 + 1] + plane1[
i * 4 + 2], epsilon);
323 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = dome_lum[
i] * (plane1[
i * 4 + c] / caccum);
325 else if(fit_weight > 1e-4f)
329 for(
int c = 0; c < 3; c++)
330 if(valid[
i * 4 + c] < 0.5f)
331 estimate[
i * 4 + c] = fit_weight * dome_lum[
i] * (plane1[
i * 4 + c] / caccum)
332 + (1.f - fit_weight) * estimate[
i * 4 + c];
340#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE
341cl_int _selfdome_stage_cl(
const int devid,
void *gd_void, cl_mem estimate, cl_mem valid, cl_mem model_quality,
342 cl_mem clip0, cl_mem depth,
const int region_w,
const int region_h,
const float cf_sigma,
346 const size_t region_pixels = (size_t)region_w * region_h;
349 const float epsilon = 1e-6f;
361 if(!
luminance || !hole || !dome_lum || !ratio0 || !ratio1 || !ratio2)
goto out;
372 if(cl_err != CL_SUCCESS)
goto out;
378 const int allmode = 0;
387 if(cl_err != CL_SUCCESS)
goto out;
393 const char *reg_dump_path = getenv(
"HL_REG_DUMP");
394 if(reg_dump_path && reg_dump_path[0])
398 if(dump_data && dump_hole
403 FILE *dump_file = g_fopen(reg_dump_path,
"wb");
406 fwrite(®ion_w,
sizeof(
int), 1, dump_file);
407 fwrite(®ion_h,
sizeof(
int), 1, dump_file);
408 const int downsample_val = ds_shared;
409 fwrite(&downsample_val,
sizeof(
int), 1, dump_file);
410 fwrite(dump_data,
sizeof(
float), region_pixels, dump_file);
411 fwrite(dump_hole, 1, region_pixels, dump_file);
421 if(cl_err != CL_SUCCESS)
goto out;
422 cl_err = _biharmonic_dome_cl(devid, gd_void, dome_lum, hole, region_w, region_h, ds_shared, pipe);
423 if(cl_err != CL_SUCCESS)
goto out;
427 const int cf_base = (int)(CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f);
428 for(
int c = 0;
c < 3 && cl_err == CL_SUCCESS;
c++)
439 if(cl_err == CL_SUCCESS)
440 cl_err =
_cf_harmonic_fill_cl(devid, gd_void, ratios[c], hole, region_w, region_h, cf_base, 1, NULL);
442 if(cl_err != CL_SUCCESS)
goto out;
463 if(cl_err != CL_SUCCESS)
goto out;
489#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE
493#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE
494cl_int _joint_core_stage_cl(
const int devid,
void *gd_void, cl_mem estimate, cl_mem valid, cl_mem clip0,
495 const int region_w,
const int region_h,
const float solid_color,
499 const size_t region_pixels = (size_t)region_w * region_h;
502 const float epsilon = 1e-6f;
504 = solid_color * solid_color * 4.f;
520 cl_mem partial_sums = NULL, perm_grid_dev = NULL, rhs_dev = NULL, mask_img = NULL, mask_blur = NULL;
522 int *matrix_col_ptr = NULL, *matrix_row_index = NULL, *perm_grid = NULL;
523 double *matrix_values = NULL;
526 if(!
luminance || !hole || !dome_lum || !embedded || !ratio0 || !ratio1 || !ratio2 || !cg_field || !hole_mask)
532 const int all_clip_mode = 1;
541 if(cl_err != CL_SUCCESS)
goto out;
547 if(cl_err != CL_SUCCESS)
goto out;
549 size_t n_hole_fine = 0;
550 for(
size_t i = 0;
i < region_pixels;
i++)
551 if(hole_mask[
i]) n_hole_fine++;
562 if(cl_err != CL_SUCCESS)
goto out;
563 cl_err = _biharmonic_dome_cl(devid, gd_void, dome_lum, hole, region_w, region_h, downsample, pipe);
564 if(cl_err != CL_SUCCESS)
goto out;
573 if(cl_err != CL_SUCCESS)
goto out;
578 const int local_size = 64, n_groups = 256;
579 const int n_pixels = (int)region_pixels;
587 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
588 size_t local[3] = { local_size, 1, 1 };
597 if(cl_err != CL_SUCCESS)
goto out;
599 float partial_host[4 * 256];
602 if(cl_err != CL_SUCCESS)
goto out;
603 double accum[4] = { 0.0, 0.0, 0.0, 0.0 };
604 for(
int group = 0; group < n_groups; group++)
605 for(
int k = 0;
k < 4;
k++) accum[
k] += (
double)partial_host[group * 4 +
k];
607 for(
int c = 0;
c < 3;
c++) chroma_mean[c] = (
float)(accum[
c] / accum[3]);
617 = !
_sp_pde_assemble(hole_mask, NULL, (react > 0.f) ? react : 0.f, 1, 1.f, region_w, region_h,
618 &matrix_col_ptr, &matrix_row_index, &matrix_values, &perm_grid, &n_unknowns, pipe);
627 else if(!perm_grid_dev || !rhs_dev)
633 const int max_iter = CLAMP(2 * extent, 200, 2000);
636 for(
int c = 0;
c < 3;
c++)
653 if(cl_err != CL_SUCCESS)
goto out;
659 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
669 if(cl_err != CL_SUCCESS)
goto out;
685 int finite = (solution_check != NULL);
691 for(
int check_index = 0; finite && check_index < n_unknowns; check_index++)
692 if(!isfinite(solution_check[check_index])) finite = 0;
705 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
711 if(cl_err != CL_SUCCESS)
goto out;
718 cl_err = _region_pde_cg_cl(devid, gd_void, cg_field, hole, region_w, region_h, (react > 0.f) ? react : 0.f,
719 (react > 0.f) ? chroma_mean[
c] : 0.f, max_iter);
720 if(cl_err != CL_SUCCESS)
goto out;
727 if(cl_err != CL_SUCCESS)
goto out;
735 if(!mask_img || !mask_blur)
747 if(cl_err != CL_SUCCESS)
goto out;
749 cl_err = _region_blur1_cl(devid, mask_img, mask_blur, region_w, region_h,
750 fmaxf(4.f, CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f));
751 if(cl_err != CL_SUCCESS)
goto out;
cl_int _cf_harmonic_fill_cl(const int devid, void *gd_void, cl_mem val, cl_mem hole, const int region_w, const int region_h, const int base_ds, const int mask_is_hole, cl_mem steer)
void _cf_harmonic_fill(float *const restrict val, const uint8_t *const restrict hole, const int region_w, const int region_h, const int base_ds, const float *const restrict steer, const dt_dev_pixelpipe_t *pipe)
const dt_colormatrix_t dt_aligned_pixel_t out
__DT_CLONE_TARGETS__ void _joint_core(_hl_region_ctx_t *const ctx)
__DT_CLONE_TARGETS__ void _selfdome(_hl_region_ctx_t *const ctx)
#define dt_pixelpipe_cache_alloc_align(size, pipe)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
__DT_CLONE_TARGETS__ void _biharmonic_dome(float *const restrict field, const uint8_t *const restrict hole, const int region_w, const int region_h, const int forced_downsample, const dt_dev_pixelpipe_t *pipe)
static float kernel(const float *x, const float *y)
static void _knee_blur(const float *const restrict in, float *const restrict out, const int width, const int height, const float sigma)
float *const restrict luminance
float *const restrict const size_t k
float dt_aligned_pixel_t[4]
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)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
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)
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)
#define DT_OPENCL_DEFAULT_ERROR
__DT_CLONE_TARGETS__ void _region_pde_solve(float *const restrict field, const uint8_t *const restrict hole, const float *const restrict diffusion, const float *const restrict target, const float *const restrict source, const int order, const float lambda, const int region_w, const int region_h, float *const restrict residual, float *const restrict search_dir, float *const restrict operator_dir, float *const restrict embedded, float *const restrict scratch, const int maxiter)
_sp_chol_t * _sp_pde_factor(const uint8_t *const restrict hole, const float *const restrict diffusion, const int order, const float lambda, const int region_w, const int region_h, int **perm_out, int *n_unknowns_out, const dt_dev_pixelpipe_t *pipe)
__DT_CLONE_TARGETS__ void _sp_pde_solve(const _sp_chol_t *const factor, const int *const restrict perm_grid, float *const restrict field, const uint8_t *const restrict hole, const float *const restrict diffusion, const float *const restrict target, const float *const restrict source, const int order, const float lambda, const int region_w, const int region_h, double *const restrict rhs, float *const restrict embedded, float *const restrict operator_out, float *const restrict scratch)
int _sp_pde_assemble(const uint8_t *const restrict hole, const float *const restrict diffusion, const float diffusion_const, const int order, const float lambda, const int region_w, const int region_h, int **matrix_col_ptr_out, int **matrix_row_index_out, double **matrix_values_out, int **perm_grid_out, int *n_unknowns_out, const dt_dev_pixelpipe_t *const pipe)
static _sp_chol_cl_kernels_t _hl_sp_chol_kernels(void *gd_void)
static void _sp_chol_free(_sp_chol_t *factor)
static void _sp_chol_cl_free(_sp_chol_cl_t *factor)
static _sp_chol_cl_t * _sp_chol_factor_cl(const int devid, const _sp_chol_cl_kernels_t kernels, const int dimension, const int *const restrict matrix_col_ptr, const int *const restrict matrix_row_index, const double *const restrict matrix_values)
static int _sp_chol_solve_cl(const _sp_chol_cl_t *const factor, const _sp_chol_cl_kernels_t kernels, cl_mem rhs)
static cl_mem _sp_cl_upload(const int devid, const void *data, const size_t bytes)
#define DT_HL_DOME_NMAX_SPARSE
const _hl_region_t * region
const dt_dev_pixelpipe_t * pipe
int kernel_hl_pde_scatter
int kernel_hl_ratio_plane
int kernel_hl_cmean_reduce
int kernel_hl_mask_to_img1
typedef double((*spd)(unsigned long int wavelength, double TempK))