31#include <glib/gstdio.h>
43 const float epsilon = ctx->
epsilon;
44 float *
const restrict estimate = ctx->
estimate;
45 float *
const restrict valid = ctx->
valid;
46 float *
const restrict plane1 = ctx->
plane1;
48 float *
const restrict clip0 = ctx->
clip0;
49 uint8_t *
const restrict hole = ctx->
hole;
51 float *
const restrict dome_lum = ctx->
dome_lum;
52 float *
const restrict lum_accum = ctx->
lum_accum;
53 float *
const restrict flat_target = ctx->
flat_target;
60 for(
size_t i = 0;
i < region_pixels;
i++)
62 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
63 if(!anyvalid)
continue;
64 for(
int c = 0; c < 3; c++)
65 if(valid[
i * 4 + c] < 0.5f && valid_variance[
i * 4 + c] * valid_variance[
i * 4 + c] < 0.9f) need_self = 1;
76 for(
size_t i = 0;
i < region_pixels;
i++)
77 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f) nh_union++;
88 for(
size_t i = 0;
i < region_pixels;
i++)
90 hole[
i] = (valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f);
91 lum_accum[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
92 solver_field[
i] = lum_accum[
i];
99 memcpy(dome_lum, solver_field, region_pixels *
sizeof(
float));
105 const int cf_base = (int)(CLAMP(region->
radius / 6.f, 8.f, 64.f) / 4.f);
112 float cmean_beta = 0.f;
113 float refine_gate = 0.f;
114 if(floor_gate > 1e-6f)
120 double plateau_sum = 0.0, plateau_count = 0.0;
121 for(
size_t i = 0;
i < region_pixels;
i++)
124 plateau_sum += (
double)lum_accum[
i];
125 plateau_count += 1.0;
127 const float lum_min = (plateau_count > 0.0) ? 0.35f * (
float)(plateau_sum / plateau_count) : 0.f;
128 double cmean_accum[3] = { 0.0, 0.0, 0.0 };
129 double cmean_count = 0.0;
130 for(
size_t i = 0;
i < region_pixels;
i++)
131 if(!hole[
i] && lum_accum[
i] >= lum_min)
133 const float inv_lum = 1.f / fmaxf(lum_accum[
i], epsilon);
134 cmean_accum[0] += (
double)(estimate[
i * 4 + 0] * inv_lum);
135 cmean_accum[1] += (
double)(estimate[
i * 4 + 1] * inv_lum);
136 cmean_accum[2] += (
double)(estimate[
i * 4 + 2] * inv_lum);
139 if(cmean_count > 0.0)
141 for(
int c = 0; c < 3; c++) cmean[c] = (
float)(cmean_accum[c] / cmean_count);
147 cmean_beta = 0.5f * refine_gate;
151 for(
int c = 0; c < 3; c++)
154 for(
size_t i = 0;
i < region_pixels;
i++)
155 flat_target[
i] = estimate[
i * 4 + c] / fmaxf(lum_accum[
i], epsilon);
160 for(
size_t i = 0;
i < region_pixels;
i++)
162 float ratio = fmaxf(flat_target[
i], 0.f);
163 if(hole[
i] && cmean_beta > 0.f) ratio = (1.f - cmean_beta) * ratio + cmean_beta * cmean[c];
164 plane1[
i * 4 + c] = ratio;
177 for(
size_t i = 0;
i < region_pixels;
i++)
179 if(!hole[
i])
continue;
181 const float caccum = fmaxf(plane1[
i * 4 + 0] + plane1[
i * 4 + 1] + plane1[
i * 4 + 2], epsilon);
182 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
184 float blended_sub = 0.f, dome_sub = 0.f;
188 float per_channel_blend[3] = { 0.f, 0.f, 0.f };
189 for(
int c = 0; c < 3; c++)
190 if(valid[
i * 4 + c] < 0.5f)
192 const float dome = dome_lum[
i] * (plane1[
i * 4 + c] / caccum);
193 const float conf_weight = valid_variance[
i * 4 + c] * valid_variance[
i * 4 + c];
194 per_channel_blend[c] = anyvalid ? (conf_weight * estimate[
i * 4 + c] + (1.f - conf_weight) * dome) : dome;
195 blended_sub += per_channel_blend[c];
198 for(
int c = 0; c < 3; c++)
199 if(valid[
i * 4 + c] < 0.5f)
201 if(refine_gate <= 1e-6f || !anyvalid || dome_sub <= epsilon)
203 estimate[
i * 4 + c] = per_channel_blend[c];
206 const float decoupled = blended_sub * (dome_lum[
i] * (plane1[
i * 4 + c] / caccum) / dome_sub);
207 estimate[
i * 4 + c] = refine_gate * decoupled + (1.f - refine_gate) * per_channel_blend[c];
216 for(
size_t i = 0;
i < region_pixels;
i++)
219 if(floor_gate > 1e-6f)
220 for(
int c = 0; c < 3; c++)
221 if(valid[
i * 4 + c] < 0.5f)
223 const float e = fmaxf(estimate[
i * 4 + c], 1e-6f);
224 lift = fmaxf(lift, fminf(fmaxf(e, clip0[
i * 4 + c]) / e, 8.f));
232 float per_chan_v[3], joint_v[3];
233 for(
int c = 0; c < 3; c++)
235 per_chan_v[c] = joint_v[c] = estimate[
i * 4 + c];
236 if(valid[
i * 4 + c] >= 0.5f)
continue;
237 per_chan_v[c] = fmaxf(estimate[
i * 4 + c], clip0[
i * 4 + c]);
238 joint_v[c] = fmaxf(fmaxf(estimate[
i * 4 + c], 1e-6f) * lift, clip0[
i * 4 + c]);
240 if(floor_gate <= 1e-6f)
242 for(
int c = 0; c < 3; c++)
243 if(valid[
i * 4 + c] < 0.5f) estimate[
i * 4 + c] = per_chan_v[c];
247 float sum_p = 0.f, sum_j = 0.f;
248 for(
int c = 0; c < 3; c++)
250 sum_p += per_chan_v[c];
253 sum_p = fmaxf(sum_p, 1e-9f);
254 sum_j = fmaxf(sum_j, 1e-9f);
255 float chroma_gain = 0.f;
256 for(
int c = 0; c < 3; c++) chroma_gain += fabsf(joint_v[c] / sum_j - per_chan_v[c] / sum_p);
258 for(
int c = 0; c < 3; c++)
259 if(valid[
i * 4 + c] < 0.5f)
260 estimate[
i * 4 + c] = per_chan_v[c] + w * (joint_v[c] - per_chan_v[c]);
274 const float epsilon = ctx->
epsilon;
277 float *
const restrict estimate = ctx->
estimate;
278 float *
const restrict valid = ctx->
valid;
279 float *
const restrict plane1 = ctx->
plane1;
280 float *
const restrict clip0 = ctx->
clip0;
281 uint8_t *
const restrict hole = ctx->
hole;
283 float *
const restrict dome_lum = ctx->
dome_lum;
284 float *
const restrict lum_accum = ctx->
lum_accum;
286 float *
const restrict flat_target = ctx->
flat_target;
287 float *
const restrict cg_residual = ctx->
cg_residual;
288 float *
const restrict cg_dir = ctx->
cg_dir;
289 float *
const restrict cg_operator = ctx->
cg_operator;
290 float *
const restrict cg_tmp1 = ctx->
cg_tmp1;
291 float *
const restrict cg_tmp2 = ctx->
cg_tmp2;
308 for(
size_t i = 0;
i < region_pixels;
i++)
310 hole[
i] = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
311 if(hole[
i]) has_allc = 1;
319 for(
size_t i = 0;
i < region_pixels;
i++)
321 lum_accum[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
322 solver_field[
i] = lum_accum[
i];
329 memcpy(dome_lum, solver_field, region_pixels *
sizeof(
float));
337 for(
size_t i = 0;
i < region_pixels;
i++)
342 const float lsat = clip0[
i * 4 + 0] + clip0[
i * 4 + 1] + clip0[
i * 4 + 2];
343 dome_lum[
i] = fmaxf(dome_lum[
i], lsat);
353 double cacc[3] = { 0.0, 0.0, 0.0 };
355 for(
size_t i = 0;
i < region_pixels;
i++)
357 if(!(valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f))
continue;
358 const float invL = 1.f / fmaxf(lum_accum[
i], epsilon);
359 cacc[0] += (
double)(estimate[
i * 4 + 0] * invL);
360 cacc[1] += (
double)(estimate[
i * 4 + 1] * invL);
361 cacc[2] += (
double)(estimate[
i * 4 + 2] * invL);
365 for(
int c = 0; c < 3; c++) cmean[c] = (
float)(cacc[c] / count);
379 double bright_count = 0.0;
382 double plateau_sum = 0.0, plateau_count = 0.0;
383 for(
size_t i = 0;
i < region_pixels;
i++)
384 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f)
386 plateau_sum += (
double)lum_accum[
i];
387 plateau_count += 1.0;
389 const float lum_min = (plateau_count > 0.0) ? 0.35f * (
float)(plateau_sum / plateau_count) : 0.f;
390 double bright_accum[3] = { 0.0, 0.0, 0.0 };
391 for(
size_t i = 0;
i < region_pixels;
i++)
393 if(!(valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f))
continue;
394 if(lum_accum[
i] < lum_min)
continue;
395 const float invL = 1.f / fmaxf(lum_accum[
i], epsilon);
396 bright_accum[0] += (
double)(estimate[
i * 4 + 0] * invL);
397 bright_accum[1] += (
double)(estimate[
i * 4 + 1] * invL);
398 bright_accum[2] += (
double)(estimate[
i * 4 + 2] * invL);
401 if(bright_count > 0.0)
402 for(
int c = 0; c < 3; c++) cmean_bright[c] = (
float)(bright_accum[c] / bright_count);
404 const float rehue_gate
405 = (bright_count > 0.0 && ctx->
floor_gate > 1e-6f)
408 if(rehue_gate > 1e-6f)
411 for(
size_t i = 0;
i < region_pixels;
i++)
414 const float lsat = clip0[
i * 4 + 0] + clip0[
i * 4 + 1] + clip0[
i * 4 + 2];
415 for(
int c = 0; c < 3; c++)
416 clip0[
i * 4 + c] = rehue_gate * (lsat * cmean_bright[c]) + (1.f - rehue_gate) * clip0[
i * 4 + c];
424 const float react = solid_color * solid_color * 4.f;
426 for(
size_t i = 0;
i < region_pixels;
i++) reaction_weight[
i] = react;
430 int *sp_pgrid = NULL;
433 &sp_pgrid, &sp_nh, pipe);
441 for(
int c = 0; c < 3; c++)
444 for(
size_t i = 0;
i < region_pixels;
i++)
449 solver_field[
i] = hole[
i] ? cmean[c] : (estimate[
i * 4 + c] / fmaxf(lum_accum[
i], epsilon));
450 flat_target[
i] = cmean[c];
455 _sp_pde_solve(sp_S, sp_pgrid, solver_field, hole, (react > 0.f) ? reaction_weight : NULL,
456 (react > 0.f) ? flat_target : NULL, NULL, 1, 1.f, region_w, region_h, sp_b, cg_tmp1, cg_tmp2,
460 (react > 0.f) ? flat_target : NULL, NULL, 1, 1.f, region_w, region_h, cg_residual,
461 cg_dir, cg_operator, cg_tmp1, cg_tmp2, max_cg_iter);
464 for(
size_t i = 0;
i < region_pixels;
i++) plane1[
i * 4 + c] = fmaxf(solver_field[
i], 0.f);
478 for(
size_t i = 0;
i < region_pixels;
i++) solver_field[
i] = hole[
i] ? 1.f : 0.f;
480 _knee_blur(solver_field, reaction_weight, region_w, region_h,
481 fmaxf(4.f, CLAMP(region->
radius / 6.f, 8.f, 64.f) / 4.f));
484 for(
size_t i = 0;
i < region_pixels;
i++)
486 const float fit_weight = CLAMP(reaction_weight[
i], 0.f, 1.f);
487 const float caccum = fmaxf(plane1[
i * 4 + 0] + plane1[
i * 4 + 1] + plane1[
i * 4 + 2], epsilon);
492 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = dome_lum[
i] * (plane1[
i * 4 + c] / caccum);
494 else if(fit_weight > 1e-4f)
498 for(
int c = 0; c < 3; c++)
499 if(valid[
i * 4 + c] < 0.5f)
500 estimate[
i * 4 + c] = fit_weight * dome_lum[
i] * (plane1[
i * 4 + c] / caccum)
501 + (1.f - fit_weight) * estimate[
i * 4 + c];
515 const float epsilon = ctx->
epsilon;
516 float *
const restrict estimate = ctx->
estimate;
517 float *
const restrict valid = ctx->
valid;
518 float *
const restrict clip0 = ctx->
clip0;
519 float *
const restrict plane2 = ctx->
plane2;
521 uint8_t *
const restrict hole = ctx->
hole;
522 float *
const restrict gate_src = ctx->
cg_tmp1;
523 float *
const restrict gate_msk = ctx->
cg_tmp2;
525 float *
const restrict gate_nrm = ctx->
cg_dir;
532 double plateau_accum = 0.0;
533 size_t plateau_count = 0;
534 for(
size_t i = 0;
i < region_pixels;
i++)
535 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f)
537 plateau_accum += (
double)(estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2]);
540 if(plateau_count == 0)
return;
541 const float lum_anchor_min = 0.35f * (float)(plateau_accum / (
double)plateau_count);
547 float *
const restrict guard_src = ctx->
flat_target;
550 for(
size_t i = 0;
i < region_pixels;
i++)
552 = (valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f) ? 1.f : 0.f;
555 const float guard_sigma = 4.f;
556 _knee_blur(guard_src, guard_blur, region_w, region_h, guard_sigma);
559 HL_PFOR(reduction(+ : n_anchor))
560 for(
size_t i = 0;
i < region_pixels;
i++)
562 const int fully_valid
563 = (valid[
i * 4 + 0] >= 0.5f) && (valid[
i * 4 + 1] >= 0.5f) && (valid[
i * 4 + 2] >= 0.5f);
564 const float lum = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
565 const int anchor = fully_valid && (lum >= lum_anchor_min) && (guard_blur[
i] < 0.05f);
570 if(n_anchor < 64 || n_anchor < region_pixels / 256)
return;
573 for(
int c = 0; c < 3; c++)
576 for(
size_t i = 0;
i < region_pixels;
i++)
578 const float lum = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
579 solver_field[
i] = estimate[
i * 4 + c] / fmaxf(lum, epsilon);
583 for(
size_t i = 0;
i < region_pixels;
i++)
584 plane2[
i * 4 + c] = CLAMP(solver_field[
i], 0.f, 1.f);
597 const float gate_tau = 0.10f;
599 for(
size_t i = 0;
i < region_pixels;
i++)
601 const int n_clip = (valid[
i * 4 + 0] < 0.5f) + (valid[
i * 4 + 1] < 0.5f) + (valid[
i * 4 + 2] < 0.5f);
602 float weight_src = 0.f, mask_src = 0.f;
616 const int cc = (valid[
i * 4 + 0] < 0.5f) ? 0 : ((valid[
i * 4 + 1] < 0.5f) ? 1 : 2);
617 const int m1 = (cc == 0) ? 1 : 0, m2 = (cc == 2) ? 1 : 2;
618 const float msum = estimate[
i * 4 + m1] + estimate[
i * 4 + m2];
619 const float meas = estimate[
i * 4 + m1] / fmaxf(msum, epsilon);
620 const float fld = plane2[
i * 4 + m1] / fmaxf(plane2[
i * 4 + m1] + plane2[
i * 4 + m2], epsilon);
621 const float t = (meas - fld) / (0.5f * gate_tau);
622 weight_src = expf(-
t *
t);
625 gate_src[
i] = weight_src;
626 gate_msk[
i] = mask_src;
628 const float gate_sigma = CLAMP(ctx->
region->
radius / 4.f, 8.f, 96.f);
629 _knee_blur(gate_src, gate_wgt, region_w, region_h, gate_sigma);
630 _knee_blur(gate_msk, gate_nrm, region_w, region_h, gate_sigma);
636 double vote_wsum = 0.0, vote_msum = 0.0;
637 for(
size_t i = 0;
i < region_pixels;
i++)
639 vote_wsum += (
double)gate_src[
i];
640 vote_msum += (
double)gate_msk[
i];
642 const float gate_vote = (vote_msum > 0.0) ? (
float)(vote_wsum / vote_msum) : 0.f;
646 for(
size_t i = 0;
i < region_pixels;
i++)
648 const int clip_r = valid[
i * 4 + 0] < 0.5f;
649 const int clip_g = valid[
i * 4 + 1] < 0.5f;
650 const int clip_b = valid[
i * 4 + 2] < 0.5f;
651 const int n_clip = clip_r + clip_g + clip_b;
668 float authored_w = 1.f;
676 const int cc = clip_r ? 0 : (clip_g ? 1 : 2);
677 const float lift = estimate[
i * 4 + cc] / fmaxf(clip0[
i * 4 + cc], 1e-9f);
679 authored_w = 1.f - CLAMP(over * over * (3.f - 2.f * over), 0.f, 1.f);
681 if(authored_w <= 1e-4f)
continue;
685 const float gate_lambda = 0.05f;
687 = CLAMP((gate_wgt[
i] + gate_lambda * gate_vote) / (gate_nrm[
i] + gate_lambda), 0.f, 1.f);
688 if(gate_w <= 1e-4f)
continue;
690 const float share_sum = fmaxf(plane2[
i * 4 + 0] + plane2[
i * 4 + 1] + plane2[
i * 4 + 2], epsilon);
691 const int anyvalid = !(clip_r && clip_g && clip_b);
700 float sv_est = 0.f, sv_share = 0.f;
701 for(
int c = 0; c < 3; c++)
702 if(valid[
i * 4 + c] >= 0.5f)
704 sv_est += estimate[
i * 4 + c];
705 sv_share += plane2[
i * 4 + c] / share_sum;
707 if(sv_share <= epsilon || sv_est <= epsilon)
continue;
711 = fminf(sv_est / sv_share, 4.f * (estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2]));
712 const float reproject_w = gate_w * authored_w;
713 for(
int c = 0; c < 3; c++)
714 if(valid[
i * 4 + c] < 0.5f)
715 estimate[
i * 4 + c] = reproject_w * (scale * (plane2[
i * 4 + c] / share_sum))
716 + (1.f - reproject_w) * estimate[
i * 4 + c];
731 for(
int c = 0; c < 3; c++)
732 if(valid[
i * 4 + c] < 0.5f)
734 const float e = fmaxf(estimate[
i * 4 + c], 1e-6f);
735 lift = fmaxf(lift, fminf(fmaxf(e, clip0[
i * 4 + c]) / e, 8.f));
737 for(
int c = 0; c < 3; c++)
738 if(valid[
i * 4 + c] < 0.5f)
740 if(lift > 1.f) estimate[
i * 4 + c] = fmaxf(estimate[
i * 4 + c], 1e-6f) * lift;
741 estimate[
i * 4 + c] = fmaxf(estimate[
i * 4 + c], clip0[
i * 4 + c]);
759 for(
int c = 0; c < 3; c++)
762 float *
const restrict authored = gate_src;
763 HL_PFOR(reduction(+ : n_hole_c))
764 for(
size_t i = 0;
i < region_pixels;
i++)
766 const int clip_r = valid[
i * 4 + 0] < 0.5f;
767 const int clip_g = valid[
i * 4 + 1] < 0.5f;
768 const int clip_b = valid[
i * 4 + 2] < 0.5f;
769 const int cc = clip_r ? 0 : (clip_g ? 1 : 2);
780 const int is_hole = (clip_r + clip_g + clip_b == 1) && (cc == c)
782 && (estimate[
i * 4 + c] <= 1.03f * fmaxf(clip0[
i * 4 + c], 1e-9f));
783 authored[
i] = is_hole ? 1.f : 0.f;
791 const float lum = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
792 const int too_dark_to_anchor = !is_hole && (lum < lum_anchor_min);
793 hole[
i] = is_hole || too_dark_to_anchor;
794 solver_field[
i] = estimate[
i * 4 + c];
797 if(n_hole_c == 0)
continue;
800 for(
size_t i = 0;
i < region_pixels;
i++)
801 if(authored[
i] > 0.5f) estimate[
i * 4 + c] = fmaxf(solver_field[
i], clip0[
i * 4 + c]);
809#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE
810cl_int _selfdome_stage_cl(
const int devid,
void *gd_void, cl_mem estimate, cl_mem valid, cl_mem model_quality,
811 cl_mem clip0, cl_mem depth, cl_mem region_worth,
const int region_w,
const int region_h,
812 const float cf_sigma,
const float reg_radius,
const int ds_shared,
816 const size_t region_pixels = (size_t)region_w * region_h;
819 const float epsilon = 1e-6f;
838 cl_mem partial_sums = NULL;
839 cl_mem lum_min_dev = NULL;
840 cl_mem cmean_dev = NULL;
841 cl_mem refine_dev = NULL;
842 if(!
luminance || !hole || !dome_lum || !ratio0 || !ratio1 || !ratio2)
goto out;
857 if(cl_err != CL_SUCCESS)
goto out;
863 const int allmode = 0;
872 if(cl_err != CL_SUCCESS)
goto out;
881 if(floor_gate > 1e-6f)
883 const int local_size = 64, n_groups = 256;
884 const int n_pixels = (int)region_pixels;
889 if(!partial_sums || !lum_min_dev || !cmean_dev || !refine_dev)
894 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
895 size_t local[3] = { local_size, 1, 1 };
909 if(cl_err != CL_SUCCESS)
goto out;
911 const int fin_stride = 2, fin_mode = 1;
912 const float fin_scale = 0.35f;
919 size_t fin_size[3] = { 1, 1, 1 };
921 if(cl_err != CL_SUCCESS)
goto out;
934 if(cl_err != CL_SUCCESS)
goto out;
945 size_t one[3] = { 1, 1, 1 };
947 if(cl_err != CL_SUCCESS)
goto out;
956 if(cl_err != CL_SUCCESS)
goto out;
965 if(cl_err != CL_SUCCESS)
goto out;
972 const char *reg_dump_path = getenv(
"HL_REG_DUMP");
973 if(reg_dump_path && reg_dump_path[0])
977 if(dump_data && dump_hole
982 FILE *dump_file = g_fopen(reg_dump_path,
"wb");
985 fwrite(®ion_w,
sizeof(
int), 1, dump_file);
986 fwrite(®ion_h,
sizeof(
int), 1, dump_file);
987 const int downsample_val = ds_shared;
988 fwrite(&downsample_val,
sizeof(
int), 1, dump_file);
989 fwrite(dump_data,
sizeof(
float), region_pixels, dump_file);
990 fwrite(dump_hole, 1, region_pixels, dump_file);
1000 if(cl_err != CL_SUCCESS)
goto out;
1001 cl_err = _biharmonic_dome_cl(devid, gd_void, dome_lum, hole, region_w, region_h, ds_shared, pipe);
1002 if(cl_err != CL_SUCCESS)
goto out;
1006 const int cf_base = (int)(CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f);
1007 for(
int c = 0;
c < 3 && cl_err == CL_SUCCESS;
c++)
1018 if(cl_err == CL_SUCCESS)
1019 cl_err =
_cf_harmonic_fill_cl(devid, gd_void, ratios[c], hole, region_w, region_h, cf_base, 1, NULL);
1020 if(cl_err == CL_SUCCESS && floor_gate > 1e-6f)
1036 if(cl_err != CL_SUCCESS)
goto out;
1058 if(cl_err != CL_SUCCESS)
goto out;
1092#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE
1096#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE
1097cl_int _joint_core_stage_cl(
const int devid,
void *gd_void, cl_mem estimate, cl_mem valid, cl_mem clip0,
1098 const int region_w,
const int region_h,
const float solid_color,
1099 const float reg_radius,
const int extent,
const float floor_gate,
1103 const size_t region_pixels = (size_t)region_w * region_h;
1106 const float epsilon = 1e-6f;
1108 = solid_color * solid_color * 4.f;
1124 cl_mem partial_sums = NULL, perm_grid_dev = NULL, rhs_dev = NULL, mask_img = NULL, mask_blur = NULL;
1125 cl_mem lum_min_dev2 = NULL, zero_dev = NULL;
1126 cl_mem bright_dev = NULL, rehue_dev = NULL;
1128 int *matrix_col_ptr = NULL, *matrix_row_index = NULL, *perm_grid = NULL;
1129 double *matrix_values = NULL;
1132 if(!
luminance || !hole || !dome_lum || !embedded || !ratio0 || !ratio1 || !ratio2 || !cg_field || !hole_mask)
1138 const int all_clip_mode = 1;
1147 if(cl_err != CL_SUCCESS)
goto out;
1153 if(cl_err != CL_SUCCESS)
goto out;
1155 size_t n_hole_fine = 0;
1156 for(
size_t i = 0;
i < region_pixels;
i++)
1157 if(hole_mask[
i]) n_hole_fine++;
1158 if(n_hole_fine == 0)
1160 cl_err = CL_SUCCESS;
1168 if(cl_err != CL_SUCCESS)
goto out;
1169 cl_err = _biharmonic_dome_cl(devid, gd_void, dome_lum, hole, region_w, region_h, downsample, pipe);
1170 if(cl_err != CL_SUCCESS)
goto out;
1179 if(cl_err != CL_SUCCESS)
goto out;
1184 const int local_size = 64, n_groups = 256;
1185 const int n_pixels = (int)region_pixels;
1191 if(!partial_sums || !lum_min_dev2 || !zero_dev || !bright_dev || !rehue_dev)
1200 const float zero = 0.f;
1203 size_t one[3] = { 1, 1, 1 };
1205 if(cl_err != CL_SUCCESS)
goto out;
1208 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
1209 size_t local[3] = { local_size, 1, 1 };
1219 if(cl_err != CL_SUCCESS)
goto out;
1221 float partial_host[8 * 256];
1224 if(cl_err != CL_SUCCESS)
goto out;
1225 double accum[4] = { 0.0, 0.0, 0.0, 0.0 };
1226 for(
int group = 0; group < n_groups; group++)
1227 for(
int k = 0;
k < 4;
k++) accum[
k] += (
double)partial_host[group * 4 +
k];
1229 for(
int c = 0;
c < 3;
c++) chroma_mean[c] = (
float)(accum[
c] / accum[3]);
1237 if(accum[3] > 0.0 && floor_gate > 1e-6f)
1249 if(cl_err != CL_SUCCESS)
goto out;
1251 const int fin_stride = 2, fin_mode = 1;
1252 const float fin_scale = 0.35f;
1259 size_t fin_size[3] = { 1, 1, 1 };
1261 if(cl_err != CL_SUCCESS)
goto out;
1276 if(cl_err != CL_SUCCESS)
goto out;
1279 const int fin_stride = 2, fin_mode = 1;
1280 const float fin_scale = 0.35f;
1281 size_t one[3] = { 1, 1, 1 };
1289 if(cl_err != CL_SUCCESS)
goto out;
1301 if(cl_err != CL_SUCCESS)
goto out;
1308 if(cl_err != CL_SUCCESS)
goto out;
1317 if(cl_err != CL_SUCCESS)
goto out;
1326 if(cl_err != CL_SUCCESS)
goto out;
1340 if(cl_err != CL_SUCCESS)
goto out;
1352 = !
_sp_pde_assemble(hole_mask, NULL, (react > 0.f) ? react : 0.f, 1, 1.f, region_w, region_h,
1353 &matrix_col_ptr, &matrix_row_index, &matrix_values, &perm_grid, &n_unknowns, pipe);
1358 perm_grid_dev =
factor ?
_sp_cl_upload(devid, perm_grid,
sizeof(
int) * n_unknowns) : NULL;
1362 else if(!perm_grid_dev || !rhs_dev)
1368 const int max_iter = CLAMP(2 * extent, 200, 2000);
1371 for(
int c = 0;
c < 3;
c++)
1388 if(cl_err != CL_SUCCESS)
goto out;
1394 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1404 if(cl_err != CL_SUCCESS)
goto out;
1420 int finite = (solution_check != NULL);
1426 for(
int check_index = 0; finite && check_index < n_unknowns; check_index++)
1427 if(!isfinite(solution_check[check_index])) finite = 0;
1440 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1446 if(cl_err != CL_SUCCESS)
goto out;
1453 cl_err = _region_pde_cg_cl(devid, gd_void, cg_field, hole, region_w, region_h, (react > 0.f) ? react : 0.f,
1454 (react > 0.f) ? chroma_mean[
c] : 0.f, max_iter);
1455 if(cl_err != CL_SUCCESS)
goto out;
1462 if(cl_err != CL_SUCCESS)
goto out;
1470 if(!mask_img || !mask_blur)
1482 if(cl_err != CL_SUCCESS)
goto out;
1484 cl_err = _region_blur1_cl(devid, mask_img, mask_blur, region_w, region_h,
1485 fmaxf(4.f, CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f));
1486 if(cl_err != CL_SUCCESS)
goto out;
1534cl_int _chromaticity_gradient_stage_cl(
const int devid,
void *gd_void, cl_mem estimate, cl_mem valid,
1535 cl_mem clip0, cl_mem clip_depth,
const int region_w,
const int region_h,
1536 const float reg_radius,
const float floor_gate,
1540 const size_t region_pixels = (size_t)region_w * region_h;
1543 const float epsilon = 1e-6f;
1563 cl_mem partial_sums = NULL, gate_vote_dev = NULL;
1565 if(!guard_src || !guard_blur || !gate_src || !gate_msk || !gate_wgt || !gate_nrm || !hole || !authored
1566 || !field || !shares || !hole_host)
1570 float lum_anchor_min = 0.f;
1572 const int local_size = 64, n_groups = 256;
1573 const int n_pixels = (int)region_pixels;
1575 if(!partial_sums)
goto out;
1577 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
1578 size_t local[3] = { local_size, 1, 1 };
1585 if(cl_err != CL_SUCCESS)
goto out;
1586 float partial_host[2 * 256];
1588 sizeof(
float) * 2 * n_groups, CL_TRUE);
1589 if(cl_err != CL_SUCCESS)
goto out;
1590 double lum_accum = 0.0, count = 0.0;
1591 for(
int group = 0; group < n_groups; group++)
1593 lum_accum += (
double)partial_host[group * 2 + 0];
1594 count += (
double)partial_host[group * 2 + 1];
1598 cl_err = CL_SUCCESS;
1601 lum_anchor_min = 0.35f * (float)(lum_accum / count);
1612 if(cl_err != CL_SUCCESS)
goto out;
1613 cl_err = _region_blur1_cl(devid, guard_src, guard_blur, region_w, region_h, 4.f);
1614 if(cl_err != CL_SUCCESS)
goto out;
1628 if(cl_err != CL_SUCCESS)
goto out;
1631 if(cl_err != CL_SUCCESS)
goto out;
1633 for(
size_t i = 0;
i < region_pixels;
i++) n_hole += (hole_host[
i] != 0);
1634 const size_t n_anchor = region_pixels - n_hole;
1635 if(n_anchor < 64 || n_anchor < region_pixels / 256)
1637 cl_err = CL_SUCCESS;
1643 for(
int c = 0;
c < 3;
c++)
1654 if(cl_err != CL_SUCCESS)
goto out;
1656 cl_err = _biharmonic_dome_cl(devid, gd_void, field, hole, region_w, region_h, downsample, pipe);
1657 if(cl_err != CL_SUCCESS)
goto out;
1666 if(cl_err != CL_SUCCESS)
goto out;
1673 const float gate_tau = 0.10f;
1685 if(cl_err != CL_SUCCESS)
goto out;
1686 const float gate_sigma = CLAMP(reg_radius / 4.f, 8.f, 96.f);
1687 cl_err = _region_blur1_cl(devid, gate_src, gate_wgt, region_w, region_h, gate_sigma);
1688 if(cl_err != CL_SUCCESS)
goto out;
1689 cl_err = _region_blur1_cl(devid, gate_msk, gate_nrm, region_w, region_h, gate_sigma);
1690 if(cl_err != CL_SUCCESS)
goto out;
1697 const int vote_local = 64, vote_groups = 256;
1700 if(!vote_partial || !gate_vote_dev)
1713 size_t vs[3] = { (size_t)vote_groups * vote_local, 1, 1 };
1714 size_t vl[3] = { vote_local, 1, 1 };
1716 if(cl_err == CL_SUCCESS)
1719 const int stride = 2, mode = 1;
1720 const float scale = 1.f;
1727 size_t one[3] = { 1, 1, 1 };
1731 if(cl_err != CL_SUCCESS)
goto out;
1756 if(floor_gate > 1e-6f)
1760 for(
int c = 0;
c < 3;
c++)
1777 if(cl_err != CL_SUCCESS)
goto out;
1782 if(cl_err != CL_SUCCESS)
goto out;
1783 size_t n_authored_c = 0;
1784 for(
size_t i = 0;
i < region_pixels;
i++) n_authored_c += (hole_host[
i] != 0);
1785 if(n_authored_c == 0)
continue;
1791 if(cl_err != CL_SUCCESS)
goto out;
1792 size_t n_hole_c = 0;
1793 for(
size_t i = 0;
i < region_pixels;
i++) n_hole_c += (hole_host[
i] != 0);
1795 cl_err = _biharmonic_dome_cl(devid, gd_void, field, hole, region_w, region_h, downsample_c, pipe);
1796 if(cl_err != CL_SUCCESS)
goto out;
1807 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
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)
__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
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
#define __OMP_PARALLEL_FOR__(...)
__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)
#define dt_pixelpipe_cache_alloc_align(size, pipe)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
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)
static float _hl_ring_flat_mean_vote(const float *const restrict estimate, const float *const restrict valid, const dt_aligned_pixel_t cmean, const size_t region_pixels)
#define DT_HL_DOME_NMAX_SPARSE
static float _hl_floor_worth(const float chroma_gain)
#define DT_HL_A3_COLLAR_PX
const _hl_region_t * region
const dt_dev_pixelpipe_t * pipe
int kernel_hl_ring_vote_finalize
int kernel_hl_cgrad_write1c
int kernel_hl_vote_reduce
int kernel_hl_pde_scatter
int kernel_hl_cgrad_plateau
int kernel_hl_cmean_finalize
int kernel_hl_cgrad_store
int kernel_hl_ratio_plane
int kernel_hl_ratio_cmean_blend
int kernel_hl_cmean_reduce
int kernel_hl_reduce_finalize
int kernel_hl_cgrad_guard
int kernel_hl_mask_to_img1
int kernel_hl_cgrad_reproject
int kernel_hl_clip0_rehue
int kernel_hl_cgrad_share
int kernel_hl_cgrad_anchor
int kernel_hl_cgrad_hole1c
#define __DT_CLONE_TARGETS__
typedef double((*spd)(unsigned long int wavelength, double TempK))