32 float *
const restrict tensor_xy,
float *
const restrict tensor_yy,
float *
const restrict scratch,
33 const int region_w,
const int region_h)
35 const size_t region_pixels = (size_t)region_w * region_h;
38 for(
int pass = 0; pass < 2; pass++)
40 const float *
const src = (pass == 0) ?
luminance : tensor_xx;
43 for(
int y = 0; y < region_h; y++)
44 for(
int x = 0;
x < region_w;
x++)
49 for(
int offset_y = -1; offset_y <= 1; offset_y++)
50 for(
int offset_x = -1; offset_x <= 1; offset_x++)
52 const int neighbour_y = CLAMP(y + offset_y, 0, region_h - 1);
53 const int neighbour_x = CLAMP(
x + offset_x, 0, region_w - 1);
54 accum += src[(size_t)neighbour_y * region_w + neighbour_x];
58 ((pass == 0) ? tensor_xx : scratch)[(
size_t)y * region_w +
x] = (float)(accum / count);
63 double grad_sum = 0.0;
66 for(
int y = 0; y < region_h; y++)
67 for(
int x = 0;
x < region_w;
x++)
69 const int x_lo =
MAX(
x - 1, 0), x_hi =
MIN(
x + 1, region_w - 1);
70 const int y_lo =
MAX(y - 1, 0), y_hi =
MIN(y + 1, region_h - 1);
71 const float grad_x = 0.5f * (scratch[(size_t)y * region_w + x_hi] - scratch[(
size_t)y * region_w + x_lo]);
72 const float grad_y = 0.5f * (scratch[(size_t)y_hi * region_w +
x] - scratch[(
size_t)y_lo * region_w +
x]);
73 tensor_xx[(size_t)y * region_w +
x] = grad_x;
74 tensor_xy[(size_t)y * region_w +
x] = grad_y;
75 grad_sum += dt_fast_hypotf(grad_x, grad_y);
78 const float grad_mean = fmaxf((
float)(grad_sum / (
double)region_pixels), 1e-9f);
82 for(
size_t i = 0;
i < region_pixels;
i++)
84 const float grad_x = tensor_xx[
i];
85 const float grad_y = tensor_xy[
i];
86 const float grad_mag = dt_fast_hypotf(grad_x, grad_y);
87 const float nonzero = (grad_mag > 1e-12f) ? 1.f : 0.f;
88 const float inv_mag = nonzero / (grad_mag + (1.f - nonzero));
89 const float grad_unit_x = grad_x * inv_mag + (1.f - nonzero);
90 const float grad_unit_y = grad_y * inv_mag;
91 const float cross_damp = expf(-grad_mag / (4.f * grad_mean));
92 const float isophote_x = -grad_unit_y, isophote_y = grad_unit_x;
95 tensor_xx[
i] = isophote_x * isophote_x + cross_damp * grad_unit_x * grad_unit_x;
96 tensor_xy[
i] = isophote_x * isophote_y + cross_damp * grad_unit_x * grad_unit_y;
97 tensor_yy[
i] = isophote_y * isophote_y + cross_damp * grad_unit_y * grad_unit_y;
103 const uint8_t *
const restrict hole,
const float *
const restrict tensor_xx,
104 const float *
const restrict tensor_xy,
const float *
const restrict tensor_yy,
105 float *
const restrict tmp,
const int region_w,
const int region_h,
const int iters,
106 const int box_x_lo,
const int box_y_lo,
const int box_x_hi,
const int box_y_hi,
107 const float react,
const float react_target)
112 for(
int y = box_y_lo; y <= box_y_hi; y++)
113 for(
int x = box_x_lo;
x <= box_x_hi;
x++)
115 const size_t i = (size_t)y * region_w +
x;
116 if(hole[
i]) field[
i] = fmaxf(field[
i], obstacle[
i]);
119 for(
int iter = 0; iter < iters; iter++)
122 for(
int y = box_y_lo; y <= box_y_hi; y++)
123 for(
int x = box_x_lo;
x <= box_x_hi;
x++)
125 const size_t i = (size_t)y * region_w +
x;
133 const int x_lo =
MAX(
x - 1, 0), x_hi =
MIN(
x + 1, region_w - 1);
134 const int y_lo =
MAX(y - 1, 0), y_hi =
MIN(y + 1, region_h - 1);
135 const float center = field[
i];
137 const float d2_xx = field[(size_t)y * region_w + x_hi] - 2.f * center + field[(
size_t)y * region_w + x_lo];
138 const float d2_yy = field[(size_t)y_hi * region_w +
x] - 2.f * center + field[(
size_t)y_lo * region_w +
x];
139 const float d2_xy = 0.25f
140 * (field[(size_t)y_hi * region_w + x_hi] - field[(
size_t)y_hi * region_w + x_lo]
141 - field[(size_t)y_lo * region_w + x_hi] + field[(
size_t)y_lo * region_w + x_lo]);
149 tmp[
i] = fmaxf(center + 0.18f * (tensor_xx[
i] * d2_xx + 2.f * tensor_xy[
i] * d2_xy + tensor_yy[
i] * d2_yy)
150 - 0.18f * react * (center - react_target),
155 for(
int y = box_y_lo; y <= box_y_hi; y++)
156 memcpy(field + (
size_t)y * region_w + box_x_lo, tmp + (
size_t)y * region_w + box_x_lo,
157 (
size_t)(box_x_hi - box_x_lo + 1) *
sizeof(
float));
162 const float *
const restrict
luminance,
float *
const restrict scratch_planes,
163 const int region_w,
const int region_h,
const float react,
166 const size_t region_pixels = (size_t)region_w * region_h;
167 float *
const restrict tensor_xx = scratch_planes;
168 float *
const restrict tensor_xy = scratch_planes + region_pixels;
169 float *
const restrict tensor_yy = scratch_planes + 2 * region_pixels;
170 float *
const restrict tensor_scratch = scratch_planes + 3 * region_pixels;
174 for(
size_t i = 0;
i < region_pixels;
i++)
176 const int is_hole = (valid[
i * 4 + 0] < 0.5f);
177 if(is_hole != (valid[
i * 4 + 1] < 0.5f) || is_hole != (valid[
i * 4 + 2] < 0.5f))
return 0;
178 n_unknowns += is_hole;
180 if(n_unknowns == 0)
return 1;
192 double *right_hand_side
194 int *matrix_row_index = NULL;
195 double *matrix_values = NULL;
196 int success = (grid_to_unknown && unknown_to_grid && unknown_x && unknown_y &&
permutation && inverse_perm
197 && matrix_col_ptr && right_hand_side);
201 int unknown_index = 0;
202 for(
size_t i = 0;
i < region_pixels;
i++)
204 const int is_hole = (valid[
i * 4 + 0] < 0.5f);
205 grid_to_unknown[
i] = is_hole ? unknown_index : -1;
208 unknown_to_grid[unknown_index] = (int)
i;
209 unknown_y[unknown_index] = (int)(
i / region_w);
210 unknown_x[unknown_index] = (int)(
i - (
size_t)unknown_y[unknown_index] * region_w);
217 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
218 inverse_perm[
permutation[perm_index]] = perm_index;
220 static const int neighbour_dy[8] = { 0, 0, -1, 1, -1, 1, -1, 1 };
221 static const int neighbour_dx[8] = { -1, 1, 0, 0, -1, 1, 1, -1 };
223 for(
int pass = 0; pass < 2 && success; pass++)
228 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
230 const int col_count = matrix_col_ptr[perm_index];
231 matrix_col_ptr[perm_index] = total;
234 matrix_col_ptr[n_unknowns] = total;
237 if(!matrix_row_index || !matrix_values)
240 memset(right_hand_side, 0,
sizeof(
double) * (
size_t)n_unknowns * 3);
243 for(
int perm_index = 0; perm_index < n_unknowns && success; perm_index++)
245 const int origin_grid = unknown_to_grid[
permutation[perm_index]];
246 const int origin_y = origin_grid / region_w;
247 const int origin_x = origin_grid - origin_y * region_w;
248 double diagonal = 0.0;
249 int n_col_entries = 0;
251 for(
int edge = 0; edge < 8; edge++)
253 const int neighbour_x = origin_x + neighbour_dx[edge];
254 const int neighbour_y = origin_y + neighbour_dy[edge];
256 if(neighbour_x < 0 || neighbour_y < 0 || neighbour_x >= region_w || neighbour_y >= region_h)
258 const size_t j = (size_t)neighbour_y * region_w + neighbour_x;
259 const float weight =
_aniso_edge_w(tensor_xx, tensor_xy, tensor_yy, (
size_t)origin_grid, j,
260 neighbour_dx[edge], neighbour_dy[edge]);
261 if(
weight <= 0.f)
continue;
264 if(grid_to_unknown[j] >= 0)
266 const int target_row = inverse_perm[grid_to_unknown[j]];
267 if(target_row < perm_index)
271 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = target_row;
272 matrix_values[matrix_col_ptr[perm_index] + n_col_entries]
281 for(
int c = 0; c < 3; c++)
282 right_hand_side[(
size_t)c * n_unknowns + perm_index] += (
double)
weight * ratios[j * 4 + c];
292 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = perm_index;
293 matrix_values[matrix_col_ptr[perm_index] + n_col_entries] = diagonal + (
double)react;
295 for(
int c = 0; c < 3; c++)
296 right_hand_side[(
size_t)c * n_unknowns + perm_index] += (
double)react * react_target[c];
299 if(pass == 0) matrix_col_ptr[perm_index] = n_col_entries;
308 for(
int c = 0; c < 3; c++)
311 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
312 ratios[(
size_t)unknown_to_grid[
permutation[perm_index]] * 4 + c]
313 = (float)right_hand_side[(
size_t)c * n_unknowns + perm_index];
343 const float epsilon = ctx->
epsilon;
344 float *
const restrict estimate = ctx->
estimate;
345 float *
const restrict prev_scale = ctx->
prev_scale;
346 float *
const restrict valid = ctx->
valid;
347 float *
const restrict blur_in = ctx->
blur_in;
348 float *
const restrict plane1 = ctx->
plane1;
349 float *
const restrict clip0 = ctx->
clip0;
350 uint8_t *
const restrict hole = ctx->
hole;
352 float *
const restrict lum_accum = ctx->
lum_accum;
354 float *
const restrict flat_target = ctx->
flat_target;
386 for(
size_t i = 0;
i < region_pixels;
i++)
388 const int allc = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
390 for(
int c = 0; c < 4; c++)
391 prev_scale[
i * 4 + c] = allc ? valid[
i * 4 + c] : fmaxf(valid[
i * 4 + c], 0.6f);
394 const float *
const restrict vld_an = prev_scale;
400 for(
size_t i = 0;
i < region_pixels;
i++)
402 const float lum_val = fmaxf(estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2], epsilon);
403 lum_accum[
i] = lum_val;
405 for(
int c = 0; c < 3; c++)
406 plane1[
i * 4 + c] = estimate[
i * 4 + c] / lum_val;
412 int abx0 = region_w, aby0 = region_h, abx1 = -1, aby1 = -1;
413 for(
int y = 0; y < region_h; y++)
414 for(
int x = 0;
x < region_w;
x++)
416 const size_t i = (size_t)y * region_w +
x;
417 if(vld_an[
i * 4 + 0] < 0.5f || vld_an[
i * 4 + 1] < 0.5f || vld_an[
i * 4 + 2] < 0.5f)
428 if(n_aniso == 0) aniso_done = 1;
437 if(react > 0.f && !aniso_done)
439 double target_accum[3] = { 0.0, 0.0, 0.0 };
440 double target_count = 0.0;
441 for(
size_t i = 0;
i < region_pixels;
i++)
443 if(!(valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f))
continue;
444 for(
int c = 0; c < 3; c++) target_accum[c] += (
double)plane1[
i * 4 + c];
447 if(target_count > 0.0)
448 for(
int c = 0; c < 3; c++) react_target[c] = (
float)(target_accum[c] / target_count);
454 aniso_done =
_aniso_div_solve(plane1, vld_an, lum_accum, blur_in, region_w, region_h, react,
460 while(((
int)region->
radius >> (nlev - 1)) > 8 && nlev < 7) nlev++;
467 for(
int level = nlev - 1; level >= 0; level--)
469 const int step = 1 << level;
470 const int down_w = (region_w + step - 1) / step;
471 const int down_h = (region_h + step - 1) / step;
472 const size_t down_pixels = (size_t)down_w * down_h;
481 uint8_t *
const restrict dhole
483 uint8_t *
const restrict hplane
486 if(!dome_L || !dome_ratio || !tensor_xx || !tensor_xy || !tensor_yy || !tensor_scratch || !dobs || !dobc
487 || !dhole || !hplane)
505 for(
int cell_y = 0; cell_y < down_h; cell_y++)
506 for(
int cell_x = 0; cell_x < down_w; cell_x++)
509 double accr[3] = { 0.0, 0.0, 0.0 };
510 int n_unknowns[3] = { 0, 0, 0 };
513 double accc[3] = { 0.0, 0.0, 0.0 };
514 for(
int nb_y = cell_y * step; nb_y <
MIN((cell_y + 1) * step, region_h); nb_y++)
515 for(
int nb_x = cell_x * step; nb_x <
MIN((cell_x + 1) * step, region_w); nb_x++)
517 const size_t fine_index = (size_t)nb_y * region_w + nb_x;
518 accL += lum_accum[fine_index];
521 for(
int c = 0; c < 3; c++)
523 accr[c] += plane1[fine_index * 4 + c];
524 accc[c] += clip0[fine_index * 4 + c];
525 n_unknowns[c] += (vld_an[fine_index * 4 + c] < 0.5f);
529 const size_t cell_index = (size_t)cell_y * down_w + cell_x;
530 dome_L[cell_index] = (float)(accL / n_total);
532 for(
int c = 0; c < 3; c++)
534 dome_ratio[cell_index * 3 + c] = (float)(accr[c] / n_total);
536 dobs[cell_index * 3 + c] = (float)(accc[c] / fmax(accL, 1e-9));
537 dhole[cell_index * 3 + c] = (2 * n_unknowns[c] > n_total) ? 1 : 0;
543 _aniso_tensor(dome_L, tensor_xx, tensor_xy, tensor_yy, tensor_scratch, down_w, down_h);
545 const int box_x_lo =
MAX(abx0 / step - 2, 0), box_y_lo =
MAX(aby0 / step - 2, 0);
546 const int box_x_hi =
MIN(abx1 / step + 2, down_w - 1), box_y_hi =
MIN(aby1 / step + 2, down_h - 1);
548 for(
int c = 0; c < 3; c++)
550 size_t n_channels = 0;
552 for(
size_t cell_index = 0; cell_index < down_pixels; cell_index++)
554 dome_L[cell_index] = dome_ratio[cell_index * 3 + c];
555 dobc[cell_index] = dobs[cell_index * 3 + c];
556 hplane[cell_index] = dhole[cell_index * 3 + c];
557 n_channels += hplane[cell_index];
560 if(n_channels == 0)
continue;
562 _aniso_iterate_obs(dome_L, dobc, hplane, tensor_xx, tensor_xy, tensor_yy, tensor_scratch, down_w, down_h,
563 240, box_x_lo, box_y_lo, box_x_hi, box_y_hi, 0.f, 0.f);
566 for(
size_t cell_index = 0; cell_index < down_pixels; cell_index++)
567 dome_ratio[cell_index * 3 + c] = dome_L[cell_index];
573 for(
int y = 0; y < region_h; y++)
574 for(
int x = 0;
x < region_w;
x++)
576 const size_t fine_index = (size_t)y * region_w +
x;
577 const float grad_x = ((float)
x + 0.5f) / step - 0.5f;
578 const float grad_y = ((float)y + 0.5f) / step - 0.5f;
579 const int x_lo = CLAMP((
int)floorf(grad_x), 0, down_w - 1);
580 const int y_lo = CLAMP((
int)floorf(grad_y), 0, down_h - 1);
581 const int x_hi =
MIN(x_lo + 1, down_w - 1);
582 const int y_hi =
MIN(y_lo + 1, down_h - 1);
583 const float frac_x = CLAMP(grad_x - x_lo, 0.f, 1.f);
584 const float frac_y = CLAMP(grad_y - y_lo, 0.f, 1.f);
586 for(
int c = 0; c < 3; c++)
588 if(vld_an[fine_index * 4 + c] >= 0.5f)
continue;
590 const float interp_a = dome_ratio[((size_t)y_lo * down_w + x_lo) * 3 + c] * (1.f - frac_x)
591 + dome_ratio[((
size_t)y_lo * down_w + x_hi) * 3 + c] * frac_x;
592 const float interp_b = dome_ratio[((size_t)y_hi * down_w + x_lo) * 3 + c] * (1.f - frac_x)
593 + dome_ratio[((
size_t)y_hi * down_w + x_hi) * 3 + c] * frac_x;
594 plane1[fine_index * 4 + c] = interp_a * (1.f - frac_y) + interp_b * frac_y;
617 for(
size_t i = 0;
i < region_pixels;
i++)
618 hole[
i] = (vld_an[
i * 4 + 0] < 0.5f && vld_an[
i * 4 + 1] < 0.5f && vld_an[
i * 4 + 2] < 0.5f);
625 int act0 = 0, act1 = 0, act2 = 0;
626 HL_PFOR(reduction(| : act0, act1, act2))
627 for(
size_t i = 0;
i < region_pixels;
i++)
629 if(!hole[
i])
continue;
630 const float invL = 1.f / fmaxf(lum_accum[
i], epsilon);
631 act0 |= (plane1[
i * 4 + 0] <= clip0[
i * 4 + 0] * invL * 1.001f);
632 act1 |= (plane1[
i * 4 + 1] <= clip0[
i * 4 + 1] * invL * 1.001f);
633 act2 |= (plane1[
i * 4 + 2] <= clip0[
i * 4 + 2] * invL * 1.001f);
637 const int react_on = (react > 0.f);
638 const int active[3] = { act0 | react_on, act1 | react_on, act2 | react_on };
640 if(act0 | act1 | act2 | react_on)
642 float *
const restrict otxx = blur_in + 0 * region_pixels;
643 float *
const restrict otxy = blur_in + 1 * region_pixels;
644 float *
const restrict otyy = blur_in + 2 * region_pixels;
645 float *
const restrict otsc = blur_in + 3 * region_pixels;
646 _aniso_tensor(lum_accum, otxx, otxy, otyy, otsc, region_w, region_h);
648 for(
int c = 0; c < 3; c++)
650 if(!active[c])
continue;
653 for(
size_t i = 0;
i < region_pixels;
i++)
655 solver_field[
i] = plane1[
i * 4 + c];
656 reaction_weight[
i] = clip0[
i * 4 + c] / fmaxf(lum_accum[
i], epsilon);
659 _aniso_iterate_obs(solver_field, reaction_weight, hole, otxx, otxy, otyy, flat_target, region_w,
660 region_h, 60, abx0, aby0, abx1, aby1, react, react_target[c]);
663 for(
size_t i = 0;
i < region_pixels;
i++) plane1[
i * 4 + c] = solver_field[
i];
681 for(
size_t i = 0;
i < region_pixels;
i++)
683 const float raccum = fmaxf(plane1[
i * 4 + 0] + plane1[
i * 4 + 1] + plane1[
i * 4 + 2], epsilon);
686 if(floor_gate > 1e-6f)
687 for(
int c = 0; c < 3; c++)
688 if(vld_an[
i * 4 + c] < 0.5f)
690 const float ratio_c = fmaxf(plane1[
i * 4 + c], 0.f);
691 const float value = fmaxf(lum_accum[
i] * ratio_c / raccum, 1e-6f);
692 const float clip_floor_c = clip0[
i * 4 + c];
694 const float weight = 0.02f * fmaxf(clip_floor_c, 1e-6f);
696 lift = fmaxf(lift, fminf(target /
value, 8.f));
699 for(
int c = 0; c < 3; c++)
700 if(vld_an[
i * 4 + c] < 0.5f)
702 const float ratio_c = fmaxf(plane1[
i * 4 + c], 0.f);
703 const float value = lum_accum[
i] * ratio_c / raccum;
706 const float clip_floor_c = clip0[
i * 4 + c];
707 const float weight = 0.02f * fmaxf(clip_floor_c, 1e-6f);
710 if(floor_gate <= 1e-6f)
712 estimate[
i * 4 + c] = per_chan;
715 const float lifted = fmaxf(
value, 1e-6f) * lift;
716 const float delta_joint = lifted - clip_floor_c;
718 = clip_floor_c + 0.5f * (delta_joint + sqrtf(delta_joint * delta_joint +
weight *
weight));
719 estimate[
i * 4 + c] = floor_gate * joint + (1.f - floor_gate) * per_chan;
727#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE && (DT_HL_ANISO_SOLVER == 2)
743static cl_int _aniso_pyramid_cl(
const int devid,
void *gd_void, cl_mem ratios, cl_mem valid, cl_mem
luminance,
744 cl_mem clip0,
const int region_w,
const int region_h,
const float radius,
745 const int box_x_lo,
const int box_y_lo,
const int box_x_hi,
const int box_y_hi,
749 cl_int cl_err = CL_SUCCESS;
759 const float no_react = 0.f;
762 while(((
int)radius >> (n_levels - 1)) > 8 && n_levels < 7) n_levels++;
764 for(
int level = n_levels - 1; level >= 0 && cl_err == CL_SUCCESS; level--)
766 const int step = 1 << level;
767 const int coarse_w = (region_w + step - 1) / step;
768 const int coarse_h = (region_h + step - 1) / step;
769 const size_t coarse_pixels = (size_t)coarse_w * coarse_h;
785 if(!coarse_lum || !coarse_ratios || !coarse_obstacle || !coarse_hole || !grad_x || !tensor_xx || !grad_y
786 || !tensor_xy || !tensor_yy || !diffuse_a || !diffuse_b || !grad_partials)
789 if(cl_err == CL_SUCCESS)
809 if(cl_err == CL_SUCCESS)
817 if(cl_err == CL_SUCCESS)
824 if(cl_err == CL_SUCCESS)
826 const int local_size = 64, n_groups = 256;
828 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
829 size_t local[3] = { local_size, 1, 1 };
838 if(cl_err == CL_SUCCESS)
844 const int gstride = 1, gmode = 2;
845 const float gscale = 1.f / (float)coarse_pixels;
846 size_t gone[3] = { 1, 1, 1 };
869 if(cl_err == CL_SUCCESS)
871 const int level_x_lo =
MAX(box_x_lo / step - 2, 0), level_y_lo =
MAX(box_y_lo / step - 2, 0);
872 const int level_x_hi =
MIN(box_x_hi / step + 2, coarse_w - 1),
873 level_y_hi =
MIN(box_y_hi / step + 2, coarse_h - 1);
875 = {
ROUNDUPDWD(level_x_hi - level_x_lo + 1, devid),
ROUNDUPDHT(level_y_hi - level_y_lo + 1, devid), 1 };
877 for(
int c = 0;
c < 3 && cl_err == CL_SUCCESS;
c++)
888 if(cl_err == CL_SUCCESS)
900 if(cl_err == CL_SUCCESS)
902 sizeof(
float) * coarse_pixels);
904 cl_mem current_buf = diffuse_a, other_buf = diffuse_b;
905 if((level_x_hi - level_x_lo + 1) * (level_y_hi - level_y_lo + 1) <= 4096)
909 const int iters = 240;
910 size_t size_block[3] = { 256, 1, 1 };
911 size_t local_block[3] = { 256, 1, 1 };
932 for(
int iter = 0; iter < 240 && cl_err == CL_SUCCESS; iter++)
952 cl_mem swap_buf = current_buf;
953 current_buf = other_buf;
954 other_buf = swap_buf;
956 if(cl_err == CL_SUCCESS)
969 if(cl_err == CL_SUCCESS)
1000cl_int _aniso_stage_cl(
const int devid,
void *gd_void, cl_mem estimate, cl_mem valid, cl_mem clip0,
1001 const int region_w,
const int region_h,
const float radius,
const float floor_gate,
const float solid_color,
const dt_dev_pixelpipe_t *pipe)
1005 const size_t region_pixels = (size_t)region_w * region_h;
1008 const float epsilon = 1e-6f;
1015 const float react = solid_color * solid_color * 4.f;
1016 float react_target[3] = { 0.f, 0.f, 0.f };
1029 cl_mem partials = NULL, perm_grid_dev = NULL, edge_weights_dev = NULL, rhs_dev = NULL;
1031 int *grid_to_unknown = NULL, *unknown_to_grid = NULL, *unknown_x = NULL, *unknown_y = NULL, *
perm = NULL,
1032 *inverse_perm = NULL;
1033 int *matrix_col_ptr = NULL, *matrix_row_index = NULL, *perm_grid = NULL;
1034 double *matrix_values = NULL;
1035 float *edge_weights = NULL;
1037 if(!valid_packed || !
luminance || !ratios || !hole || !scratch1 || !scratch2 || !tensor_xx || !tensor_xy
1038 || !tensor_yy || !hole_mask)
1054 if(cl_err != CL_SUCCESS)
goto out;
1058 if(cl_err != CL_SUCCESS)
goto out;
1061 for(
size_t i = 0;
i < region_pixels;
i++)
1062 if(hole_mask[
i]) n_unknowns++;
1065 cl_err = CL_SUCCESS;
1068 int box_x_lo = region_w, box_y_lo = region_h, box_x_hi = -1, box_y_hi = -1;
1069 for(
int y = 0; y < region_h; y++)
1070 for(
int x = 0;
x < region_w;
x++)
1071 if(hole_mask[(
size_t)y * region_w +
x])
1073 box_x_lo =
MIN(box_x_lo,
x);
1074 box_x_hi =
MAX(box_x_hi,
x);
1075 box_y_lo =
MIN(box_y_lo, y);
1076 box_y_hi =
MAX(box_y_hi, y);
1083 const int local_size = 64, n_groups = 256;
1084 const int n_pixels = (int)region_pixels;
1095 const float zero = 0.f;
1098 size_t one[3] = { 1, 1, 1 };
1100 if(cl_err != CL_SUCCESS)
1107 if(!target_partials)
1113 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
1114 size_t local[3] = { local_size, 1, 1 };
1124 float partial_host[4 * 256];
1125 if(cl_err == CL_SUCCESS)
1127 sizeof(
float) * 4 * n_groups, CL_TRUE);
1130 if(cl_err != CL_SUCCESS)
goto out;
1131 double accum[4] = { 0.0, 0.0, 0.0, 0.0 };
1132 for(
int group = 0; group < n_groups; group++)
1133 for(
int k = 0;
k < 4;
k++) accum[
k] += (
double)partial_host[group * 4 +
k];
1135 for(
int c = 0;
c < 3;
c++) react_target[c] = (
float)(accum[
c] / accum[3]);
1141 cl_err = _aniso_pyramid_cl(devid, gd_void, ratios, valid_packed,
luminance, clip0, region_w, region_h, radius,
1142 box_x_lo, box_y_lo, box_x_hi, box_y_hi, pipe);
1143 if(cl_err != CL_SUCCESS)
goto out;
1155 if(cl_err != CL_SUCCESS)
goto out;
1159 if(cl_err != CL_SUCCESS)
goto out;
1162 const int local_size = 64, n_groups = 256;
1170 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
1171 size_t local[3] = { local_size, 1, 1 };
1180 if(cl_err != CL_SUCCESS)
goto out;
1184 const int gstride = 1, gmode = 2;
1185 const float gscale = 1.f / (float)region_pixels;
1186 size_t gone[3] = { 1, 1, 1 };
1194 if(cl_err != CL_SUCCESS)
goto out;
1207 if(cl_err != CL_SUCCESS)
goto out;
1221 if(!grid_to_unknown || !unknown_to_grid || !unknown_x || !unknown_y || !
perm || !inverse_perm || !matrix_col_ptr
1222 || !perm_grid || !edge_weights)
1228 int unknown_index = 0;
1229 for(
size_t i = 0;
i < region_pixels;
i++)
1231 grid_to_unknown[
i] = hole_mask[
i] ? unknown_index : -1;
1234 unknown_to_grid[unknown_index] = (int)
i;
1235 unknown_y[unknown_index] = (int)(
i / region_w);
1236 unknown_x[unknown_index] = (int)(
i - (
size_t)unknown_y[unknown_index] * region_w);
1240 for(
int i = 0;
i < n_unknowns;
i++)
perm[
i] =
i;
1242 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++) inverse_perm[
perm[perm_index]] = perm_index;
1243 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
1244 perm_grid[perm_index] = unknown_to_grid[
perm[perm_index]];
1248 perm_grid_dev =
_sp_cl_upload(devid, perm_grid,
sizeof(
int) * n_unknowns);
1251 if(!perm_grid_dev || !edge_weights_dev || !rhs_dev)
1258 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1268 if(cl_err != CL_SUCCESS)
goto out;
1271 sizeof(
float) * (
size_t)n_unknowns * 8, CL_TRUE);
1272 if(cl_err != CL_SUCCESS)
goto out;
1276 static const int neighbour_dy[8] = { 0, 0, -1, 1, -1, 1, -1, 1 };
1277 static const int neighbour_dx[8] = { -1, 1, 0, 0, -1, 1, 1, -1 };
1279 for(
int pass = 0; pass < 2 && success; pass++)
1284 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
1286 const int c = matrix_col_ptr[perm_index];
1287 matrix_col_ptr[perm_index] = total;
1290 matrix_col_ptr[n_unknowns] = total;
1293 if(!matrix_row_index || !matrix_values) success = 0;
1296 for(
int perm_index = 0; perm_index < n_unknowns && success; perm_index++)
1298 const int origin_grid = perm_grid[perm_index];
1299 const int origin_y = origin_grid / region_w, origin_x = origin_grid - origin_y * region_w;
1301 int n_col_entries = 0;
1303 for(
int edge = 0; edge < 8; edge++)
1305 const float weight_value = edge_weights[(size_t)perm_index * 8 + edge];
1308 if(!(weight_value > 0.f))
continue;
1309 const int neighbour_x = origin_x + neighbour_dx[edge], neighbour_y = origin_y + neighbour_dy[edge];
1310 if(neighbour_x < 0 || neighbour_y < 0 || neighbour_x >= region_w || neighbour_y >= region_h)
1312 diag += weight_value;
1313 const size_t j = (size_t)neighbour_y * region_w + neighbour_x;
1314 if(grid_to_unknown[j] >= 0)
1316 const int target_row = inverse_perm[grid_to_unknown[j]];
1317 if(target_row < perm_index)
1321 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = target_row;
1322 matrix_values[matrix_col_ptr[perm_index] + n_col_entries] = -(
double)weight_value;
1330 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = perm_index;
1331 matrix_values[matrix_col_ptr[perm_index] + n_col_entries] = diag + (
double)react;
1334 if(pass == 0) matrix_col_ptr[perm_index] = n_col_entries;
1352 for(
int c = 0;
c < 3;
c++)
1356 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1369 if(cl_err != CL_SUCCESS)
goto out;
1378 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1385 if(cl_err != CL_SUCCESS)
goto out;
1402 if(!grad_y || !dobs3 || !dhole3 || !diffuse_a || !diffuse_b || !ppart || !aflags)
1406 if(cl_err == CL_SUCCESS)
1414 if(cl_err == CL_SUCCESS)
1421 if(cl_err == CL_SUCCESS)
1423 const int local_size = 64, n_groups = 256;
1425 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
1426 size_t local[3] = { local_size, 1, 1 };
1435 if(cl_err == CL_SUCCESS)
1439 const int gstride = 1, gmode = 2, gn = 256;
1440 const float gscale = 1.f / (float)region_pixels;
1441 size_t gone[3] = { 1, 1, 1 };
1449 if(cl_err != CL_SUCCESS)
goto out;
1463 if(cl_err == CL_SUCCESS)
1479 int active[3] = { 0, 0, 0 };
1480 if(cl_err == CL_SUCCESS)
1483 if(cl_err == CL_SUCCESS)
1494 if(cl_err == CL_SUCCESS)
1498 if(react > 0.f) active[0] = active[1] = active[2] = 1;
1501 = {
ROUNDUPDWD(box_x_hi - box_x_lo + 1, devid),
ROUNDUPDHT(box_y_hi - box_y_lo + 1, devid), 1 };
1502 for(
int c = 0;
c < 3 && cl_err == CL_SUCCESS;
c++)
1504 if(!active[c])
continue;
1514 if(cl_err == CL_SUCCESS)
1525 if(cl_err == CL_SUCCESS)
1527 sizeof(
float) * region_pixels);
1529 cl_mem current_buf = diffuse_a, other_buf = diffuse_b;
1530 for(
int iter = 0; iter < 60 && cl_err == CL_SUCCESS; iter++)
1550 cl_mem swap_buf = current_buf;
1551 current_buf = other_buf;
1552 other_buf = swap_buf;
1554 if(cl_err == CL_SUCCESS)
1573 if(cl_err != CL_SUCCESS)
goto out;
__DT_CLONE_TARGETS__ void _aniso_iterate_obs(float *const restrict field, const float *const restrict obstacle, const uint8_t *const restrict hole, const float *const restrict tensor_xx, const float *const restrict tensor_xy, const float *const restrict tensor_yy, float *const restrict tmp, const int region_w, const int region_h, const int iters, const int box_x_lo, const int box_y_lo, const int box_x_hi, const int box_y_hi, const float react, const float react_target)
__DT_CLONE_TARGETS__ void _aniso_tensor(const float *const restrict luminance, float *const restrict tensor_xx, float *const restrict tensor_xy, float *const restrict tensor_yy, float *const restrict scratch, const int region_w, const int region_h)
int _aniso_div_solve(float *const restrict ratios, const float *const restrict valid, const float *const restrict luminance, float *const restrict scratch_planes, const int region_w, const int region_h, const float react, const dt_aligned_pixel_t react_target, const dt_dev_pixelpipe_t *pipe)
__DT_CLONE_TARGETS__ void _aniso_chroma(_hl_region_ctx_t *const ctx)
static float _aniso_edge_w(const float *const restrict tensor_xx, const float *const restrict tensor_xy, const float *const restrict tensor_yy, const size_t i, const size_t j, const int offset_x, const int offset_y)
const dt_colormatrix_t dt_aligned_pixel_t out
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
static float kernel(const float *x, const float *y)
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)
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)
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__(...)
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 const dt_aligned_pixel_simd_t value
static void _sp_nd_order(int *const restrict unknown_ids, const int count, const int *const restrict unknown_x, const int *const restrict unknown_y, const int reach)
static void _sp_chol_free(_sp_chol_t *factor)
static void _sp_chol_solve(const _sp_chol_t *const factor, double *const restrict rhs)
static _sp_chol_t * _sp_chol_factor(const int dimension, const int *const restrict matrix_col_ptr, const int *const restrict matrix_row_index, const double *const restrict matrix_values, const int cache_id)
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)
const _hl_region_t * region
const dt_dev_pixelpipe_t * pipe
dt_dev_pixelpipe_type_t type
int kernel_hl_aniso_splat
int kernel_hl_aniso_reassemble
int kernel_hl_aniso_pyr_down
int kernel_hl_aniso_obs_flags
int kernel_hl_aniso_obs_full
int kernel_hl_pyr_project
int kernel_hl_grad_reduce
int kernel_hl_aniso_scatter
int kernel_hl_aniso_iter_block
int kernel_hl_aniso_tensor
int kernel_hl_cmean_reduce
int kernel_hl_reduce_finalize
int kernel_hl_aniso_weights
#define __DT_CLONE_TARGETS__
typedef double((*spd)(unsigned long int wavelength, double TempK))