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)
111 for(
int y = box_y_lo; y <= box_y_hi; y++)
112 for(
int x = box_x_lo;
x <= box_x_hi;
x++)
114 const size_t i = (size_t)y * region_w +
x;
115 if(hole[
i]) field[
i] = fmaxf(field[
i], obstacle[
i]);
118 for(
int iter = 0; iter < iters; iter++)
121 for(
int y = box_y_lo; y <= box_y_hi; y++)
122 for(
int x = box_x_lo;
x <= box_x_hi;
x++)
124 const size_t i = (size_t)y * region_w +
x;
132 const int x_lo =
MAX(
x - 1, 0), x_hi =
MIN(
x + 1, region_w - 1);
133 const int y_lo =
MAX(y - 1, 0), y_hi =
MIN(y + 1, region_h - 1);
134 const float center = field[
i];
136 const float d2_xx = field[(size_t)y * region_w + x_hi] - 2.f * center + field[(
size_t)y * region_w + x_lo];
137 const float d2_yy = field[(size_t)y_hi * region_w +
x] - 2.f * center + field[(
size_t)y_lo * region_w +
x];
138 const float d2_xy = 0.25f
139 * (field[(size_t)y_hi * region_w + x_hi] - field[(
size_t)y_hi * region_w + x_lo]
140 - field[(size_t)y_lo * region_w + x_hi] + field[(
size_t)y_lo * region_w + x_lo]);
144 tmp[
i] = fmaxf(center + 0.18f * (tensor_xx[
i] * d2_xx + 2.f * tensor_xy[
i] * d2_xy + tensor_yy[
i] * d2_yy),
149 for(
int y = box_y_lo; y <= box_y_hi; y++)
150 memcpy(field + (
size_t)y * region_w + box_x_lo, tmp + (
size_t)y * region_w + box_x_lo,
151 (
size_t)(box_x_hi - box_x_lo + 1) *
sizeof(
float));
156 const float *
const restrict
luminance,
float *
const restrict scratch_planes,
159 const size_t region_pixels = (size_t)region_w * region_h;
160 float *
const restrict tensor_xx = scratch_planes;
161 float *
const restrict tensor_xy = scratch_planes + region_pixels;
162 float *
const restrict tensor_yy = scratch_planes + 2 * region_pixels;
163 float *
const restrict tensor_scratch = scratch_planes + 3 * region_pixels;
167 for(
size_t i = 0;
i < region_pixels;
i++)
169 const int is_hole = (valid[
i * 4 + 0] < 0.5f);
170 if(is_hole != (valid[
i * 4 + 1] < 0.5f) || is_hole != (valid[
i * 4 + 2] < 0.5f))
return 0;
171 n_unknowns += is_hole;
173 if(n_unknowns == 0)
return 1;
185 double *right_hand_side
187 int *matrix_row_index = NULL;
188 double *matrix_values = NULL;
189 int success = (grid_to_unknown && unknown_to_grid && unknown_x && unknown_y &&
permutation && inverse_perm
190 && matrix_col_ptr && right_hand_side);
194 int unknown_index = 0;
195 for(
size_t i = 0;
i < region_pixels;
i++)
197 const int is_hole = (valid[
i * 4 + 0] < 0.5f);
198 grid_to_unknown[
i] = is_hole ? unknown_index : -1;
201 unknown_to_grid[unknown_index] = (int)
i;
202 unknown_y[unknown_index] = (int)(
i / region_w);
203 unknown_x[unknown_index] = (int)(
i - (
size_t)unknown_y[unknown_index] * region_w);
210 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
211 inverse_perm[
permutation[perm_index]] = perm_index;
213 static const int neighbour_dy[8] = { 0, 0, -1, 1, -1, 1, -1, 1 };
214 static const int neighbour_dx[8] = { -1, 1, 0, 0, -1, 1, 1, -1 };
216 for(
int pass = 0; pass < 2 && success; pass++)
221 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
223 const int col_count = matrix_col_ptr[perm_index];
224 matrix_col_ptr[perm_index] = total;
227 matrix_col_ptr[n_unknowns] = total;
230 if(!matrix_row_index || !matrix_values)
233 memset(right_hand_side, 0,
sizeof(
double) * (
size_t)n_unknowns * 3);
236 for(
int perm_index = 0; perm_index < n_unknowns && success; perm_index++)
238 const int origin_grid = unknown_to_grid[
permutation[perm_index]];
239 const int origin_y = origin_grid / region_w;
240 const int origin_x = origin_grid - origin_y * region_w;
241 double diagonal = 0.0;
242 int n_col_entries = 0;
244 for(
int edge = 0; edge < 8; edge++)
246 const int neighbour_x = origin_x + neighbour_dx[edge];
247 const int neighbour_y = origin_y + neighbour_dy[edge];
249 if(neighbour_x < 0 || neighbour_y < 0 || neighbour_x >= region_w || neighbour_y >= region_h)
251 const size_t j = (size_t)neighbour_y * region_w + neighbour_x;
252 const float weight =
_aniso_edge_w(tensor_xx, tensor_xy, tensor_yy, (
size_t)origin_grid, j,
253 neighbour_dx[edge], neighbour_dy[edge]);
254 if(
weight <= 0.f)
continue;
257 if(grid_to_unknown[j] >= 0)
259 const int target_row = inverse_perm[grid_to_unknown[j]];
260 if(target_row < perm_index)
264 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = target_row;
265 matrix_values[matrix_col_ptr[perm_index] + n_col_entries]
274 for(
int c = 0; c < 3; c++)
275 right_hand_side[(
size_t)c * n_unknowns + perm_index] += (
double)
weight * ratios[j * 4 + c];
281 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = perm_index;
282 matrix_values[matrix_col_ptr[perm_index] + n_col_entries] = diagonal;
285 if(pass == 0) matrix_col_ptr[perm_index] = n_col_entries;
294 for(
int c = 0; c < 3; c++)
297 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
298 ratios[(
size_t)unknown_to_grid[
permutation[perm_index]] * 4 + c]
299 = (float)right_hand_side[(
size_t)c * n_unknowns + perm_index];
329 const float epsilon = ctx->
epsilon;
330 float *
const restrict estimate = ctx->
estimate;
331 float *
const restrict prev_scale = ctx->
prev_scale;
332 float *
const restrict valid = ctx->
valid;
333 float *
const restrict blur_in = ctx->
blur_in;
334 float *
const restrict plane1 = ctx->
plane1;
335 float *
const restrict clip0 = ctx->
clip0;
336 uint8_t *
const restrict hole = ctx->
hole;
338 float *
const restrict lum_accum = ctx->
lum_accum;
340 float *
const restrict flat_target = ctx->
flat_target;
372 for(
size_t i = 0;
i < region_pixels;
i++)
374 const int allc = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
376 for(
int c = 0; c < 4; c++)
377 prev_scale[
i * 4 + c] = allc ? valid[
i * 4 + c] : fmaxf(valid[
i * 4 + c], 0.6f);
380 const float *
const restrict vld_an = prev_scale;
386 for(
size_t i = 0;
i < region_pixels;
i++)
388 const float lum_val = fmaxf(estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2], epsilon);
389 lum_accum[
i] = lum_val;
391 for(
int c = 0; c < 3; c++)
392 plane1[
i * 4 + c] = estimate[
i * 4 + c] / lum_val;
398 int abx0 = region_w, aby0 = region_h, abx1 = -1, aby1 = -1;
399 for(
int y = 0; y < region_h; y++)
400 for(
int x = 0;
x < region_w;
x++)
402 const size_t i = (size_t)y * region_w +
x;
403 if(vld_an[
i * 4 + 0] < 0.5f || vld_an[
i * 4 + 1] < 0.5f || vld_an[
i * 4 + 2] < 0.5f)
414 if(n_aniso == 0) aniso_done = 1;
418 if(!aniso_done) aniso_done =
_aniso_div_solve(plane1, vld_an, lum_accum, blur_in, region_w, region_h, pipe);
423 while(((
int)region->
radius >> (nlev - 1)) > 8 && nlev < 7) nlev++;
430 for(
int level = nlev - 1; level >= 0; level--)
432 const int step = 1 << level;
433 const int down_w = (region_w + step - 1) / step;
434 const int down_h = (region_h + step - 1) / step;
435 const size_t down_pixels = (size_t)down_w * down_h;
444 uint8_t *
const restrict dhole
446 uint8_t *
const restrict hplane
449 if(!dome_L || !dome_ratio || !tensor_xx || !tensor_xy || !tensor_yy || !tensor_scratch || !dobs || !dobc
450 || !dhole || !hplane)
468 for(
int cell_y = 0; cell_y < down_h; cell_y++)
469 for(
int cell_x = 0; cell_x < down_w; cell_x++)
472 double accr[3] = { 0.0, 0.0, 0.0 };
473 int n_unknowns[3] = { 0, 0, 0 };
476 double accc[3] = { 0.0, 0.0, 0.0 };
477 for(
int nb_y = cell_y * step; nb_y <
MIN((cell_y + 1) * step, region_h); nb_y++)
478 for(
int nb_x = cell_x * step; nb_x <
MIN((cell_x + 1) * step, region_w); nb_x++)
480 const size_t fine_index = (size_t)nb_y * region_w + nb_x;
481 accL += lum_accum[fine_index];
484 for(
int c = 0; c < 3; c++)
486 accr[c] += plane1[fine_index * 4 + c];
487 accc[c] += clip0[fine_index * 4 + c];
488 n_unknowns[c] += (vld_an[fine_index * 4 + c] < 0.5f);
492 const size_t cell_index = (size_t)cell_y * down_w + cell_x;
493 dome_L[cell_index] = (float)(accL / n_total);
495 for(
int c = 0; c < 3; c++)
497 dome_ratio[cell_index * 3 + c] = (float)(accr[c] / n_total);
499 dobs[cell_index * 3 + c] = (float)(accc[c] / fmax(accL, 1e-9));
500 dhole[cell_index * 3 + c] = (2 * n_unknowns[c] > n_total) ? 1 : 0;
506 _aniso_tensor(dome_L, tensor_xx, tensor_xy, tensor_yy, tensor_scratch, down_w, down_h);
508 const int box_x_lo =
MAX(abx0 / step - 2, 0), box_y_lo =
MAX(aby0 / step - 2, 0);
509 const int box_x_hi =
MIN(abx1 / step + 2, down_w - 1), box_y_hi =
MIN(aby1 / step + 2, down_h - 1);
511 for(
int c = 0; c < 3; c++)
513 size_t n_channels = 0;
515 for(
size_t cell_index = 0; cell_index < down_pixels; cell_index++)
517 dome_L[cell_index] = dome_ratio[cell_index * 3 + c];
518 dobc[cell_index] = dobs[cell_index * 3 + c];
519 hplane[cell_index] = dhole[cell_index * 3 + c];
520 n_channels += hplane[cell_index];
523 if(n_channels == 0)
continue;
525 _aniso_iterate_obs(dome_L, dobc, hplane, tensor_xx, tensor_xy, tensor_yy, tensor_scratch, down_w, down_h,
526 240, box_x_lo, box_y_lo, box_x_hi, box_y_hi);
529 for(
size_t cell_index = 0; cell_index < down_pixels; cell_index++)
530 dome_ratio[cell_index * 3 + c] = dome_L[cell_index];
536 for(
int y = 0; y < region_h; y++)
537 for(
int x = 0;
x < region_w;
x++)
539 const size_t fine_index = (size_t)y * region_w +
x;
540 const float grad_x = ((float)
x + 0.5f) / step - 0.5f;
541 const float grad_y = ((float)y + 0.5f) / step - 0.5f;
542 const int x_lo = CLAMP((
int)floorf(grad_x), 0, down_w - 1);
543 const int y_lo = CLAMP((
int)floorf(grad_y), 0, down_h - 1);
544 const int x_hi =
MIN(x_lo + 1, down_w - 1);
545 const int y_hi =
MIN(y_lo + 1, down_h - 1);
546 const float frac_x = CLAMP(grad_x - x_lo, 0.f, 1.f);
547 const float frac_y = CLAMP(grad_y - y_lo, 0.f, 1.f);
549 for(
int c = 0; c < 3; c++)
551 if(vld_an[fine_index * 4 + c] >= 0.5f)
continue;
553 const float interp_a = dome_ratio[((size_t)y_lo * down_w + x_lo) * 3 + c] * (1.f - frac_x)
554 + dome_ratio[((
size_t)y_lo * down_w + x_hi) * 3 + c] * frac_x;
555 const float interp_b = dome_ratio[((size_t)y_hi * down_w + x_lo) * 3 + c] * (1.f - frac_x)
556 + dome_ratio[((
size_t)y_hi * down_w + x_hi) * 3 + c] * frac_x;
557 plane1[fine_index * 4 + c] = interp_a * (1.f - frac_y) + interp_b * frac_y;
580 for(
size_t i = 0;
i < region_pixels;
i++)
581 hole[
i] = (vld_an[
i * 4 + 0] < 0.5f && vld_an[
i * 4 + 1] < 0.5f && vld_an[
i * 4 + 2] < 0.5f);
588 int act0 = 0, act1 = 0, act2 = 0;
589 HL_PFOR(reduction(| : act0, act1, act2))
590 for(
size_t i = 0;
i < region_pixels;
i++)
592 if(!hole[
i])
continue;
593 const float invL = 1.f / fmaxf(lum_accum[
i], epsilon);
594 act0 |= (plane1[
i * 4 + 0] <= clip0[
i * 4 + 0] * invL * 1.001f);
595 act1 |= (plane1[
i * 4 + 1] <= clip0[
i * 4 + 1] * invL * 1.001f);
596 act2 |= (plane1[
i * 4 + 2] <= clip0[
i * 4 + 2] * invL * 1.001f);
598 const int active[3] = { act0, act1, act2 };
600 if(act0 | act1 | act2)
602 float *
const restrict otxx = blur_in + 0 * region_pixels;
603 float *
const restrict otxy = blur_in + 1 * region_pixels;
604 float *
const restrict otyy = blur_in + 2 * region_pixels;
605 float *
const restrict otsc = blur_in + 3 * region_pixels;
606 _aniso_tensor(lum_accum, otxx, otxy, otyy, otsc, region_w, region_h);
608 for(
int c = 0; c < 3; c++)
610 if(!active[c])
continue;
613 for(
size_t i = 0;
i < region_pixels;
i++)
615 solver_field[
i] = plane1[
i * 4 + c];
616 reaction_weight[
i] = clip0[
i * 4 + c] / fmaxf(lum_accum[
i], epsilon);
619 _aniso_iterate_obs(solver_field, reaction_weight, hole, otxx, otxy, otyy, flat_target, region_w,
620 region_h, 60, abx0, aby0, abx1, aby1);
623 for(
size_t i = 0;
i < region_pixels;
i++) plane1[
i * 4 + c] = solver_field[
i];
634 for(
size_t i = 0;
i < region_pixels;
i++)
636 const float raccum = fmaxf(plane1[
i * 4 + 0] + plane1[
i * 4 + 1] + plane1[
i * 4 + 2], epsilon);
638 for(
int c = 0; c < 3; c++)
639 if(vld_an[
i * 4 + c] < 0.5f)
641 const float ratio_c = fmaxf(plane1[
i * 4 + c], 0.f);
642 const float value = lum_accum[
i] * ratio_c / raccum;
650 const float clip_floor_c = clip0[
i * 4 + c];
652 const float weight = 0.02f * fmaxf(clip_floor_c, 1e-6f);
661#if defined(HAVE_OPENCL) && DT_HL_SPARSE_SOLVE && (DT_HL_ANISO_SOLVER == 2)
677static cl_int _aniso_pyramid_cl(
const int devid,
void *gd_void, cl_mem ratios, cl_mem valid, cl_mem
luminance,
678 cl_mem clip0,
const int region_w,
const int region_h,
const float radius,
679 const int box_x_lo,
const int box_y_lo,
const int box_x_hi,
const int box_y_hi,
683 cl_int cl_err = CL_SUCCESS;
686 while(((
int)radius >> (n_levels - 1)) > 8 && n_levels < 7) n_levels++;
688 for(
int level = n_levels - 1; level >= 0 && cl_err == CL_SUCCESS; level--)
690 const int step = 1 << level;
691 const int coarse_w = (region_w + step - 1) / step;
692 const int coarse_h = (region_h + step - 1) / step;
693 const size_t coarse_pixels = (size_t)coarse_w * coarse_h;
709 if(!coarse_lum || !coarse_ratios || !coarse_obstacle || !coarse_hole || !grad_x || !tensor_xx || !grad_y
710 || !tensor_xy || !tensor_yy || !diffuse_a || !diffuse_b || !grad_partials)
713 if(cl_err == CL_SUCCESS)
733 if(cl_err == CL_SUCCESS)
741 if(cl_err == CL_SUCCESS)
748 if(cl_err == CL_SUCCESS)
750 const int local_size = 64, n_groups = 256;
752 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
753 size_t local[3] = { local_size, 1, 1 };
762 if(cl_err == CL_SUCCESS)
764 float partial_sums[256];
767 if(cl_err == CL_SUCCESS)
769 double grad_sum = 0.0;
770 for(
int group = 0; group < n_groups; group++) grad_sum += (
double)partial_sums[group];
771 const float grad_mean = fmaxf((
float)(grad_sum / (
double)coarse_pixels), 1e-9f);
787 if(cl_err == CL_SUCCESS)
789 const int level_x_lo =
MAX(box_x_lo / step - 2, 0), level_y_lo =
MAX(box_y_lo / step - 2, 0);
790 const int level_x_hi =
MIN(box_x_hi / step + 2, coarse_w - 1),
791 level_y_hi =
MIN(box_y_hi / step + 2, coarse_h - 1);
793 = {
ROUNDUPDWD(level_x_hi - level_x_lo + 1, devid),
ROUNDUPDHT(level_y_hi - level_y_lo + 1, devid), 1 };
795 for(
int c = 0;
c < 3 && cl_err == CL_SUCCESS;
c++)
806 if(cl_err == CL_SUCCESS)
818 if(cl_err == CL_SUCCESS)
820 sizeof(
float) * coarse_pixels);
822 cl_mem current_buf = diffuse_a, other_buf = diffuse_b;
823 if((level_x_hi - level_x_lo + 1) * (level_y_hi - level_y_lo + 1) <= 4096)
827 const int iters = 240;
828 size_t size_block[3] = { 256, 1, 1 };
829 size_t local_block[3] = { 256, 1, 1 };
848 for(
int iter = 0; iter < 240 && cl_err == CL_SUCCESS; iter++)
866 cl_mem swap_buf = current_buf;
867 current_buf = other_buf;
868 other_buf = swap_buf;
870 if(cl_err == CL_SUCCESS)
883 if(cl_err == CL_SUCCESS)
913cl_int _aniso_stage_cl(
const int devid,
void *gd_void, cl_mem estimate, cl_mem valid, cl_mem clip0,
914 const int region_w,
const int region_h,
const float radius,
const dt_dev_pixelpipe_t *pipe)
917 const size_t region_pixels = (size_t)region_w * region_h;
920 const float epsilon = 1e-6f;
933 cl_mem partials = NULL, perm_grid_dev = NULL, edge_weights_dev = NULL, rhs_dev = NULL;
935 int *grid_to_unknown = NULL, *unknown_to_grid = NULL, *unknown_x = NULL, *unknown_y = NULL, *
perm = NULL,
936 *inverse_perm = NULL;
937 int *matrix_col_ptr = NULL, *matrix_row_index = NULL, *perm_grid = NULL;
938 double *matrix_values = NULL;
939 float *edge_weights = NULL;
941 if(!valid_packed || !
luminance || !ratios || !hole || !scratch1 || !scratch2 || !tensor_xx || !tensor_xy
942 || !tensor_yy || !hole_mask)
958 if(cl_err != CL_SUCCESS)
goto out;
962 if(cl_err != CL_SUCCESS)
goto out;
965 for(
size_t i = 0;
i < region_pixels;
i++)
966 if(hole_mask[
i]) n_unknowns++;
972 int box_x_lo = region_w, box_y_lo = region_h, box_x_hi = -1, box_y_hi = -1;
973 for(
int y = 0; y < region_h; y++)
974 for(
int x = 0;
x < region_w;
x++)
975 if(hole_mask[(
size_t)y * region_w +
x])
977 box_x_lo =
MIN(box_x_lo,
x);
978 box_x_hi =
MAX(box_x_hi,
x);
979 box_y_lo =
MIN(box_y_lo, y);
980 box_y_hi =
MAX(box_y_hi, y);
986 cl_err = _aniso_pyramid_cl(devid, gd_void, ratios, valid_packed,
luminance, clip0, region_w, region_h, radius,
987 box_x_lo, box_y_lo, box_x_hi, box_y_hi, pipe);
988 if(cl_err != CL_SUCCESS)
goto out;
1000 if(cl_err != CL_SUCCESS)
goto out;
1004 if(cl_err != CL_SUCCESS)
goto out;
1007 const int local_size = 64, n_groups = 256;
1015 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
1016 size_t local[3] = { local_size, 1, 1 };
1025 if(cl_err != CL_SUCCESS)
goto out;
1029 if(cl_err != CL_SUCCESS)
goto out;
1031 for(
int group_index = 0; group_index < n_groups; group_index++) gsum += (
double)psum[group_index];
1032 const float gnorm = fmaxf((
float)(gsum / (
double)region_pixels), 1e-9f);
1044 if(cl_err != CL_SUCCESS)
goto out;
1058 if(!grid_to_unknown || !unknown_to_grid || !unknown_x || !unknown_y || !
perm || !inverse_perm || !matrix_col_ptr
1059 || !perm_grid || !edge_weights)
1065 int unknown_index = 0;
1066 for(
size_t i = 0;
i < region_pixels;
i++)
1068 grid_to_unknown[
i] = hole_mask[
i] ? unknown_index : -1;
1071 unknown_to_grid[unknown_index] = (int)
i;
1072 unknown_y[unknown_index] = (int)(
i / region_w);
1073 unknown_x[unknown_index] = (int)(
i - (
size_t)unknown_y[unknown_index] * region_w);
1077 for(
int i = 0;
i < n_unknowns;
i++)
perm[
i] =
i;
1079 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++) inverse_perm[
perm[perm_index]] = perm_index;
1080 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
1081 perm_grid[perm_index] = unknown_to_grid[
perm[perm_index]];
1085 perm_grid_dev =
_sp_cl_upload(devid, perm_grid,
sizeof(
int) * n_unknowns);
1088 if(!perm_grid_dev || !edge_weights_dev || !rhs_dev)
1095 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1105 if(cl_err != CL_SUCCESS)
goto out;
1108 sizeof(
float) * (
size_t)n_unknowns * 8, CL_TRUE);
1109 if(cl_err != CL_SUCCESS)
goto out;
1113 static const int neighbour_dy[8] = { 0, 0, -1, 1, -1, 1, -1, 1 };
1114 static const int neighbour_dx[8] = { -1, 1, 0, 0, -1, 1, 1, -1 };
1116 for(
int pass = 0; pass < 2 && success; pass++)
1121 for(
int perm_index = 0; perm_index < n_unknowns; perm_index++)
1123 const int c = matrix_col_ptr[perm_index];
1124 matrix_col_ptr[perm_index] = total;
1127 matrix_col_ptr[n_unknowns] = total;
1130 if(!matrix_row_index || !matrix_values) success = 0;
1133 for(
int perm_index = 0; perm_index < n_unknowns && success; perm_index++)
1135 const int origin_grid = perm_grid[perm_index];
1136 const int origin_y = origin_grid / region_w, origin_x = origin_grid - origin_y * region_w;
1138 int n_col_entries = 0;
1140 for(
int edge = 0; edge < 8; edge++)
1142 const float weight_value = edge_weights[(size_t)perm_index * 8 + edge];
1145 if(!(weight_value > 0.f))
continue;
1146 const int neighbour_x = origin_x + neighbour_dx[edge], neighbour_y = origin_y + neighbour_dy[edge];
1147 if(neighbour_x < 0 || neighbour_y < 0 || neighbour_x >= region_w || neighbour_y >= region_h)
1149 diag += weight_value;
1150 const size_t j = (size_t)neighbour_y * region_w + neighbour_x;
1151 if(grid_to_unknown[j] >= 0)
1153 const int target_row = inverse_perm[grid_to_unknown[j]];
1154 if(target_row < perm_index)
1158 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = target_row;
1159 matrix_values[matrix_col_ptr[perm_index] + n_col_entries] = -(
double)weight_value;
1167 matrix_row_index[matrix_col_ptr[perm_index] + n_col_entries] = perm_index;
1168 matrix_values[matrix_col_ptr[perm_index] + n_col_entries] = diag;
1171 if(pass == 0) matrix_col_ptr[perm_index] = n_col_entries;
1189 for(
int c = 0;
c < 3;
c++)
1193 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1204 if(cl_err != CL_SUCCESS)
goto out;
1213 size_t size_1d[3] = {
ROUNDUP(n_unknowns, 64), 1, 1 };
1220 if(cl_err != CL_SUCCESS)
goto out;
1237 if(!grad_y || !dobs3 || !dhole3 || !diffuse_a || !diffuse_b || !ppart || !aflags)
1241 if(cl_err == CL_SUCCESS)
1249 if(cl_err == CL_SUCCESS)
1256 if(cl_err == CL_SUCCESS)
1258 const int local_size = 64, n_groups = 256;
1260 size_t sizes[3] = { (size_t)n_groups * local_size, 1, 1 };
1261 size_t local[3] = { local_size, 1, 1 };
1270 if(cl_err == CL_SUCCESS)
1272 float partial_sums[256];
1274 if(cl_err == CL_SUCCESS)
1277 for(
int group_index = 0; group_index < 256; group_index++) gsum += (
double)partial_sums[group_index];
1278 const float gnorm = fmaxf((
float)(gsum / (
double)region_pixels), 1e-9f);
1292 if(cl_err == CL_SUCCESS)
1308 int active[3] = { 0, 0, 0 };
1309 if(cl_err == CL_SUCCESS)
1312 if(cl_err == CL_SUCCESS)
1323 if(cl_err == CL_SUCCESS)
1328 = {
ROUNDUPDWD(box_x_hi - box_x_lo + 1, devid),
ROUNDUPDHT(box_y_hi - box_y_lo + 1, devid), 1 };
1329 for(
int c = 0;
c < 3 && cl_err == CL_SUCCESS;
c++)
1331 if(!active[c])
continue;
1341 if(cl_err == CL_SUCCESS)
1352 if(cl_err == CL_SUCCESS)
1354 sizeof(
float) * region_pixels);
1356 cl_mem current_buf = diffuse_a, other_buf = diffuse_b;
1357 for(
int iter = 0; iter < 60 && cl_err == CL_SUCCESS; iter++)
1375 cl_mem swap_buf = current_buf;
1376 current_buf = other_buf;
1377 other_buf = swap_buf;
1379 if(cl_err == CL_SUCCESS)
1398 if(cl_err != CL_SUCCESS)
goto out;
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 dt_dev_pixelpipe_t *pipe)
__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)
__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)
__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
#define dt_pixelpipe_cache_alloc_align(size, pipe)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
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
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
static _sp_chol_cl_kernels_t _hl_sp_chol_kernels(void *gd_void)
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 _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 dt_dev_pixelpipe_t *pipe)
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 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
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_aniso_weights
typedef double((*spd)(unsigned long int wavelength, double TempK))