289 const uint8_t *const restrict hole, const
int region_w, const
int region_h,
290 const
int base_ds, const
float *const restrict steer,
294 const int downsample = CLAMP(base_ds, 1, 8);
295 const int base_w = (region_w + downsample - 1) / downsample;
296 const int base_h = (region_h + downsample - 1) / downsample;
297 const size_t cell_count = (size_t)base_w * base_h;
300 uint8_t *
const restrict base_anchor
303 float *
const restrict level_buffers
305 uint8_t *
const restrict level_anchor
311 const int steered = (steer && aniso_aux) ? 1 : 0;
313 if(!base_vals || !base_anchor || !level_buffers || !level_anchor || (steer && !aniso_aux))
316 for(
int plane = 0; plane < n_planes; plane++)
318 float *
const restrict plane_vals = vals[plane];
319 double anchor_sum = 0.0;
320 size_t anchor_count = 0;
321 for(
size_t i = 0;
i < (size_t)region_w * region_h;
i++)
324 anchor_sum += plane_vals[
i];
328 const float anchor_mean = anchor_count ? (float)(anchor_sum / (
double)anchor_count) : 0.f;
330 for(
size_t i = 0;
i < (size_t)region_w * region_h;
i++)
331 if(hole[
i]) plane_vals[
i] = anchor_mean;
343 float *
const restrict base_steer = steered ? aniso_aux + 5 * cell_count : NULL;
347 for(
int base_y = 0; base_y < base_h; base_y++)
348 for(
int base_x = 0; base_x < base_w; base_x++)
352 for(
int y = base_y * downsample; y <
MIN((base_y + 1) * downsample, region_h); y++)
353 for(
int x = base_x * downsample;
x <
MIN((base_x + 1) * downsample, region_w);
x++)
355 accum += steer[(size_t)y * region_w +
x];
358 base_steer[(size_t)base_y * base_w + base_x] = (
float)(accum / n_total);
364 for(
int base_y = 0; base_y < base_h; base_y++)
365 for(
int base_x = 0; base_x < base_w; base_x++)
371 for(
int y = base_y * downsample; y <
MIN((base_y + 1) * downsample, region_h); y++)
372 for(
int x = base_x * downsample;
x <
MIN((base_x + 1) * downsample, region_w);
x++)
374 const size_t i = (size_t)y * region_w +
x;
379 for(
int plane = 0; plane < n_planes; plane++) accum[plane] += vals[plane][
i];
384 const size_t cell_index = (size_t)base_y * base_w + base_x;
385 for(
int plane = 0; plane < n_planes; plane++)
386 base_vals[plane * cell_count + cell_index] = n_anchor ? (
float)(accum[plane] / n_anchor) : 0.f;
387 base_anchor[cell_index] = (2 * n_anchor > n_total);
399 while((
MAX(base_w, base_h) >> n_levels) > 8 && n_levels < 12) n_levels++;
401 float *
const restrict field = level_buffers + 0 * cell_count;
402 float *
const restrict tmp = level_buffers + (size_t)n_planes * cell_count;
403 float *
const restrict level_vals
404 = level_buffers + 2 * (size_t)n_planes * cell_count;
406 int prev_level_w = 0;
407 int prev_level_h = 0;
409 for(
int level = n_levels - 1; level >= 0; level--)
411 const int step = 1 << level;
412 const int level_w = (base_w + step - 1) / step;
413 const int level_h = (base_h + step - 1) / step;
417 for(
int level_y = 0; level_y < level_h; level_y++)
418 for(
int level_x = 0; level_x < level_w; level_x++)
424 for(
int y = level_y * step; y <
MIN((level_y + 1) * step, base_h); y++)
425 for(
int x = level_x * step;
x <
MIN((level_x + 1) * step, base_w);
x++)
427 const size_t i = (size_t)y * base_w +
x;
432 for(
int plane = 0; plane < n_planes; plane++) accum[plane] += base_vals[plane * cell_count +
i];
437 const size_t cell_index = (size_t)level_y * level_w + level_x;
438 for(
int plane = 0; plane < n_planes; plane++)
439 level_vals[plane * cell_count + cell_index] = n_anchor ? (
float)(accum[plane] / n_anchor) : 0.f;
440 level_anchor[cell_index] = (2 * n_anchor > n_total);
444 float *
const restrict level_steer = steered ? aniso_aux + 0 * cell_count : NULL;
445 float *
const restrict tensor_xx = steered ? aniso_aux + 1 * cell_count : NULL;
446 float *
const restrict tensor_xy = steered ? aniso_aux + 2 * cell_count : NULL;
447 float *
const restrict tensor_yy = steered ? aniso_aux + 3 * cell_count : NULL;
452 for(
int level_y = 0; level_y < level_h; level_y++)
453 for(
int level_x = 0; level_x < level_w; level_x++)
455 double steer_sum = 0.0;
457 for(
int y = level_y * step; y <
MIN((level_y + 1) * step, base_h); y++)
458 for(
int x = level_x * step;
x <
MIN((level_x + 1) * step, base_w);
x++)
460 steer_sum += base_steer[(size_t)y * base_w +
x];
463 level_steer[(size_t)level_y * level_w + level_x] = (
float)(steer_sum / n_total);
467 _cf_adaptive_tensor(level_steer, tensor_xx, tensor_xy, tensor_yy, aniso_aux + 4 * cell_count,
468 aniso_aux + 6 * cell_count, level_w, level_h,
DT_HL_CF_K);
474 float *
const restrict edge_weights = aniso_aux + 7 * cell_count;
475 float *
const restrict edge_weight_sum = aniso_aux + 15 * cell_count;
477 for(
int level_y = 0; level_y < level_h; level_y++)
478 for(
int level_x = 0; level_x < level_w; level_x++)
480 static const int neighbour_dy[8] = { 0, 0, -1, 1, -1, 1, 1, -1 };
481 static const int neighbour_dx[8] = { -1, 1, 0, 0, -1, 1, -1, 1 };
482 const size_t i = (size_t)level_y * level_w + level_x;
483 float weight_sum = 0.f;
484 for(
int k = 0;
k < 8;
k++)
486 const int neighbour_y = CLAMP(level_y + neighbour_dy[
k], 0, level_h - 1);
487 const int neighbour_x = CLAMP(level_x + neighbour_dx[
k], 0, level_w - 1);
488 const size_t cell_index = (size_t)neighbour_y * level_w + neighbour_x;
491 =
_aniso_edge_w(tensor_xx, tensor_xy, tensor_yy,
i, cell_index, neighbour_dx[
k], neighbour_dy[
k]);
495 edge_weight_sum[
i] = weight_sum;
499 if(level == n_levels - 1)
504 size_t anchor_count = 0;
505 for(
size_t i = 0;
i < (size_t)level_w * level_h;
i++)
508 for(
int plane = 0; plane < n_planes; plane++) anchor_sum[plane] += level_vals[plane * cell_count +
i];
513 for(
int plane = 0; plane < n_planes; plane++)
514 anchor_mean[plane] = anchor_count ? (
float)(anchor_sum[plane] / (
double)anchor_count) : 0.f;
516 for(
size_t i = 0;
i < (size_t)level_w * level_h;
i++)
517 for(
int plane = 0; plane < n_planes; plane++)
518 tmp[plane * cell_count +
i] = level_anchor[
i] ? level_vals[plane * cell_count +
i] : anchor_mean[plane];
524 for(
int level_y = 0; level_y < level_h; level_y++)
525 for(
int level_x = 0; level_x < level_w; level_x++)
527 const size_t i = (size_t)level_y * level_w + level_x;
531 for(
int plane = 0; plane < n_planes; plane++)
532 tmp[plane * cell_count +
i] = level_vals[plane * cell_count +
i];
536 const float grid_x = ((float)level_x + 0.5f) * 0.5f - 0.5f;
537 const float grid_y = ((float)level_y + 0.5f) * 0.5f - 0.5f;
538 const int x_lo = CLAMP((
int)floorf(grid_x), 0, prev_level_w - 1);
539 const int y_lo = CLAMP((
int)floorf(grid_y), 0, prev_level_h - 1);
540 const int x_hi =
MIN(x_lo + 1, prev_level_w - 1);
541 const int y_hi =
MIN(y_lo + 1, prev_level_h - 1);
542 const float frac_x = CLAMP(grid_x - x_lo, 0.f, 1.f);
543 const float frac_y = CLAMP(grid_y - y_lo, 0.f, 1.f);
544 for(
int plane = 0; plane < n_planes; plane++)
546 const float *
const plane_field = field + plane * cell_count;
547 const float interp_top = plane_field[(size_t)y_lo * prev_level_w + x_lo] * (1.f - frac_x)
548 + plane_field[(size_t)y_lo * prev_level_w + x_hi] * frac_x;
549 const float interp_bottom = plane_field[(size_t)y_hi * prev_level_w + x_lo] * (1.f - frac_x)
550 + plane_field[(size_t)y_hi * prev_level_w + x_hi] * frac_x;
551 tmp[plane * cell_count +
i] = interp_top * (1.f - frac_y) + interp_bottom * frac_y;
556 for(
int plane = 0; plane < n_planes; plane++)
557 memcpy(field + plane * cell_count, tmp + plane * cell_count, (
size_t)level_w * level_h *
sizeof(float));
562 const float *
const restrict edge_weights = steered ? aniso_aux + 7 * cell_count : NULL;
563 const float *
const restrict edge_weight_sum = steered ? aniso_aux + 15 * cell_count : NULL;
567 _cf_fill_relax_1(field, tmp, level_anchor, edge_weights, edge_weight_sum, level_w, level_h, cell_count,
571 _cf_fill_relax_2(field, tmp, level_anchor, edge_weights, edge_weight_sum, level_w, level_h, cell_count,
575 _cf_fill_relax_3(field, tmp, level_anchor, edge_weights, edge_weight_sum, level_w, level_h, cell_count,
579 _cf_fill_relax_4(field, tmp, level_anchor, edge_weights, edge_weight_sum, level_w, level_h, cell_count,
585 prev_level_w = level_w;
586 prev_level_h = level_h;
592 for(
int y = 0; y < region_h; y++)
593 for(
int x = 0;
x < region_w;
x++)
595 const size_t i = (size_t)y * region_w +
x;
597 if(!hole[
i])
continue;
599 const float grid_x = ((float)
x + 0.5f) / downsample - 0.5f;
600 const float grid_y = ((float)y + 0.5f) / downsample - 0.5f;
601 const int x_lo = CLAMP((
int)floorf(grid_x), 0, base_w - 1);
602 const int y_lo = CLAMP((
int)floorf(grid_y), 0, base_h - 1);
603 const int x_hi =
MIN(x_lo + 1, base_w - 1);
604 const int y_hi =
MIN(y_lo + 1, base_h - 1);
605 const float frac_x = CLAMP(grid_x - x_lo, 0.f, 1.f);
606 const float frac_y = CLAMP(grid_y - y_lo, 0.f, 1.f);
607 for(
int plane = 0; plane < n_planes; plane++)
609 const float *
const plane_field = field + plane * cell_count;
610 const float interp_top = plane_field[(size_t)y_lo * base_w + x_lo] * (1.f - frac_x)
611 + plane_field[(size_t)y_lo * base_w + x_hi] * frac_x;
612 const float interp_bottom = plane_field[(size_t)y_hi * base_w + x_lo] * (1.f - frac_x)
613 + plane_field[(size_t)y_hi * base_w + x_hi] * frac_x;
614 vals[plane][
i] = interp_top * (1.f - frac_y) + interp_bottom * frac_y;
641 float *
const restrict estimate = ctx->
estimate;
642 float *
const restrict prev_scale = ctx->
prev_scale;
643 float *
const restrict valid = ctx->
valid;
644 float *
const restrict blur_in = ctx->
blur_in;
645 float *
const restrict plane1 = ctx->
plane1;
646 float *
const restrict plane2 = ctx->
plane2;
647 float *
const restrict plane3 = ctx->
plane3;
649 float *
const restrict guide_score = ctx->
guide_score;
650 float *
const restrict clip_depth = ctx->
clip_depth;
651 float *
const restrict clip0 = ctx->
clip0;
652 uint8_t *
const restrict hole = ctx->
hole;
654 float *
const restrict fill_planes = ctx->
fill_planes;
655 float *
const restrict dome_lum = ctx->
dome_lum;
656 float *
const restrict lum_accum = ctx->
lum_accum;
658 float *
const restrict flat_target = ctx->
flat_target;
661 = CLAMP(region->
radius / 6.f, 8.f, 64.f);
663 const float cf_fmin = 0.05f;
667 for(
size_t i = 0;
i < region_pixels;
i++)
668 lum_accum[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
672 HL_PFOR(reduction(+ : laccum, lcnt))
673 for(
size_t i = 0;
i < region_pixels;
i++)
674 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f)
676 laccum += lum_accum[
i];
680 const float cf_lref = lcnt ? (float)(laccum / (
double)lcnt) : 0.f;
690 for(
size_t i = 0;
i < region_pixels;
i++)
694 for(
int c = 0; c < 3; c++)
695 if(valid[
i * 4 + c] >= 0.5f)
697 accum += estimate[
i * 4 + c];
700 steer[
i] = n_valid ? accum / n_valid : lum_accum[
i] / 3.f;
710 double maccum[3] = { 0.0, 0.0, 0.0 };
711 size_t mcnt[3] = { 0, 0, 0 };
712 HL_PFOR(reduction(+ : maccum[:3], mcnt[:3]))
713 for(
size_t i = 0;
i < region_pixels;
i++)
714 for(
int c = 0; c < 3; c++)
715 if(valid[
i * 4 + c] >= 0.5f)
717 maccum[c] += estimate[
i * 4 + c];
720 const float channel_means[3]
721 = { mcnt[0] ? (float)(maccum[0] / mcnt[0]) : 0.f, mcnt[1] ? (float)(maccum[1] / mcnt[1]) : 0.f,
722 mcnt[2] ? (float)(maccum[2] / mcnt[2]) : 0.f };
729 const float cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
732 uint8_t *
const restrict hole2
739 for(
size_t i = 0;
i < region_pixels;
i++)
740 for(
int c = 0; c < 4; c++) guide_score[
i * 4 + c] = 0.f;
750 for(
size_t i = 0;
i < region_pixels;
i++)
752 const float lum_weight = (cf_binv > 0.f) ? sqf(fminf(lum_accum[
i] * cf_binv, 1.f)) : 1.f;
754 = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f) ? lum_weight : 0.f;
756 blur_in[
i * 4 + 1] =
weight * (estimate[
i * 4 + 0] - channel_means[0]);
757 blur_in[
i * 4 + 2] =
weight * (estimate[
i * 4 + 1] - channel_means[1]);
758 blur_in[
i * 4 + 3] =
weight * (estimate[
i * 4 + 2] - channel_means[2]);
761 _region_blur(blur_in, prev_scale, region_w, region_h, cf_sigma);
764 for(
size_t i = 0;
i < region_pixels;
i++)
766 const float lum_weight = (cf_binv > 0.f) ? sqf(fminf(lum_accum[
i] * cf_binv, 1.f)) : 1.f;
768 = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f) ? lum_weight : 0.f;
771 = estimate[
i * 4 + 0] - channel_means[0];
772 const float val_g = estimate[
i * 4 + 1] - channel_means[1];
773 const float val_b = estimate[
i * 4 + 2] - channel_means[2];
774 blur_in[
i * 4 + 0] =
weight * val_r * val_r;
775 blur_in[
i * 4 + 1] =
weight * val_g * val_g;
776 blur_in[
i * 4 + 2] =
weight * val_b * val_b;
777 blur_in[
i * 4 + 3] =
weight * val_r * val_g;
780 _region_blur(blur_in, plane1, region_w, region_h, cf_sigma);
783 for(
size_t i = 0;
i < region_pixels;
i++)
785 const float lum_weight = (cf_binv > 0.f) ? sqf(fminf(lum_accum[
i] * cf_binv, 1.f)) : 1.f;
787 = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f) ? lum_weight : 0.f;
789 blur_in[
i * 4 + 0] =
weight * (estimate[
i * 4 + 0] - channel_means[0])
790 * (estimate[
i * 4 + 2] - channel_means[2]);
791 blur_in[
i * 4 + 1] =
weight * (estimate[
i * 4 + 1] - channel_means[1])
792 * (estimate[
i * 4 + 2] - channel_means[2]);
793 blur_in[
i * 4 + 2] = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f)
796 blur_in[
i * 4 + 3] = 0.f;
799 _region_blur(blur_in, plane3, region_w, region_h, cf_sigma);
805#define CF_M2(nb_index, coef_a, coef_b) \
806 (((coef_a) == (coef_b)) ? plane1[(nb_index) * 4 + (coef_a)] \
807 : ((2 + (coef_a) + (coef_b)) < 4 ? plane1[(nb_index) * 4 + 2 + (coef_a) + (coef_b)] \
808 : plane3[(nb_index) * 4 + (coef_a) + (coef_b) - 2]))
815 size_t nclip_c[3] = { 0, 0, 0 };
816 for(
size_t i = 0;
i < region_pixels;
i++)
817 for(
int c = 0; c < 3; c++)
818 if(valid[
i * 4 + c] < 0.5f) nclip_c[c]++;
822 = (nclip_c[0] >= nclip_c[1] && nclip_c[0] >= nclip_c[2]) ? 0 : ((nclip_c[1] >= nclip_c[2]) ? 1 : 2);
823 int deep_stashed = 0;
826 for(
int c = 0; c < 3; c++)
829 const int guide1 = (c == 0) ? 1 : 0;
830 const int guide2 = (c == 2) ? 1 : 2;
833 HL_PFOR(reduction(+ : ntarget))
834 for(
size_t i = 0;
i < region_pixels;
i++)
835 if(valid[
i * 4 + c] < 0.5f && (valid[
i * 4 + guide1] >= 0.5f || valid[
i * 4 + guide2] >= 0.5f)) ntarget++;
837 if(ntarget == 0)
continue;
849 for(
size_t i = 0;
i < region_pixels;
i++)
851 const float norm = fmaxf(prev_scale[
i * 4 + 0], 1e-9f);
852 const float inv_det = 1.f / norm;
853 const float mean1 = prev_scale[
i * 4 + 1 + guide1] * inv_det;
854 const float mean2 = prev_scale[
i * 4 + 1 + guide2] * inv_det;
855 const float mean_target = prev_scale[
i * 4 + 1 + c] * inv_det;
857 = fmaxf(
CF_M2(
i, guide1, guide1) * inv_det - mean1 * mean1, 0.f);
858 const float var22 = fmaxf(
CF_M2(
i, guide2, guide2) * inv_det - mean2 * mean2, 0.f);
859 const float var12 =
CF_M2(
i, guide1, guide2) * inv_det - mean1 * mean2;
860 const float cov_tg1 =
CF_M2(
i, c, guide1) * inv_det - mean_target * mean1;
861 const float cov_tg2 =
CF_M2(
i, c, guide2) * inv_det - mean_target * mean2;
863 const float var_target
864 = fmaxf(
CF_M2(
i, c, c) * inv_det - mean_target * mean_target, 0.f);
867 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
868 const float determinant
869 = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
871 = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
873 = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
874 const float r_sq = CLAMP((slope_a * cov_tg1 + slope_b * cov_tg2) / (var_target + 1e-12f), 0.f,
877 valid_variance[
i * 4 + 0] = slope_a;
878 valid_variance[
i * 4 + 1] = slope_b;
880 valid_variance[
i * 4 + 2] = (mean_target + channel_means[c]) - slope_a * (mean1 + channel_means[guide1])
881 - slope_b * (mean2 + channel_means[guide2]);
882 valid_variance[
i * 4 + 3] = r_sq;
890 const int mass_ok = (plane3[
i * 4 + 2] > cf_fmin && prev_scale[
i * 4 + 0] > 0.25f * plane3[
i * 4 + 2]);
894 hole[
i] = !(mass_ok && valid[
i * 4 + c] >= 0.5f && r_sq > 0.25f && fabsf(slope_a) < 64.f
895 && fabsf(slope_b) < 64.f);
897 hole2[
i] = !(mass_ok && valid[
i * 4 + c] >= 0.5f);
906 for(
size_t i = 0;
i < region_pixels;
i++)
908 fill_planes[
i] = valid_variance[
i * 4 + 0];
909 fill_planes[region_pixels +
i] = valid_variance[
i * 4 + 1];
910 fill_planes[2 * region_pixels +
i] = valid_variance[
i * 4 + 2];
911 solver_field[
i] = valid_variance[
i * 4 + 3];
915 float *planes[3] = { fill_planes, fill_planes + region_pixels, fill_planes + 2 * region_pixels };
916 _cf_harmonic_fill_n((
float *
const restrict *)planes, 3, hole, region_w, region_h, (
int)(cf_sigma / 4.f),
920 _cf_harmonic_fill(solver_field, hole2 ? hole2 : hole, region_w, region_h, (int)(cf_sigma / 4.f), steer, pipe);
923 for(
size_t i = 0;
i < region_pixels;
i++)
925 valid_variance[
i * 4 + 0] = fill_planes[
i];
926 valid_variance[
i * 4 + 1] = fill_planes[region_pixels +
i];
927 valid_variance[
i * 4 + 2] = fill_planes[2 * region_pixels +
i];
928 valid_variance[
i * 4 + 3] = solver_field[
i];
940 for(
size_t i = 0;
i < region_pixels;
i++)
942 reaction_weight[
i] = valid_variance[
i * 4 + 0];
943 flat_target[
i] = valid_variance[
i * 4 + 1];
944 dome_lum[
i] = valid_variance[
i * 4 + 2];
945 guide_score[
i * 4 + 3] = valid_variance[
i * 4 + 3];
956 for(
size_t i = 0;
i < region_pixels;
i++)
957 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
960 estimate[
i * 4 + c] = valid_variance[
i * 4 + 0] * estimate[
i * 4 + guide1]
961 + valid_variance[
i * 4 + 1] * estimate[
i * 4 + guide2] + valid_variance[
i * 4 + 2];
962 guide_score[
i * 4 + c]
963 = CLAMP(valid_variance[
i * 4 + 3], 0.f, 1.f);
975 for(
size_t i = 0;
i < region_pixels;
i++)
977 const int n_valid = (valid[
i * 4 + 0] >= 0.5f) + (valid[
i * 4 + 1] >= 0.5f) + (valid[
i * 4 + 2] >= 0.5f);
978 if(n_valid == 1) n2clip++;
982 for(
int chan_a = 0; chan_a < 3; chan_a++)
983 for(
int chan_b = chan_a + 1; chan_b < 3; chan_b++)
988 for(
size_t i = 0;
i < region_pixels;
i++)
990 const float lum_weight = (cf_binv > 0.f) ? sqf(fminf(lum_accum[
i] * cf_binv, 1.f)) : 1.f;
991 const float weight = (valid[
i * 4 + chan_a] >= 0.5f && valid[
i * 4 + chan_b] >= 0.5f) ? lum_weight : 0.f;
992 const float var_a = estimate[
i * 4 + chan_a] - channel_means[chan_a];
993 const float var_b = estimate[
i * 4 + chan_b] - channel_means[chan_b];
995 blur_in[
i * 4 + 1] =
weight * var_a;
996 blur_in[
i * 4 + 2] =
weight * var_b;
997 blur_in[
i * 4 + 3] =
weight * var_a * var_a;
1000 _region_blur(blur_in, plane2, region_w, region_h, cf_sigma);
1003 for(
size_t i = 0;
i < region_pixels;
i++)
1005 const float lum_weight = (cf_binv > 0.f) ? sqf(fminf(lum_accum[
i] * cf_binv, 1.f)) : 1.f;
1006 const float weight = (valid[
i * 4 + chan_a] >= 0.5f && valid[
i * 4 + chan_b] >= 0.5f) ? lum_weight : 0.f;
1007 const float var_a = estimate[
i * 4 + chan_a] - channel_means[chan_a];
1008 const float var_b = estimate[
i * 4 + chan_b] - channel_means[chan_b];
1009 blur_in[
i * 4 + 0] =
weight * var_b * var_b;
1010 blur_in[
i * 4 + 1] =
weight * var_a * var_b;
1011 blur_in[
i * 4 + 2] = (valid[
i * 4 + chan_a] >= 0.5f && valid[
i * 4 + chan_b] >= 0.5f) ? 1.f : 0.f;
1012 blur_in[
i * 4 + 3] = 0.f;
1015 _region_blur(blur_in, plane3, region_w, region_h, cf_sigma);
1018 for(
int orient = 0; orient < 2; orient++)
1020 const int target_chan = orient ? chan_b : chan_a;
1021 const int guide_chan = orient ? chan_a : chan_b;
1022 const int other_chan = 3 - chan_a - chan_b;
1025 HL_PFOR(reduction(+ : ntarget))
1026 for(
size_t i = 0;
i < region_pixels;
i++)
1027 if(valid[
i * 4 + target_chan] < 0.5f && valid[
i * 4 + guide_chan] >= 0.5f
1028 && valid[
i * 4 + other_chan] < 0.5f)
1031 if(ntarget == 0)
continue;
1034 for(
size_t i = 0;
i < region_pixels;
i++)
1036 const float norm = fmaxf(plane2[
i * 4 + 0], 1e-9f);
1037 const float inv_det = 1.f / norm;
1038 const float pair_mean_target = plane2[
i * 4 + (orient ? 2 : 1)] * inv_det;
1039 const float mean_guide = plane2[
i * 4 + (orient ? 1 : 2)] * inv_det;
1040 const float var_guide
1041 = fmaxf((orient ? plane2[
i * 4 + 3] : plane3[
i * 4 + 0]) * inv_det - mean_guide * mean_guide,
1043 const float var_t = fmaxf((orient ? plane3[
i * 4 + 0] : plane2[
i * 4 + 3]) * inv_det
1044 - pair_mean_target * pair_mean_target,
1046 const float covariance = plane3[
i * 4 + 1] * inv_det - pair_mean_target * mean_guide;
1048 = covariance / (var_guide * (1.f + 1e-3f) + 1e-12f);
1049 const float r_sq = CLAMP(covariance * covariance / (var_guide * var_t + 1e-18f), 0.f,
1052 valid_variance[
i * 4 + 0] = slope_a;
1054 valid_variance[
i * 4 + 1] = (pair_mean_target + channel_means[target_chan])
1055 - slope_a * (mean_guide + channel_means[guide_chan]);
1056 valid_variance[
i * 4 + 2] = r_sq;
1057 const int mass_ok = (plane3[
i * 4 + 2] > cf_fmin && plane2[
i * 4 + 0] > 0.25f * plane3[
i * 4 + 2]);
1058 hole[
i] = !(mass_ok && valid[
i * 4 + target_chan] >= 0.5f && r_sq > 0.25f && fabsf(slope_a) < 64.f);
1059 if(hole2) hole2[
i] = !(mass_ok && valid[
i * 4 + target_chan] >= 0.5f);
1066 for(
size_t i = 0;
i < region_pixels;
i++)
1068 fill_planes[
i] = valid_variance[
i * 4 + 0];
1069 fill_planes[region_pixels +
i] = valid_variance[
i * 4 + 1];
1070 solver_field[
i] = valid_variance[
i * 4 + 2];
1073 float *planes[2] = { fill_planes, fill_planes + region_pixels };
1075 (
int)(cf_sigma / 4.f), steer, pipe);
1076 _cf_harmonic_fill(solver_field, hole2 ? hole2 : hole, region_w, region_h, (int)(cf_sigma / 4.f), steer,
1080 for(
size_t i = 0;
i < region_pixels;
i++)
1082 valid_variance[
i * 4 + 0] = fill_planes[
i];
1083 valid_variance[
i * 4 + 1] = fill_planes[region_pixels +
i];
1084 valid_variance[
i * 4 + 2] = solver_field[
i];
1102 for(
size_t i = 0;
i < region_pixels;
i++)
1103 if(valid[
i * 4 + target_chan] < 0.5f && valid[
i * 4 + guide_chan] >= 0.5f
1104 && valid[
i * 4 + other_chan] < 0.5f)
1107 estimate[
i * 4 + target_chan]
1108 = valid_variance[
i * 4 + 0] * estimate[
i * 4 + guide_chan] + valid_variance[
i * 4 + 1];
1109 guide_score[
i * 4 + target_chan] = CLAMP(valid_variance[
i * 4 + 2], 0.f, 1.f);
1127 const int guide1 = (cdeep == 0) ? 1 : 0;
1128 const int guide2 = (cdeep == 2) ? 1 : 2;
1131 for(
size_t i = 0;
i < region_pixels;
i++)
1134 = (valid[
i * 4 + cdeep] < 0.5f && (valid[
i * 4 + guide1] < 0.5f || valid[
i * 4 + guide2] < 0.5f)) ? 1.f
1136 blur_in[
i * 4 + 1] = blur_in[
i * 4 + 2] = blur_in[
i * 4 + 3] = 0.f;
1143 for(
size_t i = 0;
i < region_pixels;
i++)
1145 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
1146 if(valid[
i * 4 + cdeep] < 0.5f && anyvalid)
1150 const float joint = reaction_weight[
i] * estimate[
i * 4 + guide1]
1151 + flat_target[
i] * estimate[
i * 4 + guide2] + dome_lum[
i];
1153 const int has_pair = (valid[
i * 4 + guide1] < 0.5f || valid[
i * 4 + guide2] < 0.5f);
1154 const float pair_conf = CLAMP(plane2[
i * 4 + 0], 0.f, 1.f);
1155 const float smooth_t = CLAMP((pair_conf - 0.7f) / 0.25f, 0.f, 1.f);
1156 const float floor_width = has_pair ? smooth_t * smooth_t * (3.f - 2.f * smooth_t) : 0.f;
1157 estimate[
i * 4 + cdeep] = floor_width * estimate[
i * 4 + cdeep] + (1.f - floor_width) * joint;
1158 guide_score[
i * 4 + cdeep] = floor_width * guide_score[
i * 4 + cdeep]
1159 + (1.f - floor_width) * CLAMP(guide_score[
i * 4 + 3], 0.f, 1.f);
1178 memcpy(blur_in, estimate, region_pixels * 4 *
sizeof(
float));
1180 fmaxf(cf_sigma / 4.f, 2.f));
1186 for(
size_t i = 0;
i < region_pixels;
i++)
1188 const float lum_weight = (cf_binv > 0.f) ? sqf(fminf(lum_accum[
i] * cf_binv, 1.f)) : 1.f;
1190 = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f) ? lum_weight : 0.f;
1193 blur_in[
i * 4 + 1] =
weight * (estimate[
i * 4 + 0] - plane2[
i * 4 + 0]);
1194 blur_in[
i * 4 + 2] =
weight * (estimate[
i * 4 + 1] - plane2[
i * 4 + 1]);
1195 blur_in[
i * 4 + 3] =
weight * (estimate[
i * 4 + 2] - plane2[
i * 4 + 2]);
1202 for(
size_t i = 0;
i < region_pixels;
i++)
1204 const float weight = blur_in[
i * 4 + 0];
1205 const float hf_r = estimate[
i * 4 + 0] - plane2[
i * 4 + 0];
1206 const float hf_g = estimate[
i * 4 + 1] - plane2[
i * 4 + 1];
1207 const float hf_b = estimate[
i * 4 + 2] - plane2[
i * 4 + 2];
1208 blur_in[
i * 4 + 0] =
weight * hf_r * hf_r;
1209 blur_in[
i * 4 + 1] =
weight * hf_g * hf_g;
1210 blur_in[
i * 4 + 2] =
weight * hf_b * hf_b;
1211 blur_in[
i * 4 + 3] =
weight * hf_r * hf_g;
1214 _region_blur(blur_in, plane1, region_w, region_h, cf_sigma);
1217 for(
size_t i = 0;
i < region_pixels;
i++)
1219 const float lum_weight = (cf_binv > 0.f) ? sqf(fminf(lum_accum[
i] * cf_binv, 1.f)) : 1.f;
1221 = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f) ? lum_weight : 0.f;
1223 =
weight * (estimate[
i * 4 + 0] - plane2[
i * 4 + 0]) * (estimate[
i * 4 + 2] - plane2[
i * 4 + 2]);
1225 =
weight * (estimate[
i * 4 + 1] - plane2[
i * 4 + 1]) * (estimate[
i * 4 + 2] - plane2[
i * 4 + 2]);
1226 blur_in[
i * 4 + 2] = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f)
1229 blur_in[
i * 4 + 3] = 0.f;
1232 _region_blur(blur_in, plane3, region_w, region_h, cf_sigma);
1237#define HF_M2(nb_index, coef_a, coef_b) \
1238 (((coef_a) == (coef_b)) ? plane1[(nb_index) * 4 + (coef_a)] \
1239 : ((2 + (coef_a) + (coef_b)) < 4 ? plane1[(nb_index) * 4 + 2 + (coef_a) + (coef_b)] \
1240 : plane3[(nb_index) * 4 + (coef_a) + (coef_b) - 2]))
1242 for(
int c = 0; c < 3; c++)
1244 const int guide1 = (c == 0) ? 1 : 0;
1245 const int guide2 = (c == 2) ? 1 : 2;
1248 HL_PFOR(reduction(+ : ntarget))
1249 for(
size_t i = 0;
i < region_pixels;
i++)
1250 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f) ntarget++;
1252 if(ntarget == 0)
continue;
1256 for(
size_t i = 0;
i < region_pixels;
i++)
1258 const float norm = fmaxf(prev_scale[
i * 4 + 0], 1e-9f);
1259 const float inv_det = 1.f / norm;
1260 const float mean1 = prev_scale[
i * 4 + 1 + guide1] * inv_det;
1261 const float mean2 = prev_scale[
i * 4 + 1 + guide2] * inv_det;
1262 const float mean_target = prev_scale[
i * 4 + 1 + c] * inv_det;
1265 const float var11 = fmaxf(
HF_M2(
i, guide1, guide1) * inv_det - mean1 * mean1, 0.f);
1266 const float var22 = fmaxf(
HF_M2(
i, guide2, guide2) * inv_det - mean2 * mean2, 0.f);
1267 const float var12 =
HF_M2(
i, guide1, guide2) * inv_det - mean1 * mean2;
1268 const float cov_tg1 =
HF_M2(
i, c, guide1) * inv_det - mean_target * mean1;
1269 const float cov_tg2 =
HF_M2(
i, c, guide2) * inv_det - mean_target * mean2;
1270 const float var_target
1271 = fmaxf(
HF_M2(
i, c, c) * inv_det - mean_target * mean_target, 0.f);
1273 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
1274 const float determinant = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
1275 const float hf_a = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
1276 const float hf_b_slope = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
1277 const float hf_r2 = CLAMP((hf_a * cov_tg1 + hf_b_slope * cov_tg2) / (var_target + 1e-12f), 0.f, 1.f);
1280 reaction_weight[
i] = hf_a * hf_r2;
1281 flat_target[
i] = hf_b_slope * hf_r2;
1282 hole[
i] = !(plane3[
i * 4 + 2] > cf_fmin && prev_scale[
i * 4 + 0] > 0.25f * plane3[
i * 4 + 2]
1283 && valid[
i * 4 + c] >= 0.5f && fabsf(reaction_weight[
i]) < 64.f && fabsf(flat_target[
i]) < 64.f);
1288 float *planes[2] = { reaction_weight, flat_target };
1289 _cf_harmonic_fill_n((
float *
const restrict *)planes, 2, hole, region_w, region_h, (
int)(cf_sigma / 4.f),
1295 for(
size_t i = 0;
i < region_pixels;
i++)
1298 const float hf_guided = reaction_weight[
i] * (estimate[
i * 4 + guide1] - plane2[
i * 4 + guide1])
1299 + flat_target[
i] * (estimate[
i * 4 + guide2] - plane2[
i * 4 + guide2]);
1301 const float hf_damped = CLAMP(guide_score[
i * 4 + c], 0.f, 1.f) * (estimate[
i * 4 + c] - plane2[
i * 4 + c]);
1302 blur_in[
i * 4 + 0] = fabsf(hf_guided);
1303 blur_in[
i * 4 + 1] = fabsf(hf_damped);
1304 blur_in[
i * 4 + 2] = 0.f;
1305 blur_in[
i * 4 + 3] = 0.f;
1308 _region_blur(blur_in, valid_variance, region_w, region_h, fmaxf(cf_sigma / 4.f, 2.f));
1312 for(
size_t i = 0;
i < region_pixels;
i++)
1313 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
1315 const float hf_guided = reaction_weight[
i] * (estimate[
i * 4 + guide1] - plane2[
i * 4 + guide1])
1316 + flat_target[
i] * (estimate[
i * 4 + guide2] - plane2[
i * 4 + guide2]);
1317 const float hf_damped
1318 = CLAMP(guide_score[
i * 4 + c], 0.f, 1.f) * (estimate[
i * 4 + c] - plane2[
i * 4 + c]);
1319 const float energy_g = valid_variance[
i * 4 + 0];
1320 const float energy_d = valid_variance[
i * 4 + 1];
1323 const float energy_weight = energy_d * energy_d / fmaxf(energy_d * energy_d + energy_g * energy_g, 1e-18f);
1325 estimate[
i * 4 + c] = plane2[
i * 4 + c] + energy_weight * hf_guided + (1.f - energy_weight) * hf_damped;
1333 for(
size_t i = 0;
i < region_pixels;
i++)
1335 const int n_valid = (valid[
i * 4 + 0] >= 0.5f) + (valid[
i * 4 + 1] >= 0.5f) + (valid[
i * 4 + 2] >= 0.5f);
1336 if(n_valid != 1)
continue;
1337 for(
int c = 0; c < 3; c++)
1338 if(valid[
i * 4 + c] < 0.5f)
1341 const float hf_weight = CLAMP(guide_score[
i * 4 + c], 0.f, 1.f);
1342 estimate[
i * 4 + c] = plane2[
i * 4 + c] + hf_weight * (estimate[
i * 4 + c] - plane2[
i * 4 + c]);
1352 for(
size_t i = 0;
i < region_pixels;
i++)
1353 for(
int c = 0; c < 3; c++)
1354 if(valid[
i * 4 + c] < 0.5f)
1356 const float clip_floor_c = clip0[
i * 4 + c];
1357 const float delta = estimate[
i * 4 + c] - clip_floor_c;
1358 const float weight = 0.02f * fmaxf(clip_floor_c, 1e-6f);
1374 for(
size_t i = 0;
i < region_pixels;
i++)
1375 for(
int c = 0; c < 3; c++)
1377 const float dome_t = CLAMP((guide_score[
i * 4 + c] - 0.4f) / 0.45f, 0.f, 1.f);
1378 const float we_r2 = dome_t * dome_t * (3.f - 2.f * dome_t);
1379 const float smooth_t = clip_depth[
i] / (1.5f * cf_sigma);
1380 const float gdep = expf(-smooth_t * smooth_t);
1381 valid_variance[
i * 4 + c] = sqrtf(CLAMP(1.f - (1.f - we_r2) * gdep, 0.f, 1.f));
1411 cl_mem hole,
const int region_w,
const int region_h,
const int base_ds,
1412 const int mask_is_hole, cl_mem steer)
1416 const int downsample = CLAMP(base_ds, 1, 8);
1417 const int base_w = (region_w + downsample - 1) / downsample;
1418 const int base_h = (region_h + downsample - 1) / downsample;
1419 const size_t cell_count = (size_t)base_w * base_h;
1421 const int steered = (steer != NULL);
1430 for(
int plane = 0; plane < n_planes; plane++)
1437 alloc_ok &= (base_vals[plane] && level_vals[plane] && level_solution[plane] && level_scratch[plane]
1438 && prev_level_solution[plane]);
1445 cl_mem base_steer = NULL;
1446 cl_mem level_steer = NULL;
1447 cl_mem steer_blur_lin = NULL;
1448 cl_mem steer_blur_quad = NULL;
1449 cl_mem steer_grad_x = NULL;
1450 cl_mem steer_grad_y = NULL;
1451 cl_mem steer_tensor_xx = NULL;
1452 cl_mem steer_tensor_xy = NULL;
1453 cl_mem steer_tensor_yy = NULL;
1454 cl_mem grad_partial_sums = NULL;
1455 cl_mem grad_mean_norm = NULL;
1456 cl_mem neighbour_weights = NULL;
1457 cl_mem neighbour_weights_sum = NULL;
1473 alloc_ok &= (base_steer && level_steer && steer_blur_lin && steer_blur_quad && steer_grad_x && steer_grad_y
1474 && steer_tensor_xx && steer_tensor_xy && steer_tensor_yy && grad_partial_sums && grad_mean_norm
1475 && neighbour_weights && neighbour_weights_sum)
1479 if(!alloc_ok || !base_anchor_mask || !level_anchor_mask)
goto out;
1485 for(
int plane = 0; plane < n_planes; plane++)
1500 if(cl_err != CL_SUCCESS)
goto out;
1516 if(cl_err != CL_SUCCESS)
goto out;
1522 while((
MAX(base_w, base_h) >> nlev) > 8 && nlev < 12) nlev++;
1526 int prev_level_w = 0;
1527 int prev_level_h = 0;
1528 for(
int level = nlev - 1; level >= 0; level--)
1530 const int step = 1 << level;
1531 const int level_w = (base_w + step - 1) / step;
1532 const int level_h = (base_h + step - 1) / step;
1536 for(
int plane = 0; plane < n_planes; plane++)
1548 const int level_anchor = 0;
1551 if(cl_err != CL_SUCCESS)
goto out;
1554 if(level == nlev - 1)
1557 for(
int plane = 0; plane < n_planes; plane++)
1560 const int n_cells = level_w * level_h;
1561 const int local_size = 256;
1562 size_t size_level[3] = { local_size, 1, 1 };
1563 size_t local[3] = { local_size, 1, 1 };
1571 if(cl_err != CL_SUCCESS)
goto out;
1577 for(
int plane = 0; plane < n_planes; plane++)
1589 if(cl_err != CL_SUCCESS)
goto out;
1601 const int n_cells = level_w * level_h;
1612 if(cl_err != CL_SUCCESS)
goto out;
1614 for(
int pass = 0; pass < 2; pass++)
1617 cl_mem blur_in_lin = pass ? steer_grad_x : level_steer;
1618 cl_mem blur_in_quad = pass ? steer_grad_y : level_steer;
1619 cl_mem outL = pass ? steer_blur_lin : steer_grad_x;
1620 cl_mem outQ = pass ? steer_blur_quad : steer_grad_y;
1621 const int square = (pass == 0);
1630 if(cl_err != CL_SUCCESS)
goto out;
1634 const int local_size = 64, n_groups = 256;
1635 size_t size_1d[3] = { (size_t)n_groups * local_size, 1, 1 };
1636 size_t local_size_1d[3] = { local_size, 1, 1 };
1645 if(cl_err != CL_SUCCESS)
goto out;
1650 const int ngroups = 256;
1651 size_t size_1d[3] = { 1, 1, 1 };
1657 if(cl_err != CL_SUCCESS)
goto out;
1661 size_t size_1d[3] = {
ROUNDUPDWD(n_cells, devid), 1, 1 };
1673 if(cl_err != CL_SUCCESS)
goto out;
1678 if(level_w * level_h <= 4096)
1689 if(cl_err != CL_SUCCESS)
goto out;
1695 if(level_w * level_h <= 4096)
1697 const int iters = 100;
1698 size_t size_box[3] = { 256, 1, 1 };
1699 size_t local_box[3] = { 256, 1, 1 };
1704 cl_mem solution1 = (n_planes > 1) ? level_solution[1] : level_solution[0];
1705 cl_mem solution2 = (n_planes > 2) ? level_solution[2] : level_solution[0];
1706 cl_mem scratch1 = (n_planes > 1) ? level_scratch[1] : level_scratch[0];
1707 cl_mem scratch2 = (n_planes > 2) ? level_scratch[2] : level_scratch[0];
1723 if(cl_err != CL_SUCCESS)
goto out;
1726 for(
int plane = 0; plane < n_planes; plane++)
1737 if(cl_err != CL_SUCCESS)
goto out;
1741 for(
int plane = 0; plane < n_planes; plane++)
1743 cl_mem swap_buf = prev_level_solution[plane];
1744 prev_level_solution[plane] = level_solution[plane];
1745 level_solution[plane] = swap_buf;
1747 prev_level_w = level_w;
1748 prev_level_h = level_h;
1753 const int n_iter = 100;
1755 for(
int plane = 0; plane < n_planes; plane++)
1757 solution_planes[plane] = level_solution[plane];
1758 scratch_planes[plane] = level_scratch[plane];
1760 for(
int iter = 0; iter < n_iter; iter++)
1768 cl_mem solution1 = (n_planes > 1) ? solution_planes[1] : solution_planes[0];
1769 cl_mem solution2 = (n_planes > 2) ? solution_planes[2] : solution_planes[0];
1770 cl_mem scratch1 = (n_planes > 1) ? scratch_planes[1] : scratch_planes[0];
1771 cl_mem scratch2 = (n_planes > 2) ? scratch_planes[2] : scratch_planes[0];
1787 if(cl_err != CL_SUCCESS)
goto out;
1790 for(
int plane = 0; plane < n_planes; plane++)
1800 if(cl_err != CL_SUCCESS)
goto out;
1802 for(
int plane = 0; plane < n_planes; plane++)
1804 cl_mem swap_buf = solution_planes[plane];
1805 solution_planes[plane] = scratch_planes[plane];
1806 scratch_planes[plane] = swap_buf;
1811 for(
int plane = 0; plane < n_planes; plane++)
1813 cl_mem swap_buf = prev_level_solution[plane];
1814 prev_level_solution[plane] = solution_planes[plane];
1815 solution_planes[plane] = swap_buf;
1816 level_solution[plane]
1817 = (prev_level_solution[plane] == level_solution[plane]) ? solution_planes[plane] : level_solution[plane];
1818 level_scratch[plane]
1819 = (prev_level_solution[plane] == level_scratch[plane]) ? solution_planes[plane] : level_scratch[plane];
1821 prev_level_w = level_w;
1822 prev_level_h = level_h;
1827 for(
int plane = 0; plane < n_planes; plane++)
1841 if(cl_err != CL_SUCCESS)
goto out;