35#include <glib/gstdio.h>
44 if(done || !getenv(
"HL_SPCL_TEST"))
return;
48 uint8_t *hole = calloc((
size_t)grid * grid, 1);
49 int *grid_index = malloc(
sizeof(
int) * grid * grid);
51 for(
int y = 0; y < grid; y++)
52 for(
int x = 0;
x < grid;
x++)
54 const int delta_x =
x - grid / 2;
55 const int delta_y = y - grid / 2;
56 hole[y * grid +
x] = (delta_x * delta_x + delta_y * delta_y < 34 * 34);
57 grid_index[y * grid +
x] = hole[y * grid +
x] ?
dimension++ : -1;
60 static const int stencil_dy[13] = { 0, -1, 1, 0, 0, -1, -1, 1, 1, -2, 2, 0, 0 };
61 static const int stencil_dx[13] = { 0, 0, 0, -1, 1, -1, 1, -1, 1, 0, 0, -2, 2 };
62 static const double stencil_coeff[13] = { 20., -8., -8., -8., -8., 2., 2., 2., 2., 1., 1., 1., 1. };
64 int *matrix_col_ptr = calloc(
dimension + 1,
sizeof(
int));
65 int *matrix_row_index = malloc(
sizeof(
int) * (
size_t)
dimension * 13);
66 double *matrix_values = malloc(
sizeof(
double) * (
size_t)
dimension * 13);
67 double *rhs = malloc(
sizeof(
double) *
dimension);
68 double *solution_cpu = malloc(
sizeof(
double) *
dimension);
70 for(
int y = 0; y < grid; y++)
71 for(
int x = 0;
x < grid;
x++)
73 const int j = grid_index[y * grid +
x];
75 rhs[j] = 0.5 + 0.001 * (
double)((
x * 131 + y * 17) % 97);
76 matrix_col_ptr[j] = n_nonzero;
77 for(
int tap_index = 0; tap_index < 13; tap_index++)
79 const int neighbour_y = CLAMP(y + stencil_dy[tap_index], 0, grid - 1);
80 const int neighbour_x = CLAMP(
x + stencil_dx[tap_index], 0, grid - 1);
81 const int neighbour_index = grid_index[neighbour_y * grid + neighbour_x];
82 if(neighbour_index < 0 || neighbour_index > j)
continue;
83 int scan = matrix_col_ptr[j];
84 for(; scan < n_nonzero; scan++)
85 if(matrix_row_index[scan] == neighbour_index)
87 matrix_values[scan] += stencil_coeff[tap_index];
92 matrix_row_index[n_nonzero] = neighbour_index;
93 matrix_values[n_nonzero] = stencil_coeff[tap_index];
101 memcpy(solution_cpu, rhs,
sizeof(
double) *
dimension);
107 matrix_row_index, matrix_values);
108 double max_rel_diff = -1.0;
109 if(factor_cpu && factor_gpu)
114 double *solution_gpu = malloc(
sizeof(
double) *
dimension);
121 const double rel_diff = fabs(solution_gpu[
i] - solution_cpu[
i]) / fmax(fabs(solution_cpu[
i]), 1e-12);
122 if(rel_diff > max_rel_diff) max_rel_diff = rel_diff;
129 fprintf(stderr,
"[hl sparse-cl selftest] n=%d nnz=%d levels=%d/%d cpu=%s gpu=%s max rel diff=%.3e\n",
dimension,
131 factor_gpu ? factor_gpu->
nlev_bwd : -1, factor_cpu ?
"ok" :
"FAIL", factor_gpu ?
"ok" :
"FAIL",
138 free(matrix_col_ptr);
139 free(matrix_row_index);
148 if(done || !getenv(
"HL_BLURCL_TEST") || devid < 0)
return;
151 const int region_w = 731;
152 const int region_h = 517;
153 const size_t region_pixels = (size_t)region_w * region_h;
159 for(
size_t i = 0;
i < region_pixels;
i++)
160 for(
int c = 0; c < 4; c++)
161 input[
i * 4 + c] = 0.5f + 0.5f * sinf(0.013f * (
float)(
i % region_w) + 0.007f * (
float)(
i / region_w) + c);
163 static const float test_sigmas[3] = { 4.f, 16.f, 64.f };
164 for(
int sigma_index = 0; sigma_index < 3; sigma_index++)
166 const float sigma = test_sigmas[sigma_index];
171 float max_diff = -1.f;
172 if(in_device && out_device
180 for(
size_t i = 0;
i < region_pixels * 4;
i++)
181 max_diff = fmaxf(max_diff, fabsf(output_gpu[
i] - output_cpu[
i]));
185 fprintf(stderr,
"[hl blur-cl selftest] %dx%d sigma=%.0f max|gpu-cpu|=%.3e\n", region_w, region_h,
sigma,
198 if(done || !getenv(
"HL_FILLCL_TEST") || devid < 0)
return;
201 const int region_w = 613;
202 const int region_h = 419;
203 const size_t region_pixels = (size_t)region_w * region_h;
211 for(
int y = 0; y < region_h; y++)
212 for(
int x = 0;
x < region_w;
x++)
214 const size_t i = (size_t)y * region_w +
x;
215 const int delta_x =
x - region_w / 2;
216 const int delta_y = y - (region_h - 30);
217 hole[
i] = (delta_x * delta_x + delta_y * delta_y < 120 * 120);
218 anchor[
i] = !hole[
i];
219 val_cpu[
i] = hole[
i] ? 0.f : 0.3f + 0.4f * sinf(0.02f *
x) * cosf(0.017f * y);
221 memcpy(val_gpu, val_cpu,
sizeof(
float) * region_pixels);
227 float max_diff = -1.f;
232 &&
_cf_harmonic_fill_cl(devid, gd_void, dval, danc, region_w, region_h, 2, 0, NULL) == CL_SUCCESS
237 for(
size_t i = 0;
i < region_pixels;
i++)
238 if(hole[
i]) max_diff = fmaxf(max_diff, fabsf(val_gpu[
i] - val_cpu[
i]));
242 fprintf(stderr,
"[hl fill-cl selftest] %dx%d hole=disc r120 max|gpu-cpu|=%.3e\n", region_w, region_h, max_diff);
250 for(
int y = 0; y < region_h; y++)
251 for(
int x = 0;
x < region_w;
x++)
253 const size_t i = (size_t)y * region_w +
x;
254 const int dark_bar = (
x > region_w / 2 - 12 &&
x < region_w / 2 + 12);
255 steer[
i] = dark_bar ? 0.05f : (0.4f + 0.5f * (float)y / region_h);
256 val_cpu[
i] = hole[
i] ? 0.f : 0.3f + 0.4f * sinf(0.02f *
x) * cosf(0.017f * y);
258 memcpy(val_gpu, val_cpu,
sizeof(
float) * region_pixels);
265 float max_diff_aniso = -1.f;
266 if(aniso_val_device && aniso_anchor_device && aniso_steer_device
275 &&
_cf_harmonic_fill_cl(devid, gd_void, aniso_val_device, aniso_anchor_device, region_w, region_h, 2, 0,
282 max_diff_aniso = 0.f;
283 for(
size_t i = 0;
i < region_pixels;
i++)
284 if(hole[
i]) max_diff_aniso = fmaxf(max_diff_aniso, fabsf(val_gpu[
i] - val_cpu[
i]));
289 fprintf(stderr,
"[hl fill-cl ANISO selftest] %dx%d adaptive-tensor max|gpu-cpu|=%.3e\n", region_w, region_h,
305 if(done || !getenv(
"HL_CFCL_TEST") || devid < 0)
return;
308 const int region_w = 509;
309 const int region_h = 371;
310 const size_t region_pixels = (size_t)region_w * region_h;
311 const float cf_sigma = 24.f;
312 const float cf_fmin = 0.05f;
314 const int guide1 = 0;
315 const int guide2 = 2;
334 for(
int y = 0; y < region_h; y++)
335 for(
int x = 0;
x < region_w;
x++)
337 const size_t i = (size_t)y * region_w +
x;
338 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
339 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
340 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
341 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
342 estimate[
i * 4 + 3] = 0.f;
343 const int delta_x =
x - region_w / 2;
344 const int delta_y = y - region_h / 2;
345 const int clip = (delta_x * delta_x + delta_y * delta_y < 90 * 90);
346 valid[
i * 4 + 0] = 1.f;
347 valid[
i * 4 + 1] = clip ? 0.f : 1.f;
348 valid[
i * 4 + 2] = 1.f;
349 valid[
i * 4 + 3] = clip ? 0.f : 1.f;
350 for(
int k = 0;
k < 4;
k++) model_quality[
i * 4 +
k] = 0.f;
351 if(clip) estimate[
i * 4 + 1] = 0.55f;
353 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
355 double lum_accum = 0.0;
356 size_t lum_count = 0;
357 for(
size_t i = 0;
i < region_pixels;
i++)
358 if(valid[
i * 4 + 1] < 0.5f)
360 lum_accum += estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
363 const float cf_lref = lum_count ? (float)(lum_accum / (
double)lum_count) : 0.f;
364 const float cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
367 for(
int mode = 0; mode < 3; mode++)
369 for(
size_t i = 0;
i < region_pixels;
i++)
371 const float val_r = estimate[
i * 4 + 0];
372 const float val_g = estimate[
i * 4 + 1];
373 const float val_b = estimate[
i * 4 + 2];
374 const float rgb_sum = val_r + val_g + val_b;
375 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
376 const int all_valid = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f);
377 const float weight = all_valid ? bright_weight : 0.f;
381 input[
i * 4 + 1] =
weight * val_r;
382 input[
i * 4 + 2] =
weight * val_g;
383 input[
i * 4 + 3] =
weight * val_b;
387 input[
i * 4 + 0] =
weight * val_r * val_r;
388 input[
i * 4 + 1] =
weight * val_g * val_g;
389 input[
i * 4 + 2] =
weight * val_b * val_b;
390 input[
i * 4 + 3] =
weight * val_r * val_g;
394 input[
i * 4 + 0] =
weight * val_r * val_b;
395 input[
i * 4 + 1] =
weight * val_g * val_b;
396 input[
i * 4 + 2] = all_valid ? 1.f : 0.f;
397 input[
i * 4 + 3] = 0.f;
400 _region_blur(input, (mode == 0) ? moment1 : (mode == 1) ? moment2 : moment3, region_w, region_h, cf_sigma);
403 for(
size_t i = 0;
i < region_pixels;
i++)
405 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
406 const float inv_det = 1.f / norm;
408 = { moment1[
i * 4 + 1] * inv_det, moment1[
i * 4 + 2] * inv_det, moment1[
i * 4 + 3] * inv_det };
409 const float second_moment[3]
410 = { moment2[
i * 4 + 0] * inv_det, moment2[
i * 4 + 1] * inv_det, moment2[
i * 4 + 2] * inv_det };
411 const float cross_rg = moment2[
i * 4 + 3] * inv_det;
412 const float cross_rb = moment3[
i * 4 + 0] * inv_det;
413 const float cross_gb = moment3[
i * 4 + 1] * inv_det;
414#define OFF2(chan_a, chan_b) \
415 (((chan_a) + (chan_b)) == 1 ? cross_rg : (((chan_a) + (chan_b)) == 2 ? cross_rb : cross_gb))
416 const float mean1 = mean[guide1];
417 const float mean2 = mean[guide2];
418 const float mean_target = mean[c];
419 const float var11 = fmaxf(second_moment[guide1] - mean1 * mean1, 0.f);
420 const float var22 = fmaxf(second_moment[guide2] - mean2 * mean2, 0.f);
421 const float var12 =
OFF2(guide1, guide2) - mean1 * mean2;
422 const float cov_tg1 =
OFF2(c, guide1) - mean_target * mean1;
423 const float cov_tg2 =
OFF2(c, guide2) - mean_target * mean2;
424 const float var_target = fmaxf(second_moment[c] - mean_target * mean_target, 0.f);
426 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
427 const float determinant = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
428 const float slope_a = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
429 const float slope_b = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
430 const float r_sq = CLAMP((slope_a * cov_tg1 + slope_b * cov_tg2) / (var_target + 1e-12f), 0.f, 1.f);
431 coeff_field[
i * 4 + 0] = slope_a;
432 coeff_field[
i * 4 + 1] = slope_b;
433 coeff_field[
i * 4 + 2] = mean_target - slope_a * mean1 - slope_b * mean2;
434 coeff_field[
i * 4 + 3] = r_sq;
435 const int mass_ok = (moment3[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment3[
i * 4 + 2]);
436 const int valid_ok = (valid[
i * 4 + c] >= 0.5f);
437 anchor[
i] = (mass_ok && valid_ok && r_sq > 0.25f && fabsf(slope_a) < 64.f && fabsf(slope_b) < 64.f);
438 border[
i] = (mass_ok && valid_ok);
445 for(
size_t i = 0;
i < region_pixels;
i++)
447 hole[
i] = !anchor[
i];
448 hole2[
i] = !border[
i];
450 const int base_downsample = (int)(cf_sigma / 4.f);
451 for(
int k = 0;
k < 4;
k++)
453 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = coeff_field[
i * 4 +
k];
454 _cf_harmonic_fill(plane, (
k == 3) ? hole2 : hole, region_w, region_h, base_downsample, NULL, pipe);
455 for(
size_t i = 0;
i < region_pixels;
i++) coeff_field[
i * 4 +
k] = plane[
i];
461 for(
size_t i = 0;
i < region_pixels;
i++)
462 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
463 estimate[
i * 4 + c] = coeff_field[
i * 4 + 0] * estimate[
i * 4 + guide1]
464 + coeff_field[
i * 4 + 1] * estimate[
i * 4 + guide2] + coeff_field[
i * 4 + 2];
473 float max_diff = -1.f;
475 for(
size_t i = 0;
i < region_pixels;
i++)
476 luminance[
i] = estimate_gpu[
i * 4 + 0] + estimate_gpu[
i * 4 + 1] + estimate_gpu[
i * 4 + 2];
482 cl_mem moments_device[3];
483 moments_device[0] = moment0_device;
484 moments_device[1] = moment1_device;
485 moments_device[2] = moment2_device;
486 int moms_ok = (packed_device && moment0_device && moment1_device && moment2_device);
487 if(moms_ok && dest && dvld && dbsc && dlsb &&
luminance
496 cl_int test_cl_err = CL_SUCCESS;
497 for(
int mode = 0; mode < 3 && test_cl_err == CL_SUCCESS; mode++)
508 const float zero_shift = 0.f;
513 if(test_cl_err == CL_SUCCESS)
514 test_cl_err =
_region_blur_cl(devid, packed_device, moments_device[mode], region_w, region_h, cf_sigma);
516 moms_ok = (test_cl_err == CL_SUCCESS);
520 const float zero_means[3] = { 0.f, 0.f, 0.f };
525 &&
_cf_joint_stage_cl(devid, gd_void, dest, dvld, dbsc, moment0_device, moment1_device, moment2_device,
526 NULL, zero_means, region_w, region_h, cf_sigma, cf_fmin, c, guide1, guide2)
533 for(
size_t i = 0;
i < region_pixels;
i++)
534 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
535 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
546 fprintf(stderr,
"[hl cf-joint-cl selftest] %dx%d G-disc r90 max|gpu-cpu|=%.3e\n", region_w, region_h, max_diff);
567 if(done || !getenv(
"HL_CFCL_TEST") || devid < 0)
return;
570 const int region_w = 509;
571 const int region_h = 371;
572 const size_t region_pixels = (size_t)region_w * region_h;
573 const float cf_sigma = 24.f;
574 const float cf_fmin = 0.05f;
597 for(
int y = 0; y < region_h; y++)
598 for(
int x = 0;
x < region_w;
x++)
600 const size_t i = (size_t)y * region_w +
x;
601 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
602 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
603 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
604 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
605 estimate[
i * 4 + 3] = 0.f;
606 const int delta_x =
x - region_w / 2;
607 const int delta_y = y - region_h / 2;
608 const int gclip = (delta_x * delta_x + delta_y * delta_y < 100 * 100);
609 const int rclip = (delta_x * delta_x + delta_y * delta_y < 45 * 45);
610 valid[
i * 4 + 0] = rclip ? 0.f : 1.f;
611 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
612 valid[
i * 4 + 2] = 1.f;
613 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
614 for(
int k = 0;
k < 4;
k++) model_quality[
i * 4 +
k] = 0.f;
615 if(gclip) estimate[
i * 4 + 1] = 0.58f;
616 if(rclip) estimate[
i * 4 + 0] = 0.47f;
618 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
620 double lum_accum = 0.0;
621 size_t lum_count = 0;
622 for(
size_t i = 0;
i < region_pixels;
i++)
623 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f)
625 lum_accum += estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
628 const float cf_lref = lum_count ? (float)(lum_accum / (
double)lum_count) : 0.f;
629 const float cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
630 const int base_downsample = (int)(cf_sigma / 4.f);
635 for(
size_t i = 0;
i < region_pixels;
i++)
636 luminance[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
642 const int guide1 = 0;
643 const int guide2 = 2;
644 for(
int mode = 0; mode < 3; mode++)
646 for(
size_t i = 0;
i < region_pixels;
i++)
648 const float val_r = estimate[
i * 4 + 0];
649 const float val_g = estimate[
i * 4 + 1];
650 const float val_b = estimate[
i * 4 + 2];
652 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
653 const int all_valid = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f);
654 const float weight = all_valid ? bright_weight : 0.f;
658 input[
i * 4 + 1] =
weight * val_r;
659 input[
i * 4 + 2] =
weight * val_g;
660 input[
i * 4 + 3] =
weight * val_b;
664 input[
i * 4 + 0] =
weight * val_r * val_r;
665 input[
i * 4 + 1] =
weight * val_g * val_g;
666 input[
i * 4 + 2] =
weight * val_b * val_b;
667 input[
i * 4 + 3] =
weight * val_r * val_g;
671 input[
i * 4 + 0] =
weight * val_r * val_b;
672 input[
i * 4 + 1] =
weight * val_g * val_b;
673 input[
i * 4 + 2] = all_valid ? 1.f : 0.f;
674 input[
i * 4 + 3] = 0.f;
677 _region_blur(input, (mode == 0) ? moment1 : (mode == 1) ? moment2 : moment3, region_w, region_h, cf_sigma);
679 for(
size_t i = 0;
i < region_pixels;
i++)
681 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
682 const float inv_det = 1.f / norm;
684 = { moment1[
i * 4 + 1] * inv_det, moment1[
i * 4 + 2] * inv_det, moment1[
i * 4 + 3] * inv_det };
685 const float second_moment[3]
686 = { moment2[
i * 4 + 0] * inv_det, moment2[
i * 4 + 1] * inv_det, moment2[
i * 4 + 2] * inv_det };
687 const float cross_rg = moment2[
i * 4 + 3] * inv_det;
688 const float cross_rb = moment3[
i * 4 + 0] * inv_det;
689 const float cross_gb = moment3[
i * 4 + 1] * inv_det;
690 const float mean1 = mean[guide1];
691 const float mean2 = mean[guide2];
692 const float mean_target = mean[c];
693 const float var11 = fmaxf(second_moment[guide1] - mean1 * mean1, 0.f);
694 const float var22 = fmaxf(second_moment[guide2] - mean2 * mean2, 0.f);
695 const float var12 = cross_rb - mean1 * mean2;
696 const float cov_tg1 = cross_rg - mean_target * mean1;
697 const float cov_tg2 = cross_gb - mean_target * mean2;
698 const float var_target = fmaxf(second_moment[c] - mean_target * mean_target, 0.f);
699 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
700 const float determinant = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
701 const float slope_a = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
702 const float slope_b = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
703 const float r_sq = CLAMP((slope_a * cov_tg1 + slope_b * cov_tg2) / (var_target + 1e-12f), 0.f, 1.f);
704 coeff_field_green[
i * 4 + 0] = slope_a;
705 coeff_field_green[
i * 4 + 1] = slope_b;
706 coeff_field_green[
i * 4 + 2] = mean_target - slope_a * mean1 - slope_b * mean2;
707 coeff_field_green[
i * 4 + 3] = r_sq;
708 const int mass_ok = (moment3[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment3[
i * 4 + 2]);
709 const int valid_ok = (valid[
i * 4 + c] >= 0.5f);
710 anchor[
i] = (mass_ok && valid_ok && r_sq > 0.25f && fabsf(slope_a) < 64.f && fabsf(slope_b) < 64.f);
711 border[
i] = (mass_ok && valid_ok);
713 for(
size_t i = 0;
i < region_pixels;
i++)
715 hole[
i] = !anchor[
i];
716 hole_border[
i] = !border[
i];
718 for(
int k = 0;
k < 4;
k++)
720 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = coeff_field_green[
i * 4 +
k];
721 _cf_harmonic_fill(plane, (
k == 3) ? hole_border : hole, region_w, region_h, base_downsample, NULL, pipe);
722 for(
size_t i = 0;
i < region_pixels;
i++) coeff_field_green[
i * 4 +
k] = plane[
i];
727 const int pair_a[2] = { 0, 1 };
728 const int pair_b[2] = { 2, 2 };
731 const int chan_a = pair_a[
pair];
732 const int chan_b = pair_b[
pair];
733 const int target_chan = chan_a;
734 const int guide_chan = chan_b;
735 const int other_chan = 3 - chan_a - chan_b;
736 for(
int mode = 0; mode < 2; mode++)
738 for(
size_t i = 0;
i < region_pixels;
i++)
740 const float value_a = estimate[
i * 4 + chan_a];
741 const float value_b = estimate[
i * 4 + chan_b];
743 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
744 const int pair_valid = (valid[
i * 4 + chan_a] >= 0.5f && valid[
i * 4 + chan_b] >= 0.5f);
745 const float weight = pair_valid ? bright_weight : 0.f;
749 input[
i * 4 + 1] =
weight * value_a;
750 input[
i * 4 + 2] =
weight * value_b;
751 input[
i * 4 + 3] =
weight * value_a * value_a;
755 input[
i * 4 + 0] =
weight * value_b * value_b;
756 input[
i * 4 + 1] =
weight * value_a * value_b;
757 input[
i * 4 + 2] = pair_valid ? 1.f : 0.f;
758 input[
i * 4 + 3] = 0.f;
761 _region_blur(input, mode ? moment2 : moment1, region_w, region_h, cf_sigma);
763 for(
size_t i = 0;
i < region_pixels;
i++)
765 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
766 const float inv_det = 1.f / norm;
767 const float mean_target = moment1[
i * 4 + 1] * inv_det;
768 const float mean_guide = moment1[
i * 4 + 2] * inv_det;
769 const float var_guide = fmaxf(moment2[
i * 4 + 0] * inv_det - mean_guide * mean_guide, 0.f);
770 const float var_t = fmaxf(moment1[
i * 4 + 3] * inv_det - mean_target * mean_target, 0.f);
771 const float covariance = moment2[
i * 4 + 1] * inv_det - mean_target * mean_guide;
772 const float slope_a = covariance / (var_guide * (1.f + 1e-3f) + 1e-12f);
773 const float r_sq = CLAMP(covariance * covariance / (var_guide * var_t + 1e-18f), 0.f, 1.f);
774 moment3[
i * 4 + 0] = slope_a;
775 moment3[
i * 4 + 1] = mean_target - slope_a * mean_guide;
776 moment3[
i * 4 + 2] = r_sq;
777 const int mass_ok = (moment2[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment2[
i * 4 + 2]);
778 const int valid_ok = (valid[
i * 4 + target_chan] >= 0.5f);
779 anchor[
i] = (mass_ok && valid_ok && r_sq > 0.25f && fabsf(slope_a) < 64.f);
780 border[
i] = (mass_ok && valid_ok);
782 for(
size_t i = 0;
i < region_pixels;
i++)
784 hole[
i] = !anchor[
i];
785 hole_border[
i] = !border[
i];
787 for(
int k = 0;
k < 3;
k++)
789 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = moment3[
i * 4 +
k];
790 _cf_harmonic_fill(plane, (
k == 2) ? hole_border : hole, region_w, region_h, base_downsample, NULL, pipe);
791 for(
size_t i = 0;
i < region_pixels;
i++) moment3[
i * 4 +
k] = plane[
i];
793 for(
size_t i = 0;
i < region_pixels;
i++)
794 if(valid[
i * 4 + target_chan] < 0.5f && valid[
i * 4 + guide_chan] >= 0.5f && valid[
i * 4 + other_chan] < 0.5f)
796 estimate[
i * 4 + target_chan] = moment3[
i * 4 + 0] * estimate[
i * 4 + guide_chan] + moment3[
i * 4 + 1];
797 model_quality[
i * 4 + target_chan] = CLAMP(moment3[
i * 4 + 2], 0.f, 1.f);
803 const int guide1 = 0;
804 const int guide2 = 2;
805 for(
size_t i = 0;
i < region_pixels;
i++)
808 = (valid[
i * 4 + cdeep] < 0.5f && (valid[
i * 4 + guide1] < 0.5f || valid[
i * 4 + guide2] < 0.5f));
809 input[
i * 4 + 0] = multi_clip ? 1.f : 0.f;
810 input[
i * 4 + 1] = input[
i * 4 + 2] = input[
i * 4 + 3] = 0.f;
812 _region_blur(input, moment1, region_w, region_h, cf_sigma);
813 for(
size_t i = 0;
i < region_pixels;
i++)
815 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
816 if(valid[
i * 4 + cdeep] >= 0.5f || !anyvalid)
continue;
817 const float joint = coeff_field_green[
i * 4 + 0] * estimate[
i * 4 + guide1]
818 + coeff_field_green[
i * 4 + 1] * estimate[
i * 4 + guide2] + coeff_field_green[
i * 4 + 2];
819 const int has_pair = (valid[
i * 4 + guide1] < 0.5f || valid[
i * 4 + guide2] < 0.5f);
820 const float mass = CLAMP(moment1[
i * 4 + 0], 0.f, 1.f);
821 const float smooth_t = CLAMP((mass - 0.7f) / 0.25f, 0.f, 1.f);
822 const float weight_depth = has_pair ? smooth_t * smooth_t * (3.f - 2.f * smooth_t) : 0.f;
823 estimate[
i * 4 + cdeep] = weight_depth * estimate[
i * 4 + cdeep] + (1.f - weight_depth) * joint;
824 model_quality[
i * 4 + cdeep] = weight_depth * model_quality[
i * 4 + cdeep]
825 + (1.f - weight_depth) * CLAMP(coeff_field_green[
i * 4 + 3], 0.f, 1.f);
834 float max_diff = -1.f;
835 float max_bsc_diff = -1.f;
836 if(dest && dvld && dbsc
846 memset(zero, 0,
sizeof(
float) * region_pixels * 4);
851 const float zero_means[3] = { 0.f, 0.f, 0.f };
855 &&
_cf_stage_cl(devid, gd_void, dest, dvld, dbsc, dlsb, NULL, zero_means, NULL, region_w, region_h,
856 cf_sigma, cf_fmin, cf_binv, cdeep)
863 for(
size_t i = 0;
i < region_pixels;
i++)
864 for(
int c = 0; c < 3; c++)
865 if(valid[
i * 4 + c] < 0.5f)
866 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
874 size_t arg_index = 0;
876 for(
size_t i = 0;
i < region_pixels;
i++)
877 for(
int c = 0; c < 3; c++)
879 const float diff = fabsf(estimate_gpu[
i * 4 + c] - model_quality[
i * 4 + c]);
880 if(diff > max_bsc_diff)
887 if(getenv(
"HL_CFCL_VERBOSE"))
888 fprintf(stderr,
"[hl cf-full bsc argmax] px=(%zu,%zu) c=%d gpu=%f cpu=%f\n", arg_index % region_w,
889 arg_index / region_w, arg_chan, estimate_gpu[arg_index * 4 + arg_chan],
890 model_quality[arg_index * 4 + arg_chan]);
898 fprintf(stderr,
"[hl cf-full-cl selftest] %dx%d G-disc r100 + R-core r45 max|gpu-cpu|=%.3e bsc=%.3e\n",
899 region_w, region_h, max_diff, max_bsc_diff);
923 if(done || !getenv(
"HL_HFCL_TEST") || devid < 0)
return;
926 const int region_w = 509;
927 const int region_h = 371;
928 const size_t region_pixels = (size_t)region_w * region_h;
929 const float cf_sigma = 24.f;
930 const float cf_fmin = 0.05f;
931 const float blur_sigma = fmaxf(cf_sigma / 4.f, 2.f);
932 const int base_downsample = (int)(cf_sigma / 4.f);
954 for(
int y = 0; y < region_h; y++)
955 for(
int x = 0;
x < region_w;
x++)
957 const size_t i = (size_t)y * region_w +
x;
958 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
959 const float texture = 0.05f * sinf(0.9f *
x) * sinf(0.75f * y);
960 estimate[
i * 4 + 0] = 0.9f * base + 0.05f + texture;
961 estimate[
i * 4 + 1] = 1.2f * base + 0.02f + 0.8f * texture;
962 estimate[
i * 4 + 2] = 0.7f * base + 0.08f + 1.1f * texture;
963 estimate[
i * 4 + 3] = 0.f;
964 const int delta_x =
x - region_w / 2;
965 const int delta_y = y - region_h / 2;
966 const int gclip = (delta_x * delta_x + delta_y * delta_y < 100 * 100);
967 const int rclip = (delta_x * delta_x + delta_y * delta_y < 45 * 45);
968 valid[
i * 4 + 0] = rclip ? 0.f : 1.f;
969 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
970 valid[
i * 4 + 2] = 1.f;
971 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
972 for(
int k = 0;
k < 4;
k++) model_quality[
i * 4 +
k] = gclip ? 0.65f : 0.f;
974 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
976 double lum_accum = 0.0;
977 size_t lum_count = 0;
978 for(
size_t i = 0;
i < region_pixels;
i++)
979 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f)
981 lum_accum += estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
984 const float cf_lref = lum_count ? (float)(lum_accum / (
double)lum_count) : 0.f;
985 const float cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
988 memcpy(input, estimate, region_pixels * 4 *
sizeof(
float));
989 _region_blur(input, lowpass, region_w, region_h, blur_sigma);
990 for(
int mode = 0; mode < 3; mode++)
992 for(
size_t i = 0;
i < region_pixels;
i++)
994 const float detail_r = estimate[
i * 4 + 0] - lowpass[
i * 4 + 0];
995 const float detail_g = estimate[
i * 4 + 1] - lowpass[
i * 4 + 1];
996 const float detail_b = estimate[
i * 4 + 2] - lowpass[
i * 4 + 2];
997 const float rgb_sum = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
998 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
999 const int all_valid = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f);
1000 const float weight = all_valid ? bright_weight : 0.f;
1004 input[
i * 4 + 1] =
weight * detail_r;
1005 input[
i * 4 + 2] =
weight * detail_g;
1006 input[
i * 4 + 3] =
weight * detail_b;
1010 input[
i * 4 + 0] =
weight * detail_r * detail_r;
1011 input[
i * 4 + 1] =
weight * detail_g * detail_g;
1012 input[
i * 4 + 2] =
weight * detail_b * detail_b;
1013 input[
i * 4 + 3] =
weight * detail_r * detail_g;
1017 input[
i * 4 + 0] =
weight * detail_r * detail_b;
1018 input[
i * 4 + 1] =
weight * detail_g * detail_b;
1019 input[
i * 4 + 2] = all_valid ? 1.f : 0.f;
1020 input[
i * 4 + 3] = 0.f;
1023 _region_blur(input, (mode == 0) ? moment1 : (mode == 1) ? moment2 : moment3, region_w, region_h, cf_sigma);
1025 for(
int c = 0; c < 3; c++)
1027 const int guide1 = (c == 0) ? 1 : 0;
1028 const int guide2 = (c == 2) ? 1 : 2;
1029 for(
size_t i = 0;
i < region_pixels;
i++)
1031 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
1032 const float inv_det = 1.f / norm;
1034 = { moment1[
i * 4 + 1] * inv_det, moment1[
i * 4 + 2] * inv_det, moment1[
i * 4 + 3] * inv_det };
1035 const float second_moment[3]
1036 = { moment2[
i * 4 + 0] * inv_det, moment2[
i * 4 + 1] * inv_det, moment2[
i * 4 + 2] * inv_det };
1037 const float cross_rg = moment2[
i * 4 + 3] * inv_det;
1038 const float cross_rb = moment3[
i * 4 + 0] * inv_det;
1039 const float cross_gb = moment3[
i * 4 + 1] * inv_det;
1040#define OFF3(chan_a, chan_b) \
1041 (((chan_a) + (chan_b)) == 1 ? cross_rg : (((chan_a) + (chan_b)) == 2 ? cross_rb : cross_gb))
1042 const float mean1 = mean[guide1];
1043 const float mean2 = mean[guide2];
1044 const float mean_target = mean[c];
1045 const float var11 = fmaxf(second_moment[guide1] - mean1 * mean1, 0.f);
1046 const float var22 = fmaxf(second_moment[guide2] - mean2 * mean2, 0.f);
1047 const float var12 =
OFF3(guide1, guide2) - mean1 * mean2;
1048 const float cov_tg1 =
OFF3(c, guide1) - mean_target * mean1;
1049 const float cov_tg2 =
OFF3(c, guide2) - mean_target * mean2;
1050 const float var_target = fmaxf(second_moment[c] - mean_target * mean_target, 0.f);
1052 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
1053 const float determinant = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
1054 const float slope_a = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
1055 const float slope_b = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
1056 const float r_sq = CLAMP((slope_a * cov_tg1 + slope_b * cov_tg2) / (var_target + 1e-12f), 0.f, 1.f);
1057 gain_ab[
i * 2 + 0] = slope_a * r_sq;
1058 gain_ab[
i * 2 + 1] = slope_b * r_sq;
1059 const int mass_ok = (moment3[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment3[
i * 4 + 2]);
1060 anchor[
i] = (mass_ok && valid[
i * 4 + c] >= 0.5f && fabsf(gain_ab[
i * 2 + 0]) < 64.f
1061 && fabsf(gain_ab[
i * 2 + 1]) < 64.f);
1063 for(
size_t i = 0;
i < region_pixels;
i++) hole[
i] = !anchor[
i];
1064 for(
int k = 0;
k < 2;
k++)
1066 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = gain_ab[
i * 2 +
k];
1067 _cf_harmonic_fill(plane, hole, region_w, region_h, base_downsample, NULL, pipe);
1068 for(
size_t i = 0;
i < region_pixels;
i++) gain_ab[
i * 2 +
k] = plane[
i];
1070 for(
size_t i = 0;
i < region_pixels;
i++)
1072 const float high_guide = gain_ab[
i * 2 + 0] * (estimate[
i * 4 + guide1] - lowpass[
i * 4 + guide1])
1073 + gain_ab[
i * 2 + 1] * (estimate[
i * 4 + guide2] - lowpass[
i * 4 + guide2]);
1074 const float high_damped
1075 = CLAMP(model_quality[
i * 4 + c], 0.f, 1.f) * (estimate[
i * 4 + c] - lowpass[
i * 4 + c]);
1076 input[
i * 4 + 0] = fabsf(high_guide);
1077 input[
i * 4 + 1] = fabsf(high_damped);
1078 input[
i * 4 + 2] = 0.f;
1079 input[
i * 4 + 3] = 0.f;
1081 _region_blur(input, energy, region_w, region_h, blur_sigma);
1082 for(
size_t i = 0;
i < region_pixels;
i++)
1083 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
1085 const float high_guide = gain_ab[
i * 2 + 0] * (estimate[
i * 4 + guide1] - lowpass[
i * 4 + guide1])
1086 + gain_ab[
i * 2 + 1] * (estimate[
i * 4 + guide2] - lowpass[
i * 4 + guide2]);
1087 const float high_damped
1088 = CLAMP(model_quality[
i * 4 + c], 0.f, 1.f) * (estimate[
i * 4 + c] - lowpass[
i * 4 + c]);
1089 const float weight_energy
1090 = energy[
i * 4 + 1] * energy[
i * 4 + 1]
1091 / fmaxf(energy[
i * 4 + 1] * energy[
i * 4 + 1] + energy[
i * 4 + 0] * energy[
i * 4 + 0], 1e-18f);
1093 = lowpass[
i * 4 + c] + weight_energy * high_guide + (1.f - weight_energy) * high_damped;
1096 for(
size_t i = 0;
i < region_pixels;
i++)
1098 const int n_valid = (valid[
i * 4 + 0] >= 0.5f) + (valid[
i * 4 + 1] >= 0.5f) + (valid[
i * 4 + 2] >= 0.5f);
1099 if(n_valid != 1)
continue;
1100 for(
int c = 0; c < 3; c++)
1101 if(valid[
i * 4 + c] < 0.5f)
1103 const float weight_hf = CLAMP(model_quality[
i * 4 + c], 0.f, 1.f);
1104 estimate[
i * 4 + c] = lowpass[
i * 4 + c] + weight_hf * (estimate[
i * 4 + c] - lowpass[
i * 4 + c]);
1115 float max_diff = -1.f;
1117 for(
size_t i = 0;
i < region_pixels;
i++)
1118 luminance[
i] = estimate_gpu[
i * 4 + 0] + estimate_gpu[
i * 4 + 1] + estimate_gpu[
i * 4 + 2];
1119 if(dest && dvld && dbsc && dlsb &&
luminance
1129 &&
_hf_stage_cl(devid, gd_void, dest, dvld, dbsc, dlsb, NULL, NULL, region_w, region_h, cf_sigma, cf_fmin,
1137 for(
size_t i = 0;
i < region_pixels;
i++)
1138 for(
int c = 0; c < 3; c++)
1139 if(valid[
i * 4 + c] < 0.5f)
1140 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1147 fprintf(stderr,
"[hl hf-cl selftest] %dx%d two-disc textured max|gpu-cpu|=%.3e\n", region_w, region_h,
1170 static int done = 0;
1171 if(done || !getenv(
"HL_DOMECL_TEST") || devid < 0)
return;
1177 const char *reg_dump_path = getenv(
"HL_REG_DUMP");
1178 FILE *dump_file = (reg_dump_path && reg_dump_path[0]) ? g_fopen(reg_dump_path,
"rb") : NULL;
1183 int dump_downsample;
1184 if(fread(&dump_w,
sizeof(
int), 1, dump_file) == 1 && fread(&dump_h,
sizeof(
int), 1, dump_file) == 1
1185 && fread(&dump_downsample,
sizeof(
int), 1, dump_file) == 1)
1187 const size_t dump_pixels = (size_t)dump_w * dump_h;
1191 if(dump_cpu && dump_gpu && dump_hole
1192 && fread(dump_cpu,
sizeof(
float), dump_pixels, dump_file) == dump_pixels
1193 && fread(dump_hole, 1, dump_pixels, dump_file) == dump_pixels)
1195 memcpy(dump_gpu, dump_cpu, dump_pixels *
sizeof(
float));
1196 _biharmonic_dome(dump_cpu, dump_hole, dump_w, dump_h, dump_downsample, pipe);
1199 float max_diff = -1.f;
1201 if(val_device && hole_device
1207 && _biharmonic_dome_cl(devid, gd_void, val_device, hole_device, dump_w, dump_h, dump_downsample, pipe)
1214 for(
size_t i = 0;
i < dump_pixels;
i++)
1216 if(isnan(dump_gpu[
i]))
1219 max_diff = fmaxf(max_diff, fabsf(dump_gpu[
i] - dump_cpu[
i]));
1222 fprintf(stderr,
"[hl dome-cl REPLAY] %dx%d ds=%d nan=%zu max|gpu-cpu|=%.3e\n", dump_w, dump_h,
1223 dump_downsample, n_nan, max_diff);
1235 const int region_w = 509;
1236 const int region_h = 371;
1237 const size_t region_pixels = (size_t)region_w * region_h;
1238 const float cf_sigma = 24.f;
1239 const float reg_radius = 100.f;
1240 const float epsilon = 1e-6f;
1257 size_t n_hole_union = 0;
1258 for(
int y = 0; y < region_h; y++)
1259 for(
int x = 0;
x < region_w;
x++)
1261 const size_t i = (size_t)y * region_w +
x;
1262 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
1263 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
1264 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
1265 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
1266 estimate[
i * 4 + 3] = 0.f;
1267 const int delta_x =
x - region_w / 2;
1268 const int delta_y = y - region_h / 2;
1269 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1270 const int gclip = (
dist < 100.f);
1271 const int rclip = (
dist < 45.f);
1272 valid[
i * 4 + 0] = rclip ? 0.f : 1.f;
1273 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
1274 valid[
i * 4 + 2] = 1.f;
1275 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
1276 for(
int k = 0;
k < 4;
k++)
1278 model_quality[
i * 4 +
k] = gclip ? 0.55f : 0.f;
1279 clip0[
i * 4 +
k] = 0.5f;
1281 depth[
i] = fmaxf(100.f -
dist, 0.f);
1282 if(gclip) n_hole_union++;
1284 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
1289 for(
size_t i = 0;
i < region_pixels;
i++)
1290 for(
int c = 0; c < 3; c++)
1291 if(valid[
i * 4 + c] < 0.5f)
1293 const float clip_floor = clip0[
i * 4 + c];
1294 const float diff = estimate[
i * 4 + c] - clip_floor;
1295 const float soft_width = 0.02f * fmaxf(clip_floor, 1e-6f);
1296 estimate[
i * 4 + c] = clip_floor + 0.5f * (diff + sqrtf(diff * diff + soft_width * soft_width));
1298 for(
size_t i = 0;
i < region_pixels;
i++)
1300 luminance[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
1301 hole[
i] = (valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f);
1304 _biharmonic_dome(dome_lum, hole, region_w, region_h, downsample_shared, pipe);
1306 const int cf_base = (int)(CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f);
1310 for(
int c = 0; c < 3; c++)
1312 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = estimate[
i * 4 + c] / fmaxf(
luminance[
i], epsilon);
1314 for(
size_t i = 0;
i < region_pixels;
i++) ratio[
i * 3 + c] = fmaxf(plane[
i], 0.f);
1319 for(
size_t i = 0;
i < region_pixels;
i++)
1321 if(!hole[
i])
continue;
1322 const float chroma_sum = fmaxf(ratio[
i * 3 + 0] + ratio[
i * 3 + 1] + ratio[
i * 3 + 2], epsilon);
1323 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
1324 for(
int c = 0; c < 3; c++)
1325 if(valid[
i * 4 + c] < 0.5f)
1327 const float quality = CLAMP((model_quality[
i * 4 + c] - 0.4f) / 0.45f, 0.f, 1.f);
1328 const float weight_r2 = quality * quality * (3.f - 2.f * quality);
1329 const float depth_t = depth[
i] / (1.5f * cf_sigma);
1330 const float depth_gauss = expf(-depth_t * depth_t);
1331 const float weight_sqrt = sqrtf(CLAMP(1.f - (1.f - weight_r2) * depth_gauss, 0.f, 1.f));
1332 const float weight = weight_sqrt * weight_sqrt;
1333 const float dome = dome_lum[
i] * (ratio[
i * 3 + c] / chroma_sum);
1334 estimate[
i * 4 + c] = anyvalid ? (
weight * estimate[
i * 4 + c] + (1.f -
weight) * dome) : dome;
1337 for(
size_t i = 0;
i < region_pixels;
i++)
1338 for(
int c = 0; c < 3; c++)
1339 if(valid[
i * 4 + c] < 0.5f) estimate[
i * 4 + c] = fmaxf(estimate[
i * 4 + c], clip0[
i * 4 + c]);
1349 const float worth_one = 1.f;
1351 float max_diff = -1.f;
1352 if(dest && dvld && dbsc && dclip && ddep
1364 && _selfdome_stage_cl(devid, gd_void, dest, dvld, dbsc, dclip, ddep, dworth, region_w, region_h, cf_sigma,
1365 reg_radius, downsample_shared, 0.f , pipe)
1372 for(
size_t i = 0;
i < region_pixels;
i++)
1373 for(
int c = 0; c < 3; c++)
1374 if(valid[
i * 4 + c] < 0.5f)
1375 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1383 fprintf(stderr,
"[hl dome-cl selftest] %dx%d two-disc ds=%d max|gpu-cpu|=%.3e\n", region_w, region_h,
1384 downsample_shared, max_diff);
1402 static int done = 0;
1403 if(done || !getenv(
"HL_CORECL_TEST") || devid < 0)
return;
1406 const int region_w = 509;
1407 const int region_h = 371;
1408 const size_t region_pixels = (size_t)region_w * region_h;
1409 const float solid_color = 0.4f;
1410 const float reg_radius = 100.f;
1411 const float epsilon = 1e-6f;
1434 for(
int y = 0; y < region_h; y++)
1435 for(
int x = 0;
x < region_w;
x++)
1437 const size_t i = (size_t)y * region_w +
x;
1438 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
1439 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
1440 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
1441 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
1442 estimate[
i * 4 + 3] = 0.f;
1443 const int delta_x =
x - region_w / 2;
1444 const int delta_y = y - (region_h - 40);
1445 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1446 const int allclip = (
dist < 95.f);
1447 const int gclip = (
dist < 145.f);
1448 valid[
i * 4 + 0] = allclip ? 0.f : 1.f;
1449 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
1450 valid[
i * 4 + 2] = allclip ? 0.f : 1.f;
1451 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
1452 for(
int k = 0;
k < 4;
k++) clip0[
i * 4 +
k] = 0.5f;
1454 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = 0.5f;
1456 estimate[
i * 4 + 1] = 0.55f + 0.002f * (100.f -
dist);
1458 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
1462 for(
size_t i = 0;
i < region_pixels;
i++)
1464 hole[
i] = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
1465 luminance[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
1469 memcpy(dome_lum, chroma_work, region_pixels *
sizeof(
float));
1470 for(
size_t i = 0;
i < region_pixels;
i++)
1471 if(hole[
i]) dome_lum[
i] = fmaxf(dome_lum[
i], clip0[
i * 4 + 0] + clip0[
i * 4 + 1] + clip0[
i * 4 + 2]);
1474 double chroma_accum[3] = { 0.0, 0.0, 0.0 };
1475 double chroma_count = 0.0;
1476 for(
size_t i = 0;
i < region_pixels;
i++)
1478 if(!(valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f))
continue;
1479 const float inv_lum = 1.f / fmaxf(
luminance[
i], epsilon);
1480 chroma_accum[0] += (
double)(estimate[
i * 4 + 0] * inv_lum);
1481 chroma_accum[1] += (
double)(estimate[
i * 4 + 1] * inv_lum);
1482 chroma_accum[2] += (
double)(estimate[
i * 4 + 2] * inv_lum);
1483 chroma_count += 1.0;
1485 if(chroma_count > 0.0)
1486 for(
int c = 0; c < 3; c++) chroma_mean[c] = (
float)(chroma_accum[c] / chroma_count);
1488 const float reaction = solid_color * solid_color * 4.f;
1489 for(
size_t i = 0;
i < region_pixels;
i++) diffusion_buf[
i] = reaction;
1491 int *sp_pgrid = NULL;
1492 int sp_n_unknowns = 0;
1494 region_h, &sp_pgrid, &sp_n_unknowns, pipe);
1500 const int max_iter = CLAMP(2 * 150, 200, 2000);
1501 for(
int c = 0; c < 3; c++)
1503 for(
size_t i = 0;
i < region_pixels;
i++)
1505 chroma_work[
i] = hole[
i] ? chroma_mean[c] : (estimate[
i * 4 + c] / fmaxf(
luminance[
i], epsilon));
1506 target_buf[
i] = chroma_mean[c];
1508 if(sp_factor && sp_rhs)
1509 _sp_pde_solve(sp_factor, sp_pgrid, chroma_work, hole, (reaction > 0.f) ? diffusion_buf : NULL,
1510 (reaction > 0.f) ? target_buf : NULL, NULL, 1, 1.f, region_w, region_h, sp_rhs, scratch1,
1511 scratch2, scratch_sc);
1512 else if(cg_residual && cg_search && cg_matvec)
1514 (reaction > 0.f) ? target_buf : NULL, NULL, 1, 1.f, region_w, region_h, cg_residual,
1515 cg_search, cg_matvec, scratch1, scratch2, max_iter);
1516 for(
size_t i = 0;
i < region_pixels;
i++) chroma[
i * 4 + c] = fmaxf(chroma_work[
i], 0.f);
1518 fprintf(stderr,
"[hl core-cl selftest] CPU path: %s\n", (sp_factor && sp_rhs) ?
"sparse" :
"CG");
1526 for(
size_t i = 0;
i < region_pixels;
i++) chroma_work[
i] = hole[
i] ? 1.f : 0.f;
1527 _knee_blur(chroma_work, weight_feather, region_w, region_h,
1528 fmaxf(4.f, CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f));
1530 for(
size_t i = 0;
i < region_pixels;
i++)
1532 const float feather = CLAMP(weight_feather[
i], 0.f, 1.f);
1533 const float chroma_sum = fmaxf(chroma[
i * 4 + 0] + chroma[
i * 4 + 1] + chroma[
i * 4 + 2], epsilon);
1536 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = dome_lum[
i] * (chroma[
i * 4 + c] / chroma_sum);
1538 else if(feather > 1e-4f)
1540 for(
int c = 0; c < 3; c++)
1541 if(valid[
i * 4 + c] < 0.5f)
1543 = feather * dome_lum[
i] * (chroma[
i * 4 + c] / chroma_sum) + (1.f - feather) * estimate[
i * 4 + c];
1553 float max_diff = -1.f;
1554 if(dest && dvld && dclip
1561 && _joint_core_stage_cl(devid, gd_void, dest, dvld, dclip, region_w, region_h, solid_color, reg_radius, 150, 0.f,
1569 for(
size_t i = 0;
i < region_pixels;
i++)
1570 for(
int c = 0; c < 3; c++)
1571 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1573 fprintf(stderr,
"[hl core-cl selftest] %dx%d all-clip disc + annulus max|gpu-cpu|=%.3e\n", region_w, region_h,
1600 static int done = 0;
1601 if(done || !getenv(
"HL_ANISOCL_TEST") || devid < 0)
return;
1604 const int region_w = 509;
1605 const int region_h = 371;
1606 const size_t region_pixels = (size_t)region_w * region_h;
1607 const float epsilon = 1e-6f;
1621 for(
int y = 0; y < region_h; y++)
1622 for(
int x = 0;
x < region_w;
x++)
1624 const size_t i = (size_t)y * region_w +
x;
1626 const float base = 0.6f + 0.25f * sinf(0.05f *
x + 0.08f * y) + 0.1f * cosf(0.021f * y);
1627 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
1628 estimate[
i * 4 + 1] = 1.1f * base + 0.02f;
1629 estimate[
i * 4 + 2] = 0.8f * base + 0.08f;
1630 estimate[
i * 4 + 3] = 0.f;
1631 const int delta_x =
x - region_w / 2;
1632 const int delta_y = y - region_h / 2;
1633 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1634 const int allclip = (
dist < 55.f);
1635 const int gclip = (
dist < 90.f);
1636 valid[
i * 4 + 0] = allclip ? 0.f : 1.f;
1637 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
1638 valid[
i * 4 + 2] = allclip ? 0.f : 1.f;
1639 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
1640 for(
int k = 0;
k < 4;
k++) clip0[
i * 4 +
k] = 0.5f;
1642 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = 1.6f + 0.1f * c;
1644 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
1648 for(
size_t i = 0;
i < region_pixels;
i++)
1650 const int all_clip = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
1651 for(
int c = 0; c < 4; c++) prev[
i * 4 + c] = all_clip ? valid[
i * 4 + c] : fmaxf(valid[
i * 4 + c], 0.6f);
1653 for(
size_t i = 0;
i < region_pixels;
i++)
1655 const float pixel_lum = fmaxf(estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2], epsilon);
1657 for(
int c = 0; c < 3; c++) chroma[
i * 4 + c] = estimate[
i * 4 + c] / pixel_lum;
1662 fprintf(stderr,
"[hl aniso-cl selftest] CPU div solve failed, aborting\n");
1668 float *
const restrict tensor_xx = planes + 0 * region_pixels;
1669 float *
const restrict tensor_xy = planes + 1 * region_pixels;
1670 float *
const restrict tensor_yy = planes + 2 * region_pixels;
1671 float *
const restrict tensor_scale = planes + 3 * region_pixels;
1677 if(solve_u && obstacle && scratch && hole_flag)
1681 int box_x0 = region_w;
1682 int box_y0 = region_h;
1685 for(
int y = 0; y < region_h; y++)
1686 for(
int x = 0;
x < region_w;
x++)
1688 const size_t i = (size_t)y * region_w +
x;
1689 hole_flag[
i] = (prev[
i * 4 + 0] < 0.5f && prev[
i * 4 + 1] < 0.5f && prev[
i * 4 + 2] < 0.5f);
1692 box_x0 =
MIN(box_x0,
x);
1693 box_x1 =
MAX(box_x1,
x);
1694 box_y0 =
MIN(box_y0, y);
1695 box_y1 =
MAX(box_y1, y);
1700 int active[3] = { 0, 0, 0 };
1701 for(
size_t i = 0;
i < region_pixels;
i++)
1703 if(!hole_flag[
i])
continue;
1704 const float inv_lum = 1.f / fmaxf(
luminance[
i], epsilon);
1705 for(
int c = 0; c < 3; c++) active[c] |= (chroma[
i * 4 + c] <= clip0[
i * 4 + c] * inv_lum * 1.001f);
1708 if(box_x1 >= box_x0)
1709 for(
int c = 0; c < 3; c++)
1711 if(!active[c])
continue;
1712 for(
size_t i = 0;
i < region_pixels;
i++)
1714 solve_u[
i] = chroma[
i * 4 + c];
1715 obstacle[
i] = clip0[
i * 4 + c] / fmaxf(
luminance[
i], epsilon);
1717 _aniso_iterate_obs(solve_u, obstacle, hole_flag, tensor_xx, tensor_xy, tensor_yy, scratch, region_w,
1718 region_h, 60, box_x0, box_y0, box_x1, box_y1, 0.f, 0.f);
1719 for(
size_t i = 0;
i < region_pixels;
i++) chroma[
i * 4 + c] = solve_u[
i];
1728 for(
size_t i = 0;
i < region_pixels;
i++)
1730 const float ratio_sum = fmaxf(chroma[
i * 4 + 0] + chroma[
i * 4 + 1] + chroma[
i * 4 + 2], epsilon);
1731 for(
int c = 0; c < 3; c++)
1732 if(prev[
i * 4 + c] < 0.5f)
1734 const float ratio_c = fmaxf(chroma[
i * 4 + c], 0.f);
1737 const float clip_floor = clip0[
i * 4 + c];
1738 const float diff =
value - clip_floor;
1739 const float soft_width = 0.02f * fmaxf(clip_floor, 1e-6f);
1740 estimate[
i * 4 + c] = clip_floor + 0.5f * (diff + sqrtf(diff * diff + soft_width * soft_width));
1750 float max_diff = -1.f;
1751 if(dest && dvld && dclip
1758 && _aniso_stage_cl(devid, gd_void, dest, dvld, dclip, region_w, region_h, 55.f, 0.f, 0.f, pipe) == CL_SUCCESS
1764 for(
size_t i = 0;
i < region_pixels;
i++)
1765 for(
int c = 0; c < 3; c++)
1766 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1768 fprintf(stderr,
"[hl aniso-cl selftest] %dx%d all-clip disc textured max|gpu-cpu|=%.3e\n", region_w, region_h,
1788 static int done = 0;
1789 if(done || !getenv(
"HL_CGRADCL_TEST") || devid < 0)
return;
1792 const int region_w = 509;
1793 const int region_h = 371;
1794 const size_t region_pixels = (size_t)region_w * region_h;
1816 for(
int y = 0; y < region_h; y++)
1817 for(
int x = 0;
x < region_w;
x++)
1819 const size_t i = (size_t)y * region_w +
x;
1820 const float t = (float)
x / (
float)region_w;
1821 const float lum = 1.2f + 0.4f * sinf(0.013f *
x) * cosf(0.011f * y);
1822 estimate[
i * 4 + 0] = lum * (0.45f + 0.2f *
t);
1823 estimate[
i * 4 + 1] = lum * 0.33f;
1824 estimate[
i * 4 + 2] = lum * (0.22f - 0.2f *
t + 0.2f);
1825 estimate[
i * 4 + 3] = 0.f;
1826 const int dx =
x - region_w / 2, dy = y - region_h / 2;
1827 const float dist = sqrtf((
float)(dx * dx + dy * dy));
1828 const int rclip =
dist < 120.f, gclip =
dist < 95.f, bclip =
dist < 40.f;
1829 valid[
i * 4 + 0] = rclip ? 0.f : 1.f;
1830 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
1831 valid[
i * 4 + 2] = bclip ? 0.f : 1.f;
1832 valid[
i * 4 + 3] = rclip ? 0.f : 1.f;
1833 for(
int k = 0;
k < 4;
k++) clip0[
i * 4 +
k] = 0.6f;
1835 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = fmaxf(estimate[
i * 4 + c], 0.62f);
1843 if(rclip && !gclip &&
dist < 107.f)
1845 estimate[
i * 4 + 0] = clip0[
i * 4 + 0];
1846 estimate[
i * 4 + 1] = lum * 0.33f;
1847 estimate[
i * 4 + 2] = lum * (0.42f - 0.2f *
t);
1850 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
1897 float max_diff = -1.f;
1898 if(dest && dvld && dclip && ddepth && zero_depth
1908 && _chromaticity_gradient_stage_cl(devid, gd_void, dest, dvld, dclip, ddepth, region_w, region_h, 120.f, 1.f , 1.f, pipe)
1915 for(
size_t i = 0;
i < region_pixels;
i++)
1916 for(
int c = 0; c < 3; c++)
1917 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1919 fprintf(stderr,
"[hl cgrad-cl selftest] %dx%d gradient sky + 3-tier disc max|gpu-cpu|=%.3e\n", region_w,
1920 region_h, max_diff);
1942 static int done = 0;
1943 if(done || !getenv(
"HL_REGCL_TEST") || devid < 0)
return;
1946 const int width = 700;
1956 const float radii[3] = { 60.f, 75.f, 50.f };
1957 for(
int y = 0; y <
height; y++)
1960 const size_t i = (size_t)y *
width +
x;
1961 const float base = 0.5f + 0.3f * sinf(0.013f *
x) * cosf(0.011f * y) + 0.1f * cosf(0.03f *
x);
1962 const float gain[3] = { 0.9f, 1.15f, 0.75f };
1963 const int center_x =
width - 80;
1964 const int center_y =
height - 70;
1965 const int delta_x =
x - center_x;
1966 const int delta_y = y - center_y;
1967 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1968 const int occluder = (y > center_y - 8 && y < center_y + 8);
1970 for(
int c = 0; c < 3; c++)
1972 const int clipped = (
dist < radii[c]) && !occluder;
1973 mask[
i * 4 + c] = clipped ? 1.f : 0.f;
1974 interp[
i * 4 + c] = clipped ? 0.62f * gain[c] : fmaxf(base * gain[c] * (occluder ? 0.15f : 1.f), 0.f);
1975 any_clip |= clipped;
1977 mask[
i * 4 + 3] = any_clip ? 1.f : 0.f;
1978 interp[
i * 4 + 3] = interp[
i * 4 + 0] + interp[
i * 4 + 1] + interp[
i * 4 + 2];
1979 depth[
i] = fmaxf(radii[1] -
dist, 0.f);
1981 memcpy(interp_gpu, interp, n_pixels * 4 *
sizeof(
float));
1994 const float solid_color = 0.3f;
1996 _region_guided_filter(interp, mask, depth,
width, ®ion, pipe, solid_color, 30, 0.f, 0.7f, 1.f);
2002 float max_diff = -1.f;
2003 if(interp_device && mask_device && depth_device
2011 && _region_guided_filter_cl(devid, gd_void, interp_device, mask_device, depth_device,
width, ®ion, pipe,
2012 solid_color, 0.7f, 1.f)
2019 double sum_diff = 0.0;
2021 for(
size_t i = 0;
i < n_pixels;
i++)
2022 for(
int c = 0; c < 3; c++)
2024 const float diff = fabsf(interp_gpu[
i * 4 + c] - interp[
i * 4 + c]);
2025 max_diff = fmaxf(max_diff, diff);
2026 sum_diff += (
double)diff;
2027 if(diff > 1e-4f) n_big++;
2029 fprintf(stderr,
"[hl region-cl selftest] mean=%.3e npix>1e-4: %zu/%zu\n", sum_diff / (
double)(n_pixels * 3),
2030 n_big, n_pixels * 3);
2032 fprintf(stderr,
"[hl region-cl selftest] %dx%d staggered blob r=%g max|gpu-cpu|=%.3e\n",
width,
height,
2033 region.
radius, max_diff);
2048 static int done_ = 0;
2049 if(done_ || !getenv(
"HL_KNEECL_TEST") || devid < 0)
return;
2052 const size_t width = 1462;
2053 const size_t height = 1034;
2055 const uint32_t filters = 0x94949494u;
2066 for(
size_t j = 0; j <
width; j++)
2068 const int c =
FC(
i, j, filters);
2069 const float base = 0.55f + 0.45f * sinf(0.006f * j) * cosf(0.008f *
i) + 0.12f * sinf(0.03f * (
i + j));
2070 const float gain[3] = { 0.95f, 1.05f, 0.85f };
2071 float value = fmaxf(base * gain[c > 2 ? 1 : c], 0.f);
2083 float curve_diff = -1.f;
2084 float apply_diff = -1.f;
2086 if(in_device && out_device
2089 &&
_hl_knee_estimate_cl(devid, gd_void, in_device,
width,
height, filters, &roi_in, NULL, 0, clipraw,
2093 engaged_ok = (curve_cpu[0].
engaged == curve_gpu[0].
engaged) && (curve_cpu[1].engaged == curve_gpu[1].engaged)
2096 for(
int c = 0; c < 3; c++)
2098 curve_diff = fmaxf(curve_diff, fabsf(curve_cpu[c].lift[
i] - curve_gpu[c].lift[
i]));
2102 if(
_hl_knee_apply_cfa_cl(devid, gd_void, in_device, out_device,
width,
height, filters, &roi_in, NULL, 0,
2109 for(
size_t i = 0;
i < n_pixels;
i++) apply_diff = fmaxf(apply_diff, fabsf(corr_gpu[
i] - corr_cpu[
i]));
2113 "[hl knee-cl selftest] %zux%zu RGGB engaged cpu=[%d %d %d] match=%d "
2114 "max|curve dcpu-gpu|=%.3e max|apply gpu-cpu|=%.3e\n",
2115 width,
height, curve_cpu[0].engaged, curve_cpu[1].engaged, curve_cpu[2].engaged, engaged_ok,
2116 curve_diff, apply_diff);
static double dist(double x1, double y1, double x2, double y2)
void cleanup(dt_imageio_module_format_t *self)
cl_int _region_blur_cl(const int devid, cl_mem in, cl_mem out, const int region_w, const int region_h, const float sigma)
static void _region_blur(const float *const restrict in, float *const restrict out, const int region_w, const int region_h, const float sigma)
__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)
cl_int _cf_stage_cl(const int devid, void *gd_void, cl_mem estimate, cl_mem valid, cl_mem model_quality, cl_mem luminance, cl_mem steer, const float *const restrict channel_means, dt_gaussian_cl_t *gaussian, const int region_w, const int region_h, const float cf_sigma, const float cf_fmin, const float cf_binv, const int cdeep)
cl_int _cf_harmonic_fill_cl(const int devid, void *gd_void, cl_mem val, cl_mem hole, const int region_w, const int region_h, const int base_ds, const int mask_is_hole, cl_mem steer)
cl_int _cf_joint_stage_cl(const int devid, void *gd_void, cl_mem estimate, cl_mem valid, cl_mem model_quality, cl_mem mom0, cl_mem mom1, cl_mem mom2, cl_mem steer, const float *const restrict channel_means, const int region_w, const int region_h, const float cf_sigma, const float cf_fmin, const int c, const int guide1, const int guide2)
void _cf_harmonic_fill(float *const restrict val, const uint8_t *const restrict hole, const int region_w, const int region_h, const int base_ds, const float *const restrict steer, const dt_dev_pixelpipe_t *pipe)
cl_int _hf_stage_cl(const int devid, void *gd_void, cl_mem estimate, cl_mem valid, cl_mem model_quality, cl_mem luminance, cl_mem steer, dt_gaussian_cl_t *gaussian, const int region_w, const int region_h, const float cf_sigma, const float cf_fmin, const float cf_binv)
void _chromaticity_gradient(_hl_region_ctx_t *const ctx)
static int FC(const int row, const int col, const unsigned int filters)
__DT_CLONE_TARGETS__ void _biharmonic_dome(float *const restrict field, const uint8_t *const restrict hole, const int region_w, const int region_h, const int forced_downsample, const dt_dev_pixelpipe_t *pipe)
static 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)
__DT_CLONE_TARGETS__ void _hl_knee_estimate(const float *const restrict input, const size_t width, const size_t height, const uint32_t filters, const dt_iop_roi_t *const roi_in, const uint8_t(*const xtrans)[6], const dt_aligned_pixel_t clipval_raw, _hl_knee_curve_t curves[3], const dt_dev_pixelpipe_t *pipe)
__DT_CLONE_TARGETS__ void _hl_knee_apply_cfa(const float *const restrict input, float *const restrict input_corr, const size_t width, const size_t height, const uint32_t filters, const dt_iop_roi_t *const roi_in, const uint8_t(*const xtrans)[6], const dt_aligned_pixel_t clipval_raw, const _hl_knee_curve_t curves[3])
cl_int _hl_knee_estimate_cl(const int devid, void *gd_void, cl_mem dev_in, const size_t width, const size_t height, const uint32_t filters, const dt_iop_roi_t *const roi_in, cl_mem dev_xtrans, const int is_xtrans, const dt_aligned_pixel_t clipval_raw, _hl_knee_curve_t curves[3], const dt_dev_pixelpipe_t *pipe)
cl_int _hl_knee_apply_cfa_cl(const int devid, void *gd_void, cl_mem dev_in, cl_mem dev_out, const size_t width, const size_t height, const uint32_t filters, const dt_iop_roi_t *const roi_in, cl_mem dev_xtrans, const int is_xtrans, const dt_aligned_pixel_t clipval_raw, const _hl_knee_curve_t curves[3])
static void _knee_blur(const float *const restrict in, float *const restrict out, const int width, const int height, const float sigma)
float *const restrict luminance
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static float * dt_calloc_align_float(size_t pixels)
dt_alloc_align_float() followed by a zero fill.
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
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_copy_device_to_host(const int devid, void *host, void *device, const int width, const int height, const int bpp)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
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)
void dt_opencl_release_mem_object(cl_mem mem)
int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
__DT_CLONE_TARGETS__ void _region_pde_solve(float *const restrict field, const uint8_t *const restrict hole, const float *const restrict diffusion, const float *const restrict target, const float *const restrict source, const int order, const float lambda, const int region_w, const int region_h, float *const restrict residual, float *const restrict search_dir, float *const restrict operator_dir, float *const restrict embedded, float *const restrict scratch, const int maxiter)
_sp_chol_t * _sp_pde_factor(const uint8_t *const restrict hole, const float *const restrict diffusion, const int order, const float lambda, const int region_w, const int region_h, int **perm_out, int *n_unknowns_out, const dt_dev_pixelpipe_t *pipe)
__DT_CLONE_TARGETS__ void _sp_pde_solve(const _sp_chol_t *const factor, const int *const restrict perm_grid, float *const restrict field, const uint8_t *const restrict hole, const float *const restrict diffusion, const float *const restrict target, const float *const restrict source, const int order, const float lambda, const int region_w, const int region_h, double *const restrict rhs, float *const restrict embedded, float *const restrict operator_out, float *const restrict scratch)
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)
void _region_guided_filter(float *const restrict interp, const float *const restrict mask, const float *const restrict depth, const int width, const _hl_region_t *const region, const dt_dev_pixelpipe_t *pipe, const float solid_color, const int max_iter, const float noise_level, const float floor_gate, const float module_scale)
#define OFF3(chan_a, chan_b)
void _hf_stage_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _region_guided_filter_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _knee_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
#define OFF2(chan_a, chan_b)
void _joint_core_stage_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _selfdome_stage_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _aniso_stage_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _cf_harmonic_fill_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _cf_stage_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _region_blur_cl_selftest(const int devid, const dt_dev_pixelpipe_t *pipe)
void _chromaticity_gradient_stage_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _cf_joint_stage_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
void _sp_chol_cl_selftest(const int devid, void *gd_void, const dt_dev_pixelpipe_t *pipe)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
static const dt_aligned_pixel_simd_t value
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)
#define DT_HL_DOME_NMAX_SPARSE
const _hl_region_t * region
const dt_dev_pixelpipe_t * pipe
dt_dev_pixelpipe_type_t type
int kernel_hl_cf_pack_joint
Region of interest passed through the pixelpipe.
typedef double((*spd)(unsigned long int wavelength, double TempK))