203 gboolean *
const cache_output,
214 double gpu_in_borrow_ms = 0.0;
215 double gpu_out_alloc_ms = 0.0;
216 double gpu_in_prepare_ms = 0.0;
217 double gpu_out_cl_ms = 0.0;
218 double gpu_cst_ms = 0.0;
219 gboolean gpu_out_cl_reused =
FALSE;
224 void *cl_mem_input = NULL;
225 void *cl_mem_output = NULL;
226 void *cl_mem_process_input = NULL;
227 void *cl_mem_blend_input = NULL;
228 void *cl_mem_blend_output = NULL;
229 void *cl_mem_process_input_temp = NULL;
230 void *cl_mem_blend_input_temp = NULL;
231 void *cl_mem_blend_output_temp = NULL;
234 gboolean borrowed_cl_mem_input =
FALSE;
247 actual_input_dsc.
bpp);
249 gpu_in_borrow_ms = (g_get_monotonic_time() - borrow_t0) / 1000.0;
250 borrowed_cl_mem_input = (!
IS_NULL_PTR(cl_mem_input));
266 &borrowed_cl_mem_input,
piece, previous_piece,
tiling,
267 pixelpipe_flow, cache_output,
268 input_entry, output_entry);
276 const float required_factor_cl
283 size_t fit_needed = 0, fit_limit = 0;
287 required_factor_cl,
tiling->overhead, &fit_needed, &fit_limit);
292 "[dev_pixelpipe] %s pre-check didn't fit on device, flushing cached pinned buffers and retrying\n",
297 required_factor_cl,
tiling->overhead, &fit_needed, &fit_limit);
302 && (
module->flags() & IOP_FLAGS_PREVIEW_NON_OPENCL))
303 && (fits_on_device || piece->process_tiling_ready);
305 if(!possible_cl || !fits_on_device) *cache_output =
TRUE;
311 gpu_out_alloc_ms = (g_get_monotonic_time() - alloc_t0) / 1000.0;
315 if(possible_cl && !fits_on_device)
319 / (
sizeof(float) *
MAX(
piece->dsc_in.bpp,
piece->dsc_out.bpp)
320 * ceilf(required_factor_cl));
321 const float dx =
MAX(
piece->roi_in.width,
piece->roi_out.width);
322 const float dy =
MAX(
piece->roi_in.height,
piece->roi_out.height);
323 const float border =
tiling->overlap + 1;
324 const gboolean possible = (cl_px > dx * border) || (cl_px > dy * border) || (cl_px > border * border);
328 "[dt_dev_pixelpipe_process_rec] CL: tiling impossible in module `%s'. avail=%.1fM, requ=%.1fM (%ix%i). overlap=%i\n",
329 module->name(), cl_px / 1e6f, dx * dy / 1e6f, (
int)dx, (
int)dy, (
int)
tiling->overlap);
336 input_entry, output_entry))
340 if(!possible_cl)
goto error;
348 &
piece->roi_in,
piece->dsc_in.bpp, input_entry,
349 &locked_input_entry, NULL))
352 gpu_in_prepare_ms = (g_get_monotonic_time() - inprep_t0) / 1000.0;
354 cl_mem_process_input = cl_mem_input;
364 "output", output_entry,
365 &gpu_out_cl_reused, cl_mem_input);
367 gpu_out_cl_ms = (g_get_monotonic_time() - outcl_t0) / 1000.0;
370 const int cst_before_cl = process_input_dsc.
cst;
372 if(process_input_dsc.
cst !=
piece->dsc_in.cst
376 module,
"module input colorspace temp",
383 process_input_dsc.
cst,
piece->dsc_in.cst,
384 &process_input_dsc.
cst, work_profile))
386 cl_mem_process_input = cl_mem_process_input_temp;
388 else if(process_input_dsc.
cst !=
piece->dsc_in.cst)
390 process_input_dsc.
cst =
piece->dsc_in.cst;
393 gpu_cst_ms = (g_get_monotonic_time() - cst_t0) / 1000.0;
394 const int cst_after_cl = process_input_dsc.
cst;
398 process_input_dsc.
bpp,
piece->dsc_out.bpp,
399 cst_before_cl, cst_after_cl);
402 if(!module->process_cl(module,
pipe,
piece, cl_mem_process_input, cl_mem_output))
406 "[dev_pixelpipe] %s gpu prologue=%.2f ms"
407 " (inbuf=%.2f outalloc=%.2f inprep=%.2f outcl=%.2f cst=%.2f) process_cl=%.2f ms"
408 " (in %dx%d bpp=%" G_GSIZE_FORMAT
" -> out bpp=%" G_GSIZE_FORMAT
409 " cache_out=%d outcl_reused=%d host=%p)\n",
410 module->op, (gpu_prologue_end - gpu_stage_t0) / 1000.0,
411 gpu_in_borrow_ms, gpu_out_alloc_ms, gpu_in_prepare_ms, gpu_out_cl_ms, gpu_cst_ms,
412 (g_get_monotonic_time() - gpu_prologue_end) / 1000.0,
414 *cache_output ? 1 : 0, gpu_out_cl_reused ? 1 : 0, output);
431 cl_mem_blend_input = cl_mem_process_input;
432 cl_mem_blend_output = cl_mem_output;
433 blend_input_dsc = process_input_dsc;
434 blend_output_dsc =
piece->dsc_out;
439 const int blend_in_before = blend_input_dsc.
cst;
443 module,
"blend input colorspace temp",
444 cl_mem_process_input);
449 cl_mem_process_input, cl_mem_blend_input_temp,
451 blend_input_dsc.
cst, blend_cst,
452 &blend_input_dsc.
cst, work_profile);
453 cl_mem_blend_input = cl_mem_blend_input_temp;
455 const int blend_in_after = blend_input_dsc.
cst;
457 &process_input_dsc, &blend_input_dsc,
459 process_input_dsc.
bpp, blend_input_dsc.
bpp,
460 blend_in_before, blend_in_after);
461 const int blend_out_before = blend_output_dsc.
cst;
465 piece->dsc_out.bpp, module,
466 "blend output colorspace temp", cl_mem_output);
471 cl_mem_blend_output_temp,
piece->roi_out.width,
472 piece->roi_out.height, blend_output_dsc.
cst, blend_cst,
473 &blend_output_dsc.
cst, work_profile);
474 cl_mem_blend_output = cl_mem_blend_output_temp;
476 const int blend_out_after = blend_output_dsc.
cst;
478 &
piece->dsc_out, &blend_output_dsc,
480 piece->dsc_out.bpp, blend_output_dsc.
bpp,
481 blend_out_before, blend_out_after);
498 "[blend] %s transforms_in+out=%.2f ms kernel=%.2f ms mask_mode=%u transforms=%d\n",
499 module->op, (blend_pre - blend_t0) / 1000.0,
500 (g_get_monotonic_time() - blend_pre) / 1000.0,
501 bp ? bp->
mask_mode : 0u, (int)blend_transforms);
507 cl_mem_output,
piece->roi_out.width,
508 piece->roi_out.height, blend_output_dsc.
cst,
509 piece->dsc_out.cst, &blend_output_dsc.
cst,
521 piece->dsc_out.bpp, module,
533 dt_print(
DT_DEBUG_PERF,
"[dev_pixelpipe] %s output readback %dx%d bpp=%" G_GSIZE_FORMAT
" took %.2f ms\n",
534 module->op,
piece->roi_out.width,
piece->roi_out.height,
piece->dsc_out.bpp,
535 (g_get_monotonic_time() - readback_t0) / 1000.0);
543 const float *module_input = input;
544 const float *blend_input = input;
545 float *module_input_temp = NULL;
546 float *blend_input_temp = NULL;
547 gboolean input_locked =
FALSE;
549 if(borrowed_cl_mem_input)
553 borrowed_cl_mem_input =
FALSE;
559 if(process_input_dsc.
cst !=
piece->dsc_in.cst
570 piece->roi_in.height, process_input_dsc.
cst,
piece->dsc_in.cst,
571 &process_input_dsc.
cst, work_profile);
573 input_locked =
FALSE;
574 module_input = module_input_temp;
576 else if(process_input_dsc.
cst !=
piece->dsc_in.cst)
578 process_input_dsc.
cst =
piece->dsc_in.cst;
588 int fail = !
module->process_tiling_cl(module, pipe, piece, module_input, output, piece->dsc_in.bpp);
602 blend_input = module_input;
603 blend_input_dsc = process_input_dsc;
604 void *blend_output = output;
605 blend_output_dsc =
piece->dsc_out;
626 piece->roi_in.height, blend_input_dsc.
cst, blend_cst,
627 &blend_input_dsc.
cst, work_profile);
628 blend_input = blend_input_temp;
632 input_locked =
FALSE;
638 float *blend_output_temp
650 piece->roi_out.height, blend_output_dsc.
cst, blend_cst,
651 &blend_output_dsc.
cst, work_profile);
652 blend_output = blend_output_temp;
665 piece->roi_out.height, blend_output_dsc.
cst,
piece->dsc_out.cst,
666 &blend_output_dsc.
cst, work_profile);
671 if(blend_output != output)
685 if(locked_input_entry)
691 if(borrowed_cl_mem_input)
695 borrowed_cl_mem_input =
FALSE;
722 if(locked_input_entry)
732 if(borrowed_cl_mem_input)
758 " MiB but the largest allocation the device allows is %" G_GSIZE_FORMAT
759 " MiB; falling back to CPU"),
760 module->name(), (
size_t)(fit_needed / (1024 * 1024)),
761 (
size_t)(fit_limit / (1024 * 1024)));
765 " MiB but only %" G_GSIZE_FORMAT
" MiB are free on the device; falling back to CPU"),
766 module->name(), (
size_t)(fit_needed / (1024 * 1024)),
767 (
size_t)(fit_limit / (1024 * 1024)));
770 dt_pipeline_message(_(
"OpenCL failed for module `%s`: image dimensions %" G_GSIZE_FORMAT
"x%" G_GSIZE_FORMAT
771 " exceed the device limits; falling back to CPU"),
772 module->name(), precheck_width, precheck_height);
775 dt_pipeline_message(_(
"OpenCL failed for module `%s`; falling back to CPU"), module->name());
779 cache_output, cpu_input_entry, output_entry);
785 "[dev_pixelpipe] %s GPU error fallback will reuse host input\n",
791 cpu_input_entry, output_entry))
793 if(borrowed_cl_mem_input)
797 borrowed_cl_mem_input =
FALSE;
808 "[dev_pixelpipe] %s CPU fallback has no input buffer (cache allocation failed?)\n",
813 if(borrowed_cl_mem_input)
823 cache_output, cpu_input_entry, output_entry);