42 if(done || !getenv(
"HL_SPCL_TEST"))
return;
46 uint8_t *hole = calloc((
size_t)grid * grid, 1);
47 int *grid_index = malloc(
sizeof(
int) * grid * grid);
49 for(
int y = 0; y < grid; y++)
50 for(
int x = 0;
x < grid;
x++)
52 const int delta_x =
x - grid / 2;
53 const int delta_y = y - grid / 2;
54 hole[y * grid +
x] = (delta_x * delta_x + delta_y * delta_y < 34 * 34);
55 grid_index[y * grid +
x] = hole[y * grid +
x] ?
dimension++ : -1;
58 static const int stencil_dy[13] = { 0, -1, 1, 0, 0, -1, -1, 1, 1, -2, 2, 0, 0 };
59 static const int stencil_dx[13] = { 0, 0, 0, -1, 1, -1, 1, -1, 1, 0, 0, -2, 2 };
60 static const double stencil_coeff[13] = { 20., -8., -8., -8., -8., 2., 2., 2., 2., 1., 1., 1., 1. };
62 int *matrix_col_ptr = calloc(
dimension + 1,
sizeof(
int));
63 int *matrix_row_index = malloc(
sizeof(
int) * (
size_t)
dimension * 13);
64 double *matrix_values = malloc(
sizeof(
double) * (
size_t)
dimension * 13);
65 double *rhs = malloc(
sizeof(
double) *
dimension);
66 double *solution_cpu = malloc(
sizeof(
double) *
dimension);
68 for(
int y = 0; y < grid; y++)
69 for(
int x = 0;
x < grid;
x++)
71 const int j = grid_index[y * grid +
x];
73 rhs[j] = 0.5 + 0.001 * (
double)((
x * 131 + y * 17) % 97);
74 matrix_col_ptr[j] = n_nonzero;
75 for(
int tap_index = 0; tap_index < 13; tap_index++)
77 const int neighbour_y = CLAMP(y + stencil_dy[tap_index], 0, grid - 1);
78 const int neighbour_x = CLAMP(
x + stencil_dx[tap_index], 0, grid - 1);
79 const int neighbour_index = grid_index[neighbour_y * grid + neighbour_x];
80 if(neighbour_index < 0 || neighbour_index > j)
continue;
81 int scan = matrix_col_ptr[j];
82 for(; scan < n_nonzero; scan++)
83 if(matrix_row_index[scan] == neighbour_index)
85 matrix_values[scan] += stencil_coeff[tap_index];
90 matrix_row_index[n_nonzero] = neighbour_index;
91 matrix_values[n_nonzero] = stencil_coeff[tap_index];
99 memcpy(solution_cpu, rhs,
sizeof(
double) *
dimension);
105 matrix_row_index, matrix_values);
106 double max_rel_diff = -1.0;
107 if(factor_cpu && factor_gpu)
112 double *solution_gpu = malloc(
sizeof(
double) *
dimension);
119 const double rel_diff = fabs(solution_gpu[
i] - solution_cpu[
i]) / fmax(fabs(solution_cpu[
i]), 1e-12);
120 if(rel_diff > max_rel_diff) max_rel_diff = rel_diff;
127 fprintf(stderr,
"[hl sparse-cl selftest] n=%d nnz=%d levels=%d/%d cpu=%s gpu=%s max rel diff=%.3e\n",
dimension,
129 factor_gpu ? factor_gpu->
nlev_bwd : -1, factor_cpu ?
"ok" :
"FAIL", factor_gpu ?
"ok" :
"FAIL",
136 free(matrix_col_ptr);
137 free(matrix_row_index);
146 if(done || !getenv(
"HL_BLURCL_TEST") || devid < 0)
return;
149 const int region_w = 731;
150 const int region_h = 517;
151 const size_t region_pixels = (size_t)region_w * region_h;
157 for(
size_t i = 0;
i < region_pixels;
i++)
158 for(
int c = 0; c < 4; c++)
159 input[
i * 4 + c] = 0.5f + 0.5f * sinf(0.013f * (
float)(
i % region_w) + 0.007f * (
float)(
i / region_w) + c);
161 static const float test_sigmas[3] = { 4.f, 16.f, 64.f };
162 for(
int sigma_index = 0; sigma_index < 3; sigma_index++)
164 const float sigma = test_sigmas[sigma_index];
169 float max_diff = -1.f;
170 if(in_device && out_device
178 for(
size_t i = 0;
i < region_pixels * 4;
i++)
179 max_diff = fmaxf(max_diff, fabsf(output_gpu[
i] - output_cpu[
i]));
183 fprintf(stderr,
"[hl blur-cl selftest] %dx%d sigma=%.0f max|gpu-cpu|=%.3e\n", region_w, region_h,
sigma,
196 if(done || !getenv(
"HL_FILLCL_TEST") || devid < 0)
return;
199 const int region_w = 613;
200 const int region_h = 419;
201 const size_t region_pixels = (size_t)region_w * region_h;
209 for(
int y = 0; y < region_h; y++)
210 for(
int x = 0;
x < region_w;
x++)
212 const size_t i = (size_t)y * region_w +
x;
213 const int delta_x =
x - region_w / 2;
214 const int delta_y = y - (region_h - 30);
215 hole[
i] = (delta_x * delta_x + delta_y * delta_y < 120 * 120);
216 anchor[
i] = !hole[
i];
217 val_cpu[
i] = hole[
i] ? 0.f : 0.3f + 0.4f * sinf(0.02f *
x) * cosf(0.017f * y);
219 memcpy(val_gpu, val_cpu,
sizeof(
float) * region_pixels);
225 float max_diff = -1.f;
230 &&
_cf_harmonic_fill_cl(devid, gd_void, dval, danc, region_w, region_h, 2, 0, NULL) == CL_SUCCESS
235 for(
size_t i = 0;
i < region_pixels;
i++)
236 if(hole[
i]) max_diff = fmaxf(max_diff, fabsf(val_gpu[
i] - val_cpu[
i]));
240 fprintf(stderr,
"[hl fill-cl selftest] %dx%d hole=disc r120 max|gpu-cpu|=%.3e\n", region_w, region_h, max_diff);
248 for(
int y = 0; y < region_h; y++)
249 for(
int x = 0;
x < region_w;
x++)
251 const size_t i = (size_t)y * region_w +
x;
252 const int dark_bar = (
x > region_w / 2 - 12 &&
x < region_w / 2 + 12);
253 steer[
i] = dark_bar ? 0.05f : (0.4f + 0.5f * (float)y / region_h);
254 val_cpu[
i] = hole[
i] ? 0.f : 0.3f + 0.4f * sinf(0.02f *
x) * cosf(0.017f * y);
256 memcpy(val_gpu, val_cpu,
sizeof(
float) * region_pixels);
263 float max_diff_aniso = -1.f;
264 if(aniso_val_device && aniso_anchor_device && aniso_steer_device
273 &&
_cf_harmonic_fill_cl(devid, gd_void, aniso_val_device, aniso_anchor_device, region_w, region_h, 2, 0,
280 max_diff_aniso = 0.f;
281 for(
size_t i = 0;
i < region_pixels;
i++)
282 if(hole[
i]) max_diff_aniso = fmaxf(max_diff_aniso, fabsf(val_gpu[
i] - val_cpu[
i]));
287 fprintf(stderr,
"[hl fill-cl ANISO selftest] %dx%d adaptive-tensor max|gpu-cpu|=%.3e\n", region_w, region_h,
303 if(done || !getenv(
"HL_CFCL_TEST") || devid < 0)
return;
306 const int region_w = 509;
307 const int region_h = 371;
308 const size_t region_pixels = (size_t)region_w * region_h;
309 const float cf_sigma = 24.f;
310 const float cf_fmin = 0.05f;
312 const int guide1 = 0;
313 const int guide2 = 2;
332 for(
int y = 0; y < region_h; y++)
333 for(
int x = 0;
x < region_w;
x++)
335 const size_t i = (size_t)y * region_w +
x;
336 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
337 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
338 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
339 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
340 estimate[
i * 4 + 3] = 0.f;
341 const int delta_x =
x - region_w / 2;
342 const int delta_y = y - region_h / 2;
343 const int clip = (delta_x * delta_x + delta_y * delta_y < 90 * 90);
344 valid[
i * 4 + 0] = 1.f;
345 valid[
i * 4 + 1] = clip ? 0.f : 1.f;
346 valid[
i * 4 + 2] = 1.f;
347 valid[
i * 4 + 3] = clip ? 0.f : 1.f;
348 for(
int k = 0;
k < 4;
k++) model_quality[
i * 4 +
k] = 0.f;
349 if(clip) estimate[
i * 4 + 1] = 0.55f;
351 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
353 double lum_accum = 0.0;
354 size_t lum_count = 0;
355 for(
size_t i = 0;
i < region_pixels;
i++)
356 if(valid[
i * 4 + 1] < 0.5f)
358 lum_accum += estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
361 const float cf_lref = lum_count ? (float)(lum_accum / (
double)lum_count) : 0.f;
362 const float cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
365 for(
int mode = 0; mode < 3; mode++)
367 for(
size_t i = 0;
i < region_pixels;
i++)
369 const float val_r = estimate[
i * 4 + 0];
370 const float val_g = estimate[
i * 4 + 1];
371 const float val_b = estimate[
i * 4 + 2];
372 const float rgb_sum = val_r + val_g + val_b;
373 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
374 const int all_valid = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f);
375 const float weight = all_valid ? bright_weight : 0.f;
379 input[
i * 4 + 1] =
weight * val_r;
380 input[
i * 4 + 2] =
weight * val_g;
381 input[
i * 4 + 3] =
weight * val_b;
385 input[
i * 4 + 0] =
weight * val_r * val_r;
386 input[
i * 4 + 1] =
weight * val_g * val_g;
387 input[
i * 4 + 2] =
weight * val_b * val_b;
388 input[
i * 4 + 3] =
weight * val_r * val_g;
392 input[
i * 4 + 0] =
weight * val_r * val_b;
393 input[
i * 4 + 1] =
weight * val_g * val_b;
394 input[
i * 4 + 2] = all_valid ? 1.f : 0.f;
395 input[
i * 4 + 3] = 0.f;
398 _region_blur(input, (mode == 0) ? moment1 : (mode == 1) ? moment2 : moment3, region_w, region_h, cf_sigma);
401 for(
size_t i = 0;
i < region_pixels;
i++)
403 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
404 const float inv_det = 1.f / norm;
406 = { moment1[
i * 4 + 1] * inv_det, moment1[
i * 4 + 2] * inv_det, moment1[
i * 4 + 3] * inv_det };
407 const float second_moment[3]
408 = { moment2[
i * 4 + 0] * inv_det, moment2[
i * 4 + 1] * inv_det, moment2[
i * 4 + 2] * inv_det };
409 const float cross_rg = moment2[
i * 4 + 3] * inv_det;
410 const float cross_rb = moment3[
i * 4 + 0] * inv_det;
411 const float cross_gb = moment3[
i * 4 + 1] * inv_det;
412#define OFF2(chan_a, chan_b) \
413 (((chan_a) + (chan_b)) == 1 ? cross_rg : (((chan_a) + (chan_b)) == 2 ? cross_rb : cross_gb))
414 const float mean1 = mean[guide1];
415 const float mean2 = mean[guide2];
416 const float mean_target = mean[c];
417 const float var11 = fmaxf(second_moment[guide1] - mean1 * mean1, 0.f);
418 const float var22 = fmaxf(second_moment[guide2] - mean2 * mean2, 0.f);
419 const float var12 =
OFF2(guide1, guide2) - mean1 * mean2;
420 const float cov_tg1 =
OFF2(c, guide1) - mean_target * mean1;
421 const float cov_tg2 =
OFF2(c, guide2) - mean_target * mean2;
422 const float var_target = fmaxf(second_moment[c] - mean_target * mean_target, 0.f);
424 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
425 const float determinant = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
426 const float slope_a = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
427 const float slope_b = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
428 const float r_sq = CLAMP((slope_a * cov_tg1 + slope_b * cov_tg2) / (var_target + 1e-12f), 0.f, 1.f);
429 coeff_field[
i * 4 + 0] = slope_a;
430 coeff_field[
i * 4 + 1] = slope_b;
431 coeff_field[
i * 4 + 2] = mean_target - slope_a * mean1 - slope_b * mean2;
432 coeff_field[
i * 4 + 3] = r_sq;
433 const int mass_ok = (moment3[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment3[
i * 4 + 2]);
434 const int valid_ok = (valid[
i * 4 + c] >= 0.5f);
435 anchor[
i] = (mass_ok && valid_ok && r_sq > 0.25f && fabsf(slope_a) < 64.f && fabsf(slope_b) < 64.f);
436 border[
i] = (mass_ok && valid_ok);
443 for(
size_t i = 0;
i < region_pixels;
i++)
445 hole[
i] = !anchor[
i];
446 hole2[
i] = !border[
i];
448 const int base_downsample = (int)(cf_sigma / 4.f);
449 for(
int k = 0;
k < 4;
k++)
451 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = coeff_field[
i * 4 +
k];
452 _cf_harmonic_fill(plane, (
k == 3) ? hole2 : hole, region_w, region_h, base_downsample, NULL, pipe);
453 for(
size_t i = 0;
i < region_pixels;
i++) coeff_field[
i * 4 +
k] = plane[
i];
459 for(
size_t i = 0;
i < region_pixels;
i++)
460 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
461 estimate[
i * 4 + c] = coeff_field[
i * 4 + 0] * estimate[
i * 4 + guide1]
462 + coeff_field[
i * 4 + 1] * estimate[
i * 4 + guide2] + coeff_field[
i * 4 + 2];
471 float max_diff = -1.f;
473 for(
size_t i = 0;
i < region_pixels;
i++)
474 luminance[
i] = estimate_gpu[
i * 4 + 0] + estimate_gpu[
i * 4 + 1] + estimate_gpu[
i * 4 + 2];
480 cl_mem moments_device[3];
481 moments_device[0] = moment0_device;
482 moments_device[1] = moment1_device;
483 moments_device[2] = moment2_device;
484 int moms_ok = (packed_device && moment0_device && moment1_device && moment2_device);
485 if(moms_ok && dest && dvld && dbsc && dlsb &&
luminance
494 cl_int test_cl_err = CL_SUCCESS;
495 for(
int mode = 0; mode < 3 && test_cl_err == CL_SUCCESS; mode++)
506 const float zero_shift = 0.f;
511 if(test_cl_err == CL_SUCCESS)
512 test_cl_err =
_region_blur_cl(devid, packed_device, moments_device[mode], region_w, region_h, cf_sigma);
514 moms_ok = (test_cl_err == CL_SUCCESS);
518 const float zero_means[3] = { 0.f, 0.f, 0.f };
523 &&
_cf_joint_stage_cl(devid, gd_void, dest, dvld, dbsc, moment0_device, moment1_device, moment2_device,
524 NULL, zero_means, region_w, region_h, cf_sigma, cf_fmin, c, guide1, guide2)
531 for(
size_t i = 0;
i < region_pixels;
i++)
532 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
533 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
544 fprintf(stderr,
"[hl cf-joint-cl selftest] %dx%d G-disc r90 max|gpu-cpu|=%.3e\n", region_w, region_h, max_diff);
565 if(done || !getenv(
"HL_CFCL_TEST") || devid < 0)
return;
568 const int region_w = 509;
569 const int region_h = 371;
570 const size_t region_pixels = (size_t)region_w * region_h;
571 const float cf_sigma = 24.f;
572 const float cf_fmin = 0.05f;
595 for(
int y = 0; y < region_h; y++)
596 for(
int x = 0;
x < region_w;
x++)
598 const size_t i = (size_t)y * region_w +
x;
599 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
600 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
601 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
602 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
603 estimate[
i * 4 + 3] = 0.f;
604 const int delta_x =
x - region_w / 2;
605 const int delta_y = y - region_h / 2;
606 const int gclip = (delta_x * delta_x + delta_y * delta_y < 100 * 100);
607 const int rclip = (delta_x * delta_x + delta_y * delta_y < 45 * 45);
608 valid[
i * 4 + 0] = rclip ? 0.f : 1.f;
609 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
610 valid[
i * 4 + 2] = 1.f;
611 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
612 for(
int k = 0;
k < 4;
k++) model_quality[
i * 4 +
k] = 0.f;
613 if(gclip) estimate[
i * 4 + 1] = 0.58f;
614 if(rclip) estimate[
i * 4 + 0] = 0.47f;
616 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
618 double lum_accum = 0.0;
619 size_t lum_count = 0;
620 for(
size_t i = 0;
i < region_pixels;
i++)
621 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f)
623 lum_accum += estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
626 const float cf_lref = lum_count ? (float)(lum_accum / (
double)lum_count) : 0.f;
627 const float cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
628 const int base_downsample = (int)(cf_sigma / 4.f);
633 for(
size_t i = 0;
i < region_pixels;
i++)
634 luminance[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
640 const int guide1 = 0;
641 const int guide2 = 2;
642 for(
int mode = 0; mode < 3; mode++)
644 for(
size_t i = 0;
i < region_pixels;
i++)
646 const float val_r = estimate[
i * 4 + 0];
647 const float val_g = estimate[
i * 4 + 1];
648 const float val_b = estimate[
i * 4 + 2];
650 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
651 const int all_valid = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f);
652 const float weight = all_valid ? bright_weight : 0.f;
656 input[
i * 4 + 1] =
weight * val_r;
657 input[
i * 4 + 2] =
weight * val_g;
658 input[
i * 4 + 3] =
weight * val_b;
662 input[
i * 4 + 0] =
weight * val_r * val_r;
663 input[
i * 4 + 1] =
weight * val_g * val_g;
664 input[
i * 4 + 2] =
weight * val_b * val_b;
665 input[
i * 4 + 3] =
weight * val_r * val_g;
669 input[
i * 4 + 0] =
weight * val_r * val_b;
670 input[
i * 4 + 1] =
weight * val_g * val_b;
671 input[
i * 4 + 2] = all_valid ? 1.f : 0.f;
672 input[
i * 4 + 3] = 0.f;
675 _region_blur(input, (mode == 0) ? moment1 : (mode == 1) ? moment2 : moment3, region_w, region_h, cf_sigma);
677 for(
size_t i = 0;
i < region_pixels;
i++)
679 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
680 const float inv_det = 1.f / norm;
682 = { moment1[
i * 4 + 1] * inv_det, moment1[
i * 4 + 2] * inv_det, moment1[
i * 4 + 3] * inv_det };
683 const float second_moment[3]
684 = { moment2[
i * 4 + 0] * inv_det, moment2[
i * 4 + 1] * inv_det, moment2[
i * 4 + 2] * inv_det };
685 const float cross_rg = moment2[
i * 4 + 3] * inv_det;
686 const float cross_rb = moment3[
i * 4 + 0] * inv_det;
687 const float cross_gb = moment3[
i * 4 + 1] * inv_det;
688 const float mean1 = mean[guide1];
689 const float mean2 = mean[guide2];
690 const float mean_target = mean[c];
691 const float var11 = fmaxf(second_moment[guide1] - mean1 * mean1, 0.f);
692 const float var22 = fmaxf(second_moment[guide2] - mean2 * mean2, 0.f);
693 const float var12 = cross_rb - mean1 * mean2;
694 const float cov_tg1 = cross_rg - mean_target * mean1;
695 const float cov_tg2 = cross_gb - mean_target * mean2;
696 const float var_target = fmaxf(second_moment[c] - mean_target * mean_target, 0.f);
697 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
698 const float determinant = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
699 const float slope_a = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
700 const float slope_b = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
701 const float r_sq = CLAMP((slope_a * cov_tg1 + slope_b * cov_tg2) / (var_target + 1e-12f), 0.f, 1.f);
702 coeff_field_green[
i * 4 + 0] = slope_a;
703 coeff_field_green[
i * 4 + 1] = slope_b;
704 coeff_field_green[
i * 4 + 2] = mean_target - slope_a * mean1 - slope_b * mean2;
705 coeff_field_green[
i * 4 + 3] = r_sq;
706 const int mass_ok = (moment3[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment3[
i * 4 + 2]);
707 const int valid_ok = (valid[
i * 4 + c] >= 0.5f);
708 anchor[
i] = (mass_ok && valid_ok && r_sq > 0.25f && fabsf(slope_a) < 64.f && fabsf(slope_b) < 64.f);
709 border[
i] = (mass_ok && valid_ok);
711 for(
size_t i = 0;
i < region_pixels;
i++)
713 hole[
i] = !anchor[
i];
714 hole_border[
i] = !border[
i];
716 for(
int k = 0;
k < 4;
k++)
718 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = coeff_field_green[
i * 4 +
k];
719 _cf_harmonic_fill(plane, (
k == 3) ? hole_border : hole, region_w, region_h, base_downsample, NULL, pipe);
720 for(
size_t i = 0;
i < region_pixels;
i++) coeff_field_green[
i * 4 +
k] = plane[
i];
725 const int pair_a[2] = { 0, 1 };
726 const int pair_b[2] = { 2, 2 };
729 const int chan_a = pair_a[
pair];
730 const int chan_b = pair_b[
pair];
731 const int target_chan = chan_a;
732 const int guide_chan = chan_b;
733 const int other_chan = 3 - chan_a - chan_b;
734 for(
int mode = 0; mode < 2; mode++)
736 for(
size_t i = 0;
i < region_pixels;
i++)
738 const float value_a = estimate[
i * 4 + chan_a];
739 const float value_b = estimate[
i * 4 + chan_b];
741 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
742 const int pair_valid = (valid[
i * 4 + chan_a] >= 0.5f && valid[
i * 4 + chan_b] >= 0.5f);
743 const float weight = pair_valid ? bright_weight : 0.f;
747 input[
i * 4 + 1] =
weight * value_a;
748 input[
i * 4 + 2] =
weight * value_b;
749 input[
i * 4 + 3] =
weight * value_a * value_a;
753 input[
i * 4 + 0] =
weight * value_b * value_b;
754 input[
i * 4 + 1] =
weight * value_a * value_b;
755 input[
i * 4 + 2] = pair_valid ? 1.f : 0.f;
756 input[
i * 4 + 3] = 0.f;
759 _region_blur(input, mode ? moment2 : moment1, region_w, region_h, cf_sigma);
761 for(
size_t i = 0;
i < region_pixels;
i++)
763 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
764 const float inv_det = 1.f / norm;
765 const float mean_target = moment1[
i * 4 + 1] * inv_det;
766 const float mean_guide = moment1[
i * 4 + 2] * inv_det;
767 const float var_guide = fmaxf(moment2[
i * 4 + 0] * inv_det - mean_guide * mean_guide, 0.f);
768 const float var_t = fmaxf(moment1[
i * 4 + 3] * inv_det - mean_target * mean_target, 0.f);
769 const float covariance = moment2[
i * 4 + 1] * inv_det - mean_target * mean_guide;
770 const float slope_a = covariance / (var_guide * (1.f + 1e-3f) + 1e-12f);
771 const float r_sq = CLAMP(covariance * covariance / (var_guide * var_t + 1e-18f), 0.f, 1.f);
772 moment3[
i * 4 + 0] = slope_a;
773 moment3[
i * 4 + 1] = mean_target - slope_a * mean_guide;
774 moment3[
i * 4 + 2] = r_sq;
775 const int mass_ok = (moment2[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment2[
i * 4 + 2]);
776 const int valid_ok = (valid[
i * 4 + target_chan] >= 0.5f);
777 anchor[
i] = (mass_ok && valid_ok && r_sq > 0.25f && fabsf(slope_a) < 64.f);
778 border[
i] = (mass_ok && valid_ok);
780 for(
size_t i = 0;
i < region_pixels;
i++)
782 hole[
i] = !anchor[
i];
783 hole_border[
i] = !border[
i];
785 for(
int k = 0;
k < 3;
k++)
787 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = moment3[
i * 4 +
k];
788 _cf_harmonic_fill(plane, (
k == 2) ? hole_border : hole, region_w, region_h, base_downsample, NULL, pipe);
789 for(
size_t i = 0;
i < region_pixels;
i++) moment3[
i * 4 +
k] = plane[
i];
791 for(
size_t i = 0;
i < region_pixels;
i++)
792 if(valid[
i * 4 + target_chan] < 0.5f && valid[
i * 4 + guide_chan] >= 0.5f && valid[
i * 4 + other_chan] < 0.5f)
794 estimate[
i * 4 + target_chan] = moment3[
i * 4 + 0] * estimate[
i * 4 + guide_chan] + moment3[
i * 4 + 1];
795 model_quality[
i * 4 + target_chan] = CLAMP(moment3[
i * 4 + 2], 0.f, 1.f);
801 const int guide1 = 0;
802 const int guide2 = 2;
803 for(
size_t i = 0;
i < region_pixels;
i++)
806 = (valid[
i * 4 + cdeep] < 0.5f && (valid[
i * 4 + guide1] < 0.5f || valid[
i * 4 + guide2] < 0.5f));
807 input[
i * 4 + 0] = multi_clip ? 1.f : 0.f;
808 input[
i * 4 + 1] = input[
i * 4 + 2] = input[
i * 4 + 3] = 0.f;
810 _region_blur(input, moment1, region_w, region_h, cf_sigma);
811 for(
size_t i = 0;
i < region_pixels;
i++)
813 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
814 if(valid[
i * 4 + cdeep] >= 0.5f || !anyvalid)
continue;
815 const float joint = coeff_field_green[
i * 4 + 0] * estimate[
i * 4 + guide1]
816 + coeff_field_green[
i * 4 + 1] * estimate[
i * 4 + guide2] + coeff_field_green[
i * 4 + 2];
817 const int has_pair = (valid[
i * 4 + guide1] < 0.5f || valid[
i * 4 + guide2] < 0.5f);
818 const float mass = CLAMP(moment1[
i * 4 + 0], 0.f, 1.f);
819 const float smooth_t = CLAMP((mass - 0.7f) / 0.25f, 0.f, 1.f);
820 const float weight_depth = has_pair ? smooth_t * smooth_t * (3.f - 2.f * smooth_t) : 0.f;
821 estimate[
i * 4 + cdeep] = weight_depth * estimate[
i * 4 + cdeep] + (1.f - weight_depth) * joint;
822 model_quality[
i * 4 + cdeep] = weight_depth * model_quality[
i * 4 + cdeep]
823 + (1.f - weight_depth) * CLAMP(coeff_field_green[
i * 4 + 3], 0.f, 1.f);
832 float max_diff = -1.f;
833 float max_bsc_diff = -1.f;
834 if(dest && dvld && dbsc
844 memset(zero, 0,
sizeof(
float) * region_pixels * 4);
849 const float zero_means[3] = { 0.f, 0.f, 0.f };
853 &&
_cf_stage_cl(devid, gd_void, dest, dvld, dbsc, dlsb, NULL, zero_means, NULL, region_w, region_h,
854 cf_sigma, cf_fmin, cf_binv, cdeep)
861 for(
size_t i = 0;
i < region_pixels;
i++)
862 for(
int c = 0; c < 3; c++)
863 if(valid[
i * 4 + c] < 0.5f)
864 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
872 size_t arg_index = 0;
874 for(
size_t i = 0;
i < region_pixels;
i++)
875 for(
int c = 0; c < 3; c++)
877 const float diff = fabsf(estimate_gpu[
i * 4 + c] - model_quality[
i * 4 + c]);
878 if(diff > max_bsc_diff)
885 if(getenv(
"HL_CFCL_VERBOSE"))
886 fprintf(stderr,
"[hl cf-full bsc argmax] px=(%zu,%zu) c=%d gpu=%f cpu=%f\n", arg_index % region_w,
887 arg_index / region_w, arg_chan, estimate_gpu[arg_index * 4 + arg_chan],
888 model_quality[arg_index * 4 + arg_chan]);
896 fprintf(stderr,
"[hl cf-full-cl selftest] %dx%d G-disc r100 + R-core r45 max|gpu-cpu|=%.3e bsc=%.3e\n",
897 region_w, region_h, max_diff, max_bsc_diff);
921 if(done || !getenv(
"HL_HFCL_TEST") || devid < 0)
return;
924 const int region_w = 509;
925 const int region_h = 371;
926 const size_t region_pixels = (size_t)region_w * region_h;
927 const float cf_sigma = 24.f;
928 const float cf_fmin = 0.05f;
929 const float blur_sigma = fmaxf(cf_sigma / 4.f, 2.f);
930 const int base_downsample = (int)(cf_sigma / 4.f);
952 for(
int y = 0; y < region_h; y++)
953 for(
int x = 0;
x < region_w;
x++)
955 const size_t i = (size_t)y * region_w +
x;
956 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
957 const float texture = 0.05f * sinf(0.9f *
x) * sinf(0.75f * y);
958 estimate[
i * 4 + 0] = 0.9f * base + 0.05f + texture;
959 estimate[
i * 4 + 1] = 1.2f * base + 0.02f + 0.8f * texture;
960 estimate[
i * 4 + 2] = 0.7f * base + 0.08f + 1.1f * texture;
961 estimate[
i * 4 + 3] = 0.f;
962 const int delta_x =
x - region_w / 2;
963 const int delta_y = y - region_h / 2;
964 const int gclip = (delta_x * delta_x + delta_y * delta_y < 100 * 100);
965 const int rclip = (delta_x * delta_x + delta_y * delta_y < 45 * 45);
966 valid[
i * 4 + 0] = rclip ? 0.f : 1.f;
967 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
968 valid[
i * 4 + 2] = 1.f;
969 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
970 for(
int k = 0;
k < 4;
k++) model_quality[
i * 4 +
k] = gclip ? 0.65f : 0.f;
972 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
974 double lum_accum = 0.0;
975 size_t lum_count = 0;
976 for(
size_t i = 0;
i < region_pixels;
i++)
977 if(valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f)
979 lum_accum += estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
982 const float cf_lref = lum_count ? (float)(lum_accum / (
double)lum_count) : 0.f;
983 const float cf_binv = (cf_lref > 1e-9f) ? 1.f / (0.35f * cf_lref) : 0.f;
986 memcpy(input, estimate, region_pixels * 4 *
sizeof(
float));
987 _region_blur(input, lowpass, region_w, region_h, blur_sigma);
988 for(
int mode = 0; mode < 3; mode++)
990 for(
size_t i = 0;
i < region_pixels;
i++)
992 const float detail_r = estimate[
i * 4 + 0] - lowpass[
i * 4 + 0];
993 const float detail_g = estimate[
i * 4 + 1] - lowpass[
i * 4 + 1];
994 const float detail_b = estimate[
i * 4 + 2] - lowpass[
i * 4 + 2];
995 const float rgb_sum = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
996 const float bright_weight = (cf_binv > 0.f) ? sqf(fminf(rgb_sum * cf_binv, 1.f)) : 1.f;
997 const int all_valid = (valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f);
998 const float weight = all_valid ? bright_weight : 0.f;
1002 input[
i * 4 + 1] =
weight * detail_r;
1003 input[
i * 4 + 2] =
weight * detail_g;
1004 input[
i * 4 + 3] =
weight * detail_b;
1008 input[
i * 4 + 0] =
weight * detail_r * detail_r;
1009 input[
i * 4 + 1] =
weight * detail_g * detail_g;
1010 input[
i * 4 + 2] =
weight * detail_b * detail_b;
1011 input[
i * 4 + 3] =
weight * detail_r * detail_g;
1015 input[
i * 4 + 0] =
weight * detail_r * detail_b;
1016 input[
i * 4 + 1] =
weight * detail_g * detail_b;
1017 input[
i * 4 + 2] = all_valid ? 1.f : 0.f;
1018 input[
i * 4 + 3] = 0.f;
1021 _region_blur(input, (mode == 0) ? moment1 : (mode == 1) ? moment2 : moment3, region_w, region_h, cf_sigma);
1023 for(
int c = 0; c < 3; c++)
1025 const int guide1 = (c == 0) ? 1 : 0;
1026 const int guide2 = (c == 2) ? 1 : 2;
1027 for(
size_t i = 0;
i < region_pixels;
i++)
1029 const float norm = fmaxf(moment1[
i * 4 + 0], 1e-9f);
1030 const float inv_det = 1.f / norm;
1032 = { moment1[
i * 4 + 1] * inv_det, moment1[
i * 4 + 2] * inv_det, moment1[
i * 4 + 3] * inv_det };
1033 const float second_moment[3]
1034 = { moment2[
i * 4 + 0] * inv_det, moment2[
i * 4 + 1] * inv_det, moment2[
i * 4 + 2] * inv_det };
1035 const float cross_rg = moment2[
i * 4 + 3] * inv_det;
1036 const float cross_rb = moment3[
i * 4 + 0] * inv_det;
1037 const float cross_gb = moment3[
i * 4 + 1] * inv_det;
1038#define OFF3(chan_a, chan_b) \
1039 (((chan_a) + (chan_b)) == 1 ? cross_rg : (((chan_a) + (chan_b)) == 2 ? cross_rb : cross_gb))
1040 const float mean1 = mean[guide1];
1041 const float mean2 = mean[guide2];
1042 const float mean_target = mean[c];
1043 const float var11 = fmaxf(second_moment[guide1] - mean1 * mean1, 0.f);
1044 const float var22 = fmaxf(second_moment[guide2] - mean2 * mean2, 0.f);
1045 const float var12 =
OFF3(guide1, guide2) - mean1 * mean2;
1046 const float cov_tg1 =
OFF3(c, guide1) - mean_target * mean1;
1047 const float cov_tg2 =
OFF3(c, guide2) - mean_target * mean2;
1048 const float var_target = fmaxf(second_moment[c] - mean_target * mean_target, 0.f);
1050 const float lambda = 1e-3f * 0.5f * (var11 + var22) + 1e-12f;
1051 const float determinant = fmaxf((var11 + lambda) * (var22 + lambda) - var12 * var12, 1e-18f);
1052 const float slope_a = ((var22 + lambda) * cov_tg1 - var12 * cov_tg2) / determinant;
1053 const float slope_b = ((var11 + lambda) * cov_tg2 - var12 * cov_tg1) / determinant;
1054 const float r_sq = CLAMP((slope_a * cov_tg1 + slope_b * cov_tg2) / (var_target + 1e-12f), 0.f, 1.f);
1055 gain_ab[
i * 2 + 0] = slope_a * r_sq;
1056 gain_ab[
i * 2 + 1] = slope_b * r_sq;
1057 const int mass_ok = (moment3[
i * 4 + 2] > cf_fmin && moment1[
i * 4 + 0] > 0.25f * moment3[
i * 4 + 2]);
1058 anchor[
i] = (mass_ok && valid[
i * 4 + c] >= 0.5f && fabsf(gain_ab[
i * 2 + 0]) < 64.f
1059 && fabsf(gain_ab[
i * 2 + 1]) < 64.f);
1061 for(
size_t i = 0;
i < region_pixels;
i++) hole[
i] = !anchor[
i];
1062 for(
int k = 0;
k < 2;
k++)
1064 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = gain_ab[
i * 2 +
k];
1065 _cf_harmonic_fill(plane, hole, region_w, region_h, base_downsample, NULL, pipe);
1066 for(
size_t i = 0;
i < region_pixels;
i++) gain_ab[
i * 2 +
k] = plane[
i];
1068 for(
size_t i = 0;
i < region_pixels;
i++)
1070 const float high_guide = gain_ab[
i * 2 + 0] * (estimate[
i * 4 + guide1] - lowpass[
i * 4 + guide1])
1071 + gain_ab[
i * 2 + 1] * (estimate[
i * 4 + guide2] - lowpass[
i * 4 + guide2]);
1072 const float high_damped
1073 = CLAMP(model_quality[
i * 4 + c], 0.f, 1.f) * (estimate[
i * 4 + c] - lowpass[
i * 4 + c]);
1074 input[
i * 4 + 0] = fabsf(high_guide);
1075 input[
i * 4 + 1] = fabsf(high_damped);
1076 input[
i * 4 + 2] = 0.f;
1077 input[
i * 4 + 3] = 0.f;
1079 _region_blur(input, energy, region_w, region_h, blur_sigma);
1080 for(
size_t i = 0;
i < region_pixels;
i++)
1081 if(valid[
i * 4 + c] < 0.5f && valid[
i * 4 + guide1] >= 0.5f && valid[
i * 4 + guide2] >= 0.5f)
1083 const float high_guide = gain_ab[
i * 2 + 0] * (estimate[
i * 4 + guide1] - lowpass[
i * 4 + guide1])
1084 + gain_ab[
i * 2 + 1] * (estimate[
i * 4 + guide2] - lowpass[
i * 4 + guide2]);
1085 const float high_damped
1086 = CLAMP(model_quality[
i * 4 + c], 0.f, 1.f) * (estimate[
i * 4 + c] - lowpass[
i * 4 + c]);
1087 const float weight_energy
1088 = energy[
i * 4 + 1] * energy[
i * 4 + 1]
1089 / fmaxf(energy[
i * 4 + 1] * energy[
i * 4 + 1] + energy[
i * 4 + 0] * energy[
i * 4 + 0], 1e-18f);
1091 = lowpass[
i * 4 + c] + weight_energy * high_guide + (1.f - weight_energy) * high_damped;
1094 for(
size_t i = 0;
i < region_pixels;
i++)
1096 const int n_valid = (valid[
i * 4 + 0] >= 0.5f) + (valid[
i * 4 + 1] >= 0.5f) + (valid[
i * 4 + 2] >= 0.5f);
1097 if(n_valid != 1)
continue;
1098 for(
int c = 0; c < 3; c++)
1099 if(valid[
i * 4 + c] < 0.5f)
1101 const float weight_hf = CLAMP(model_quality[
i * 4 + c], 0.f, 1.f);
1102 estimate[
i * 4 + c] = lowpass[
i * 4 + c] + weight_hf * (estimate[
i * 4 + c] - lowpass[
i * 4 + c]);
1113 float max_diff = -1.f;
1115 for(
size_t i = 0;
i < region_pixels;
i++)
1116 luminance[
i] = estimate_gpu[
i * 4 + 0] + estimate_gpu[
i * 4 + 1] + estimate_gpu[
i * 4 + 2];
1117 if(dest && dvld && dbsc && dlsb &&
luminance
1127 &&
_hf_stage_cl(devid, gd_void, dest, dvld, dbsc, dlsb, NULL, NULL, region_w, region_h, cf_sigma, cf_fmin,
1135 for(
size_t i = 0;
i < region_pixels;
i++)
1136 for(
int c = 0; c < 3; c++)
1137 if(valid[
i * 4 + c] < 0.5f)
1138 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1145 fprintf(stderr,
"[hl hf-cl selftest] %dx%d two-disc textured max|gpu-cpu|=%.3e\n", region_w, region_h,
1168 static int done = 0;
1169 if(done || !getenv(
"HL_DOMECL_TEST") || devid < 0)
return;
1175 const char *reg_dump_path = getenv(
"HL_REG_DUMP");
1176 FILE *dump_file = (reg_dump_path && reg_dump_path[0]) ? g_fopen(reg_dump_path,
"rb") : NULL;
1181 int dump_downsample;
1182 if(fread(&dump_w,
sizeof(
int), 1, dump_file) == 1 && fread(&dump_h,
sizeof(
int), 1, dump_file) == 1
1183 && fread(&dump_downsample,
sizeof(
int), 1, dump_file) == 1)
1185 const size_t dump_pixels = (size_t)dump_w * dump_h;
1189 if(dump_cpu && dump_gpu && dump_hole
1190 && fread(dump_cpu,
sizeof(
float), dump_pixels, dump_file) == dump_pixels
1191 && fread(dump_hole, 1, dump_pixels, dump_file) == dump_pixels)
1193 memcpy(dump_gpu, dump_cpu, dump_pixels *
sizeof(
float));
1194 _biharmonic_dome(dump_cpu, dump_hole, dump_w, dump_h, dump_downsample, pipe);
1197 float max_diff = -1.f;
1199 if(val_device && hole_device
1205 && _biharmonic_dome_cl(devid, gd_void, val_device, hole_device, dump_w, dump_h, dump_downsample, pipe)
1212 for(
size_t i = 0;
i < dump_pixels;
i++)
1214 if(isnan(dump_gpu[
i]))
1217 max_diff = fmaxf(max_diff, fabsf(dump_gpu[
i] - dump_cpu[
i]));
1220 fprintf(stderr,
"[hl dome-cl REPLAY] %dx%d ds=%d nan=%zu max|gpu-cpu|=%.3e\n", dump_w, dump_h,
1221 dump_downsample, n_nan, max_diff);
1233 const int region_w = 509;
1234 const int region_h = 371;
1235 const size_t region_pixels = (size_t)region_w * region_h;
1236 const float cf_sigma = 24.f;
1237 const float reg_radius = 100.f;
1238 const float epsilon = 1e-6f;
1255 size_t n_hole_union = 0;
1256 for(
int y = 0; y < region_h; y++)
1257 for(
int x = 0;
x < region_w;
x++)
1259 const size_t i = (size_t)y * region_w +
x;
1260 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
1261 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
1262 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
1263 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
1264 estimate[
i * 4 + 3] = 0.f;
1265 const int delta_x =
x - region_w / 2;
1266 const int delta_y = y - region_h / 2;
1267 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1268 const int gclip = (
dist < 100.f);
1269 const int rclip = (
dist < 45.f);
1270 valid[
i * 4 + 0] = rclip ? 0.f : 1.f;
1271 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
1272 valid[
i * 4 + 2] = 1.f;
1273 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
1274 for(
int k = 0;
k < 4;
k++)
1276 model_quality[
i * 4 +
k] = gclip ? 0.55f : 0.f;
1277 clip0[
i * 4 +
k] = 0.5f;
1279 depth[
i] = fmaxf(100.f -
dist, 0.f);
1280 if(gclip) n_hole_union++;
1282 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
1287 for(
size_t i = 0;
i < region_pixels;
i++)
1288 for(
int c = 0; c < 3; c++)
1289 if(valid[
i * 4 + c] < 0.5f)
1291 const float clip_floor = clip0[
i * 4 + c];
1292 const float diff = estimate[
i * 4 + c] - clip_floor;
1293 const float soft_width = 0.02f * fmaxf(clip_floor, 1e-6f);
1294 estimate[
i * 4 + c] = clip_floor + 0.5f * (diff + sqrtf(diff * diff + soft_width * soft_width));
1296 for(
size_t i = 0;
i < region_pixels;
i++)
1298 luminance[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
1299 hole[
i] = (valid[
i * 4 + 0] < 0.5f || valid[
i * 4 + 1] < 0.5f || valid[
i * 4 + 2] < 0.5f);
1302 _biharmonic_dome(dome_lum, hole, region_w, region_h, downsample_shared, pipe);
1304 const int cf_base = (int)(CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f);
1308 for(
int c = 0; c < 3; c++)
1310 for(
size_t i = 0;
i < region_pixels;
i++) plane[
i] = estimate[
i * 4 + c] / fmaxf(
luminance[
i], epsilon);
1312 for(
size_t i = 0;
i < region_pixels;
i++) ratio[
i * 3 + c] = fmaxf(plane[
i], 0.f);
1317 for(
size_t i = 0;
i < region_pixels;
i++)
1319 if(!hole[
i])
continue;
1320 const float chroma_sum = fmaxf(ratio[
i * 3 + 0] + ratio[
i * 3 + 1] + ratio[
i * 3 + 2], epsilon);
1321 const int anyvalid = (valid[
i * 4 + 0] >= 0.5f) || (valid[
i * 4 + 1] >= 0.5f) || (valid[
i * 4 + 2] >= 0.5f);
1322 for(
int c = 0; c < 3; c++)
1323 if(valid[
i * 4 + c] < 0.5f)
1325 const float quality = CLAMP((model_quality[
i * 4 + c] - 0.4f) / 0.45f, 0.f, 1.f);
1326 const float weight_r2 = quality * quality * (3.f - 2.f * quality);
1327 const float depth_t = depth[
i] / (1.5f * cf_sigma);
1328 const float depth_gauss = expf(-depth_t * depth_t);
1329 const float weight_sqrt = sqrtf(CLAMP(1.f - (1.f - weight_r2) * depth_gauss, 0.f, 1.f));
1330 const float weight = weight_sqrt * weight_sqrt;
1331 const float dome = dome_lum[
i] * (ratio[
i * 3 + c] / chroma_sum);
1332 estimate[
i * 4 + c] = anyvalid ? (
weight * estimate[
i * 4 + c] + (1.f -
weight) * dome) : dome;
1335 for(
size_t i = 0;
i < region_pixels;
i++)
1336 for(
int c = 0; c < 3; c++)
1337 if(valid[
i * 4 + c] < 0.5f) estimate[
i * 4 + c] = fmaxf(estimate[
i * 4 + c], clip0[
i * 4 + c]);
1346 float max_diff = -1.f;
1347 if(dest && dvld && dbsc && dclip && ddep
1359 && _selfdome_stage_cl(devid, gd_void, dest, dvld, dbsc, dclip, ddep, region_w, region_h, cf_sigma,
1360 reg_radius, downsample_shared, pipe)
1367 for(
size_t i = 0;
i < region_pixels;
i++)
1368 for(
int c = 0; c < 3; c++)
1369 if(valid[
i * 4 + c] < 0.5f)
1370 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1377 fprintf(stderr,
"[hl dome-cl selftest] %dx%d two-disc ds=%d max|gpu-cpu|=%.3e\n", region_w, region_h,
1378 downsample_shared, max_diff);
1396 static int done = 0;
1397 if(done || !getenv(
"HL_CORECL_TEST") || devid < 0)
return;
1400 const int region_w = 509;
1401 const int region_h = 371;
1402 const size_t region_pixels = (size_t)region_w * region_h;
1403 const float solid_color = 0.4f;
1404 const float reg_radius = 100.f;
1405 const float epsilon = 1e-6f;
1428 for(
int y = 0; y < region_h; y++)
1429 for(
int x = 0;
x < region_w;
x++)
1431 const size_t i = (size_t)y * region_w +
x;
1432 const float base = 0.4f + 0.3f * sinf(0.011f *
x) * cosf(0.014f * y);
1433 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
1434 estimate[
i * 4 + 1] = 1.2f * base + 0.02f;
1435 estimate[
i * 4 + 2] = 0.7f * base + 0.08f;
1436 estimate[
i * 4 + 3] = 0.f;
1437 const int delta_x =
x - region_w / 2;
1438 const int delta_y = y - (region_h - 40);
1439 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1440 const int allclip = (
dist < 95.f);
1441 const int gclip = (
dist < 145.f);
1442 valid[
i * 4 + 0] = allclip ? 0.f : 1.f;
1443 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
1444 valid[
i * 4 + 2] = allclip ? 0.f : 1.f;
1445 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
1446 for(
int k = 0;
k < 4;
k++) clip0[
i * 4 +
k] = 0.5f;
1448 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = 0.5f;
1450 estimate[
i * 4 + 1] = 0.55f + 0.002f * (100.f -
dist);
1452 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
1456 for(
size_t i = 0;
i < region_pixels;
i++)
1458 hole[
i] = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
1459 luminance[
i] = estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2];
1463 memcpy(dome_lum, chroma_work, region_pixels *
sizeof(
float));
1464 for(
size_t i = 0;
i < region_pixels;
i++)
1465 if(hole[
i]) dome_lum[
i] = fmaxf(dome_lum[
i], clip0[
i * 4 + 0] + clip0[
i * 4 + 1] + clip0[
i * 4 + 2]);
1468 double chroma_accum[3] = { 0.0, 0.0, 0.0 };
1469 double chroma_count = 0.0;
1470 for(
size_t i = 0;
i < region_pixels;
i++)
1472 if(!(valid[
i * 4 + 0] >= 0.5f && valid[
i * 4 + 1] >= 0.5f && valid[
i * 4 + 2] >= 0.5f))
continue;
1473 const float inv_lum = 1.f / fmaxf(
luminance[
i], epsilon);
1474 chroma_accum[0] += (
double)(estimate[
i * 4 + 0] * inv_lum);
1475 chroma_accum[1] += (
double)(estimate[
i * 4 + 1] * inv_lum);
1476 chroma_accum[2] += (
double)(estimate[
i * 4 + 2] * inv_lum);
1477 chroma_count += 1.0;
1479 if(chroma_count > 0.0)
1480 for(
int c = 0; c < 3; c++) chroma_mean[c] = (
float)(chroma_accum[c] / chroma_count);
1482 const float reaction = solid_color * solid_color * 4.f;
1483 for(
size_t i = 0;
i < region_pixels;
i++) diffusion_buf[
i] = reaction;
1485 int *sp_pgrid = NULL;
1486 int sp_n_unknowns = 0;
1488 region_h, &sp_pgrid, &sp_n_unknowns, pipe);
1494 const int max_iter = CLAMP(2 * 150, 200, 2000);
1495 for(
int c = 0; c < 3; c++)
1497 for(
size_t i = 0;
i < region_pixels;
i++)
1499 chroma_work[
i] = hole[
i] ? chroma_mean[c] : (estimate[
i * 4 + c] / fmaxf(
luminance[
i], epsilon));
1500 target_buf[
i] = chroma_mean[c];
1502 if(sp_factor && sp_rhs)
1503 _sp_pde_solve(sp_factor, sp_pgrid, chroma_work, hole, (reaction > 0.f) ? diffusion_buf : NULL,
1504 (reaction > 0.f) ? target_buf : NULL, NULL, 1, 1.f, region_w, region_h, sp_rhs, scratch1,
1505 scratch2, scratch_sc);
1506 else if(cg_residual && cg_search && cg_matvec)
1508 (reaction > 0.f) ? target_buf : NULL, NULL, 1, 1.f, region_w, region_h, cg_residual,
1509 cg_search, cg_matvec, scratch1, scratch2, max_iter);
1510 for(
size_t i = 0;
i < region_pixels;
i++) chroma[
i * 4 + c] = fmaxf(chroma_work[
i], 0.f);
1512 fprintf(stderr,
"[hl core-cl selftest] CPU path: %s\n", (sp_factor && sp_rhs) ?
"sparse" :
"CG");
1520 for(
size_t i = 0;
i < region_pixels;
i++) chroma_work[
i] = hole[
i] ? 1.f : 0.f;
1521 _knee_blur(chroma_work, weight_feather, region_w, region_h,
1522 fmaxf(4.f, CLAMP(reg_radius / 6.f, 8.f, 64.f) / 4.f));
1524 for(
size_t i = 0;
i < region_pixels;
i++)
1526 const float feather = CLAMP(weight_feather[
i], 0.f, 1.f);
1527 const float chroma_sum = fmaxf(chroma[
i * 4 + 0] + chroma[
i * 4 + 1] + chroma[
i * 4 + 2], epsilon);
1530 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = dome_lum[
i] * (chroma[
i * 4 + c] / chroma_sum);
1532 else if(feather > 1e-4f)
1534 for(
int c = 0; c < 3; c++)
1535 if(valid[
i * 4 + c] < 0.5f)
1537 = feather * dome_lum[
i] * (chroma[
i * 4 + c] / chroma_sum) + (1.f - feather) * estimate[
i * 4 + c];
1547 float max_diff = -1.f;
1548 if(dest && dvld && dclip
1555 && _joint_core_stage_cl(devid, gd_void, dest, dvld, dclip, region_w, region_h, solid_color, reg_radius, 150,
1563 for(
size_t i = 0;
i < region_pixels;
i++)
1564 for(
int c = 0; c < 3; c++)
1565 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1567 fprintf(stderr,
"[hl core-cl selftest] %dx%d all-clip disc + annulus max|gpu-cpu|=%.3e\n", region_w, region_h,
1594 static int done = 0;
1595 if(done || !getenv(
"HL_ANISOCL_TEST") || devid < 0)
return;
1598 const int region_w = 509;
1599 const int region_h = 371;
1600 const size_t region_pixels = (size_t)region_w * region_h;
1601 const float epsilon = 1e-6f;
1615 for(
int y = 0; y < region_h; y++)
1616 for(
int x = 0;
x < region_w;
x++)
1618 const size_t i = (size_t)y * region_w +
x;
1620 const float base = 0.6f + 0.25f * sinf(0.05f *
x + 0.08f * y) + 0.1f * cosf(0.021f * y);
1621 estimate[
i * 4 + 0] = 0.9f * base + 0.05f;
1622 estimate[
i * 4 + 1] = 1.1f * base + 0.02f;
1623 estimate[
i * 4 + 2] = 0.8f * base + 0.08f;
1624 estimate[
i * 4 + 3] = 0.f;
1625 const int delta_x =
x - region_w / 2;
1626 const int delta_y = y - region_h / 2;
1627 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1628 const int allclip = (
dist < 55.f);
1629 const int gclip = (
dist < 90.f);
1630 valid[
i * 4 + 0] = allclip ? 0.f : 1.f;
1631 valid[
i * 4 + 1] = gclip ? 0.f : 1.f;
1632 valid[
i * 4 + 2] = allclip ? 0.f : 1.f;
1633 valid[
i * 4 + 3] = gclip ? 0.f : 1.f;
1634 for(
int k = 0;
k < 4;
k++) clip0[
i * 4 +
k] = 0.5f;
1636 for(
int c = 0; c < 3; c++) estimate[
i * 4 + c] = 1.6f + 0.1f * c;
1638 memcpy(estimate_gpu, estimate, region_pixels * 4 *
sizeof(
float));
1642 for(
size_t i = 0;
i < region_pixels;
i++)
1644 const int all_clip = (valid[
i * 4 + 0] < 0.5f && valid[
i * 4 + 1] < 0.5f && valid[
i * 4 + 2] < 0.5f);
1645 for(
int c = 0; c < 4; c++) prev[
i * 4 + c] = all_clip ? valid[
i * 4 + c] : fmaxf(valid[
i * 4 + c], 0.6f);
1647 for(
size_t i = 0;
i < region_pixels;
i++)
1649 const float pixel_lum = fmaxf(estimate[
i * 4 + 0] + estimate[
i * 4 + 1] + estimate[
i * 4 + 2], epsilon);
1651 for(
int c = 0; c < 3; c++) chroma[
i * 4 + c] = estimate[
i * 4 + c] / pixel_lum;
1655 fprintf(stderr,
"[hl aniso-cl selftest] CPU div solve failed, aborting\n");
1661 float *
const restrict tensor_xx = planes + 0 * region_pixels;
1662 float *
const restrict tensor_xy = planes + 1 * region_pixels;
1663 float *
const restrict tensor_yy = planes + 2 * region_pixels;
1664 float *
const restrict tensor_scale = planes + 3 * region_pixels;
1670 if(solve_u && obstacle && scratch && hole_flag)
1674 int box_x0 = region_w;
1675 int box_y0 = region_h;
1678 for(
int y = 0; y < region_h; y++)
1679 for(
int x = 0;
x < region_w;
x++)
1681 const size_t i = (size_t)y * region_w +
x;
1682 hole_flag[
i] = (prev[
i * 4 + 0] < 0.5f && prev[
i * 4 + 1] < 0.5f && prev[
i * 4 + 2] < 0.5f);
1685 box_x0 =
MIN(box_x0,
x);
1686 box_x1 =
MAX(box_x1,
x);
1687 box_y0 =
MIN(box_y0, y);
1688 box_y1 =
MAX(box_y1, y);
1693 int active[3] = { 0, 0, 0 };
1694 for(
size_t i = 0;
i < region_pixels;
i++)
1696 if(!hole_flag[
i])
continue;
1697 const float inv_lum = 1.f / fmaxf(
luminance[
i], epsilon);
1698 for(
int c = 0; c < 3; c++) active[c] |= (chroma[
i * 4 + c] <= clip0[
i * 4 + c] * inv_lum * 1.001f);
1701 if(box_x1 >= box_x0)
1702 for(
int c = 0; c < 3; c++)
1704 if(!active[c])
continue;
1705 for(
size_t i = 0;
i < region_pixels;
i++)
1707 solve_u[
i] = chroma[
i * 4 + c];
1708 obstacle[
i] = clip0[
i * 4 + c] / fmaxf(
luminance[
i], epsilon);
1710 _aniso_iterate_obs(solve_u, obstacle, hole_flag, tensor_xx, tensor_xy, tensor_yy, scratch, region_w,
1711 region_h, 60, box_x0, box_y0, box_x1, box_y1);
1712 for(
size_t i = 0;
i < region_pixels;
i++) chroma[
i * 4 + c] = solve_u[
i];
1721 for(
size_t i = 0;
i < region_pixels;
i++)
1723 const float ratio_sum = fmaxf(chroma[
i * 4 + 0] + chroma[
i * 4 + 1] + chroma[
i * 4 + 2], epsilon);
1724 for(
int c = 0; c < 3; c++)
1725 if(prev[
i * 4 + c] < 0.5f)
1727 const float ratio_c = fmaxf(chroma[
i * 4 + c], 0.f);
1730 const float clip_floor = clip0[
i * 4 + c];
1731 const float diff =
value - clip_floor;
1732 const float soft_width = 0.02f * fmaxf(clip_floor, 1e-6f);
1733 estimate[
i * 4 + c] = clip_floor + 0.5f * (diff + sqrtf(diff * diff + soft_width * soft_width));
1743 float max_diff = -1.f;
1744 if(dest && dvld && dclip
1751 && _aniso_stage_cl(devid, gd_void, dest, dvld, dclip, region_w, region_h, 55.f, pipe) == CL_SUCCESS
1757 for(
size_t i = 0;
i < region_pixels;
i++)
1758 for(
int c = 0; c < 3; c++)
1759 max_diff = fmaxf(max_diff, fabsf(estimate_gpu[
i * 4 + c] - estimate[
i * 4 + c]));
1761 fprintf(stderr,
"[hl aniso-cl selftest] %dx%d all-clip disc textured max|gpu-cpu|=%.3e\n", region_w, region_h,
1781 static int done = 0;
1782 if(done || !getenv(
"HL_REGCL_TEST") || devid < 0)
return;
1785 const int width = 700;
1795 const float radii[3] = { 60.f, 75.f, 50.f };
1796 for(
int y = 0; y <
height; y++)
1799 const size_t i = (size_t)y *
width +
x;
1800 const float base = 0.5f + 0.3f * sinf(0.013f *
x) * cosf(0.011f * y) + 0.1f * cosf(0.03f *
x);
1801 const float gain[3] = { 0.9f, 1.15f, 0.75f };
1802 const int center_x =
width - 80;
1803 const int center_y =
height - 70;
1804 const int delta_x =
x - center_x;
1805 const int delta_y = y - center_y;
1806 const float dist = sqrtf((
float)(delta_x * delta_x + delta_y * delta_y));
1807 const int occluder = (y > center_y - 8 && y < center_y + 8);
1809 for(
int c = 0; c < 3; c++)
1811 const int clipped = (
dist < radii[c]) && !occluder;
1812 mask[
i * 4 + c] = clipped ? 1.f : 0.f;
1813 interp[
i * 4 + c] = clipped ? 0.62f * gain[c] : fmaxf(base * gain[c] * (occluder ? 0.15f : 1.f), 0.f);
1814 any_clip |= clipped;
1816 mask[
i * 4 + 3] = any_clip ? 1.f : 0.f;
1817 interp[
i * 4 + 3] = interp[
i * 4 + 0] + interp[
i * 4 + 1] + interp[
i * 4 + 2];
1818 depth[
i] = fmaxf(radii[1] -
dist, 0.f);
1820 memcpy(interp_gpu, interp, n_pixels * 4 *
sizeof(
float));
1833 const float solid_color = 0.3f;
1841 float max_diff = -1.f;
1842 if(interp_device && mask_device && depth_device
1850 && _region_guided_filter_cl(devid, gd_void, interp_device, mask_device, depth_device,
width, ®ion, pipe,
1858 double sum_diff = 0.0;
1860 for(
size_t i = 0;
i < n_pixels;
i++)
1861 for(
int c = 0; c < 3; c++)
1863 const float diff = fabsf(interp_gpu[
i * 4 + c] - interp[
i * 4 + c]);
1864 max_diff = fmaxf(max_diff, diff);
1865 sum_diff += (
double)diff;
1866 if(diff > 1e-4f) n_big++;
1868 fprintf(stderr,
"[hl region-cl selftest] mean=%.3e npix>1e-4: %zu/%zu\n", sum_diff / (
double)(n_pixels * 3),
1869 n_big, n_pixels * 3);
1871 fprintf(stderr,
"[hl region-cl selftest] %dx%d staggered blob r=%g max|gpu-cpu|=%.3e\n",
width,
height,
1872 region.
radius, max_diff);
1887 static int done_ = 0;
1888 if(done_ || !getenv(
"HL_KNEECL_TEST") || devid < 0)
return;
1891 const size_t width = 1462;
1892 const size_t height = 1034;
1894 const uint32_t filters = 0x94949494u;
1905 for(
size_t j = 0; j <
width; j++)
1907 const int c =
FC(
i, j, filters);
1908 const float base = 0.55f + 0.45f * sinf(0.006f * j) * cosf(0.008f *
i) + 0.12f * sinf(0.03f * (
i + j));
1909 const float gain[3] = { 0.95f, 1.05f, 0.85f };
1910 float value = fmaxf(base * gain[c > 2 ? 1 : c], 0.f);
1922 float curve_diff = -1.f;
1923 float apply_diff = -1.f;
1925 if(in_device && out_device
1928 &&
_hl_knee_estimate_cl(devid, gd_void, in_device,
width,
height, filters, &roi_in, NULL, 0, clipraw,
1932 engaged_ok = (curve_cpu[0].
engaged == curve_gpu[0].
engaged) && (curve_cpu[1].engaged == curve_gpu[1].engaged)
1935 for(
int c = 0; c < 3; c++)
1937 curve_diff = fmaxf(curve_diff, fabsf(curve_cpu[c].lift[
i] - curve_gpu[c].lift[
i]));
1941 if(
_hl_knee_apply_cfa_cl(devid, gd_void, in_device, out_device,
width,
height, filters, &roi_in, NULL, 0,
1948 for(
size_t i = 0;
i < n_pixels;
i++) apply_diff = fmaxf(apply_diff, fabsf(corr_gpu[
i] - corr_cpu[
i]));
1952 "[hl knee-cl selftest] %zux%zu RGGB engaged cpu=[%d %d %d] match=%d "
1953 "max|curve dcpu-gpu|=%.3e max|apply gpu-cpu|=%.3e\n",
1954 width,
height, curve_cpu[0].engaged, curve_cpu[1].engaged, curve_cpu[2].engaged, engaged_ok,
1955 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)
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)
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)
#define dt_pixelpipe_cache_alloc_align(size, pipe)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
static const dt_aligned_pixel_simd_t value
#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 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
float dt_aligned_pixel_t[4]
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)
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)
#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 _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)
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)
#define DT_HL_DOME_NMAX_SPARSE
int kernel_hl_cf_pack_joint
Region of interest passed through the pixelpipe.
typedef double((*spd)(unsigned long int wavelength, double TempK))