Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
pixelpipe_hb.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2016 johannes hanika.
4 Copyright (C) 2010-2012 Henrik Andersson.
5 Copyright (C) 2011 Bruce Guenter.
6 Copyright (C) 2011 Robert Bieber.
7 Copyright (C) 2011 Rostyslav Pidgornyi.
8 Copyright (C) 2011-2017, 2019 Ulrich Pegelow.
9 Copyright (C) 2012, 2021 Aldric Renaudin.
10 Copyright (C) 2012 Richard Wonka.
11 Copyright (C) 2012-2019 Tobias Ellinghaus.
12 Copyright (C) 2013-2016 Roman Lebedev.
13 Copyright (C) 2013 Simon Spannagel.
14 Copyright (C) 2014, 2016 Pedro Côrte-Real.
15 Copyright (C) 2016 Matthieu Moy.
16 Copyright (C) 2017, 2019 luzpaz.
17 Copyright (C) 2018, 2020-2026 Aurélien PIERRE.
18 Copyright (C) 2018-2019 Edgardo Hoszowski.
19 Copyright (C) 2018-2022 Pascal Obry.
20 Copyright (C) 2019 Andreas Schneider.
21 Copyright (C) 2019-2022 Dan Torop.
22 Copyright (C) 2019-2022 Hanno Schwalm.
23 Copyright (C) 2019 Heiko Bauke.
24 Copyright (C) 2020 Chris Elston.
25 Copyright (C) 2020 Diederik Ter Rahe.
26 Copyright (C) 2020 GrahamByrnes.
27 Copyright (C) 2020-2021 Harold le Clément de Saint-Marcq.
28 Copyright (C) 2020-2021 Hubert Kowalski.
29 Copyright (C) 2020-2021 Ralf Brown.
30 Copyright (C) 2021 Sakari Kapanen.
31 Copyright (C) 2022 Martin Bařinka.
32 Copyright (C) 2022 Philipp Lutz.
33 Copyright (C) 2023-2024 Alynx Zhou.
34 Copyright (C) 2023 lologor.
35 Copyright (C) 2023 Luca Zulberti.
36 Copyright (C) 2024 Alban Gruin.
37 Copyright (C) 2024 tatu.
38 Copyright (C) 2025-2026 Guillaume Stutin.
39 Copyright (C) 2025 Miguel Moquillon.
40
41 darktable is free software: you can redistribute it and/or modify
42 it under the terms of the GNU General Public License as published by
43 the Free Software Foundation, either version 3 of the License, or
44 (at your option) any later version.
45
46 darktable is distributed in the hope that it will be useful,
47 but WITHOUT ANY WARRANTY; without even the implied warranty of
48 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49 GNU General Public License for more details.
50
51 You should have received a copy of the GNU General Public License
52 along with darktable. If not, see <http://www.gnu.org/licenses/>.
53*/
54#include "common/colorspaces.h"
55#include "common/darktable.h"
56#include "common/histogram.h"
57#include "common/imageio.h"
58#include "common/atomic.h"
59#include "common/opencl.h"
60#include "common/iop_order.h"
61#include "control/control.h"
62#include "control/conf.h"
63#include "control/signal.h"
64#include "develop/blend.h"
66#include "develop/format.h"
68#include "develop/pixelpipe.h"
73#include "develop/tiling.h"
74#include "develop/masks.h"
75#include "gui/gtk.h"
76#include "libs/colorpicker.h"
77#include "libs/lib.h"
79
80#include <assert.h>
81#include <inttypes.h>
82#include <math.h>
83#include <stdint.h>
84#include <stdlib.h>
85#include <string.h>
86#include <strings.h>
87#include <unistd.h>
88
91
92static void _trace_cache_owner(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module,
93 const char *phase, const char *slot, const uint64_t requested_hash,
94 const void *buffer, const dt_pixel_cache_entry_t *entry,
95 const gboolean verbose)
96{
97 if(!(darktable.unmuted & DT_DEBUG_PIPECACHE)) return;
98 if(!(darktable.unmuted & DT_DEBUG_VERBOSE)) return;
99
101 "[pixelpipe_owner] pipe=%s module=%s phase=%s slot=%s req=%" PRIu64
102 " entry=%" PRIu64 "/%" PRIu64 " refs=%i auto=%i data=%p buf=%p name=%s\n",
103 pipe ? dt_pixelpipe_get_pipe_name(pipe->type) : "-",
104 module ? module->op : "base",
105 phase ? phase : "-",
106 slot ? slot : "-",
107 requested_hash,
108 entry ? entry->hash : DT_PIXELPIPE_CACHE_HASH_INVALID,
109 entry ? entry->serial : 0,
110 entry ? dt_atomic_get_int((dt_atomic_int *)&entry->refcount) : -1,
111 entry ? entry->auto_destroy : -1,
112 entry ? entry->data : NULL,
113 buffer,
114 (entry && entry->name) ? entry->name : "-");
115}
116
117
118static void _trace_buffer_content(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module,
119 const char *phase, const void *buffer,
120 const dt_iop_buffer_dsc_t *format, const dt_iop_roi_t *roi)
121{
122 if(!(darktable.unmuted & DT_DEBUG_PIPECACHE)) return;
123 if(!(darktable.unmuted & DT_DEBUG_VERBOSE)) return;
124 if(IS_NULL_PTR(buffer) || IS_NULL_PTR(format) || IS_NULL_PTR(roi)) return;
125 if(roi->width <= 0 || roi->height <= 0) return;
126
127 const size_t pixels = (size_t)roi->width * (size_t)roi->height;
128 const unsigned int channels = format->channels;
129
130 if(format->datatype == TYPE_FLOAT && channels >= 1)
131 {
132 const float *in = (const float *)buffer;
133 float minv[4] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
134 float maxv[4] = { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX };
135 size_t nonfinite = 0;
136 size_t near_black = 0;
137
138 for(size_t k = 0; k < pixels; k++, in += channels)
139 {
140 gboolean finite = TRUE;
141 for(unsigned int c = 0; c < MIN(channels, 4U); c++)
142 {
143 if(!isfinite(in[c]))
144 {
145 finite = FALSE;
146 continue;
147 }
148 minv[c] = fminf(minv[c], in[c]);
149 maxv[c] = fmaxf(maxv[c], in[c]);
150 }
151
152 if(!finite)
153 {
154 nonfinite++;
155 continue;
156 }
157
158 const float energy = fabsf(in[0]) + ((channels > 1) ? fabsf(in[1]) : 0.0f)
159 + ((channels > 2) ? fabsf(in[2]) : 0.0f);
160 if(energy < 1e-6f) near_black++;
161 }
162
164 "[pixelpipe_stats] pipe=%s module=%s phase=%s type=float ch=%u roi=%dx%d "
165 "rgb_min=(%g,%g,%g) rgb_max=(%g,%g,%g) a_min=%g a_max=%g near_black=%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT " nonfinite=%" G_GSIZE_FORMAT "\n",
166 dt_pixelpipe_get_pipe_name(pipe->type), module->op, phase ? phase : "-",
167 channels, roi->width, roi->height,
168 minv[0], (channels > 1) ? minv[1] : 0.0f, (channels > 2) ? minv[2] : 0.0f,
169 maxv[0], (channels > 1) ? maxv[1] : 0.0f, (channels > 2) ? maxv[2] : 0.0f,
170 (channels > 3) ? minv[3] : 0.0f, (channels > 3) ? maxv[3] : 0.0f,
171 near_black, pixels, nonfinite);
172 }
173 else if(format->datatype == TYPE_UINT8 && channels >= 1)
174 {
175 const uint8_t *in = (const uint8_t *)buffer;
176 int minv[4] = { 255, 255, 255, 255 };
177 int maxv[4] = { 0, 0, 0, 0 };
178 size_t near_black = 0;
179
180 for(size_t k = 0; k < pixels; k++, in += channels)
181 {
182 for(unsigned int c = 0; c < MIN(channels, 4U); c++)
183 {
184 minv[c] = MIN(minv[c], in[c]);
185 maxv[c] = MAX(maxv[c], in[c]);
186 }
187
188 const int energy = in[0] + ((channels > 1) ? in[1] : 0) + ((channels > 2) ? in[2] : 0);
189 if(energy == 0) near_black++;
190 }
191
193 "[pixelpipe_stats] pipe=%s module=%s phase=%s type=u8 ch=%u roi=%dx%d "
194 "rgb_min=(%d,%d,%d) rgb_max=(%d,%d,%d) a_min=%d a_max=%d near_black=%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT "\n",
195 dt_pixelpipe_get_pipe_name(pipe->type), module->op, phase ? phase : "-",
196 channels, roi->width, roi->height,
197 minv[0], (channels > 1) ? minv[1] : 0, (channels > 2) ? minv[2] : 0,
198 maxv[0], (channels > 1) ? maxv[1] : 0, (channels > 2) ? maxv[2] : 0,
199 (channels > 3) ? minv[3] : 0, (channels > 3) ? maxv[3] : 0,
200 near_black, pixels);
201 }
202}
203
205 dt_iop_module_t *module, const uint64_t input_hash,
206 const void *input, dt_pixel_cache_entry_t *input_entry,
207 const uint64_t output_hash, void **output,
208 void **cl_mem_output, dt_pixel_cache_entry_t *output_entry)
209{
210 _trace_cache_owner(pipe, module, "shutdown-drop", "input", input_hash, input, input_entry, FALSE);
211 _trace_cache_owner(pipe, module, "shutdown-drop", "output", output_hash,
212 output ? *output : NULL, output_entry, FALSE);
213
215
216 if(!IS_NULL_PTR(input_entry))
217 {
220 }
221
222 if(!IS_NULL_PTR(output_entry))
223 {
225
228 }
229
230 if(output) *output = NULL;
231
232 if(!IS_NULL_PTR(*cl_mem_output))
233 dt_dev_pixelpipe_cache_release_cl_buffer(cl_mem_output, NULL, NULL, FALSE);
234
235 return 1;
236}
237
238static inline gboolean _is_focused_realtime_gui_module(const dt_dev_pixelpipe_t *pipe,
239 const dt_develop_t *dev,
240 const dt_iop_module_t *module)
241{
242 return (pipe->type == DT_DEV_PIXELPIPE_FULL || pipe->type == DT_DEV_PIXELPIPE_PREVIEW)
243 && pipe->realtime && dev && module && dev->gui_module == module;
244}
245
246
248 const dt_pixel_cache_entry_t *cache_entry)
249{
250 return (pipe->realtime
251 || (cache_entry && IS_NULL_PTR(dt_pixel_cache_entry_get_data((dt_pixel_cache_entry_t *)cache_entry)))
252 || !_bypass_cache(pipe, NULL));
253}
254
256{
257 char *r = NULL;
258
259 switch(pipe_type)
260 {
262 r = _("preview");
263 break;
265 r = _("full");
266 break;
268 r = _("thumbnail");
269 break;
271 r = _("export");
272 break;
273 default:
274 r = _("invalid");
275 }
276 return r;
277}
278
279
280inline static void _uint8_to_float(const uint8_t *const input, float *const output,
281 const size_t width, const size_t height, const size_t chan)
282{
283 __OMP_FOR_SIMD__(aligned(input, output: 64) )
284 for(size_t k = 0; k < height * width; k++)
285 {
286 const size_t index = k * chan;
287 // Warning: we take BGRa and put it back into RGBa
288 output[index + 0] = (float)input[index + 2] / 255.f;
289 output[index + 1] = (float)input[index + 1] / 255.f;
290 output[index + 2] = (float)input[index + 0] / 255.f;
291 output[index + 3] = 0.f;
292 }
293}
294
295static const char *_debug_cst_to_string(const int cst)
296{
297 switch(cst)
298 {
299 case IOP_CS_RAW:
300 return "raw";
301 case IOP_CS_LAB:
302 return "lab";
303 case IOP_CS_RGB:
304 return "rgb";
306 return "display-rgb";
307 case IOP_CS_LCH:
308 return "lch";
309 case IOP_CS_HSL:
310 return "hsl";
311 case IOP_CS_JZCZHZ:
312 return "jzczhz";
313 case IOP_CS_NONE:
314 return "none";
315 default:
316 return "unknown";
317 }
318}
319
321{
322 switch(type)
323 {
324 case TYPE_FLOAT:
325 return "float";
326 case TYPE_UINT16:
327 return "uint16";
328 case TYPE_UINT8:
329 return "uint8";
330 case TYPE_UNKNOWN:
331 default:
332 return "unknown";
333 }
334}
335
337 const gboolean is_cl,
338 const dt_iop_buffer_dsc_t *in_dsc, const dt_iop_buffer_dsc_t *out_dsc,
339 const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out,
340 const size_t in_bpp, const size_t out_bpp,
341 const int cst_before, const int cst_after)
342{
343 if(!(darktable.unmuted & DT_DEBUG_PIPE)) return;
344 if(!(darktable.unmuted & DT_DEBUG_VERBOSE)) return;
345 const char *module_name = module ? module->op : "base";
346 const char *pipe_name = dt_pixelpipe_get_pipe_name(pipe->type);
347 const char *stage_name = stage ? stage : "process";
348
349 if(!IS_NULL_PTR(in_dsc) && !IS_NULL_PTR(out_dsc))
350 {
352 "[pixelpipe] %s %s %s %s: in cst=%s->%s ch=%d type=%s bpp=%" G_GSIZE_FORMAT " roi=%dx%d | "
353 "out cst=%s ch=%d type=%s bpp=%" G_GSIZE_FORMAT " roi=%dx%d\n",
354 pipe_name, module_name, is_cl ? "cl" : "cpu", stage_name,
355 _debug_cst_to_string(cst_before), _debug_cst_to_string(cst_after),
356 in_dsc->channels, _debug_type_to_string(in_dsc->datatype), in_bpp,
357 roi_in ? roi_in->width : 0, roi_in ? roi_in->height : 0,
358 _debug_cst_to_string(out_dsc->cst), out_dsc->channels, _debug_type_to_string(out_dsc->datatype),
359 out_bpp, roi_out ? roi_out->width : 0, roi_out ? roi_out->height : 0);
360 }
361 else if(!IS_NULL_PTR(out_dsc))
362 {
364 "[pixelpipe] %s %s %s %s: out cst=%s ch=%d type=%s bpp=%" G_GSIZE_FORMAT " roi=%dx%d\n",
365 pipe_name, module_name, is_cl ? "cl" : "cpu", stage_name,
366 _debug_cst_to_string(out_dsc->cst), out_dsc->channels, _debug_type_to_string(out_dsc->datatype),
367 out_bpp, roi_out ? roi_out->width : 0, roi_out ? roi_out->height : 0);
368 }
369}
370
371
372int dt_dev_pixelpipe_init_export(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, int levels, gboolean store_masks)
373{
374 const int res = dt_dev_pixelpipe_init_cached(pipe);
377 pipe->levels = levels;
378 pipe->store_all_raster_masks = store_masks;
379 pipe->dev = dev;
380 return res;
381}
382
384{
385 const int res = dt_dev_pixelpipe_init_cached(pipe);
387 pipe->no_cache = TRUE;
388 pipe->dev = dev;
389 return res;
390}
391
393{
394 const int res = dt_dev_pixelpipe_init_cached(pipe);
396 pipe->no_cache = TRUE;
397 pipe->dev = dev;
398 return res;
399}
400
402{
403 // Init with the size of MIPMAP_F
404 const int res = dt_dev_pixelpipe_init_cached(pipe);
407
408 // Needed for caching
410 pipe->dev = dev;
411 return res;
412}
413
415{
416 const int res = dt_dev_pixelpipe_init_cached(pipe);
418
419 // Needed for caching
421 pipe->dev = dev;
422 return res;
423}
424
426{
427 // Set everything to 0 = NULL = FALSE
428 memset(pipe, 0, sizeof(dt_dev_pixelpipe_t));
429
430 // Set only the stuff that doesn't take 0 as default
431 pipe->devid = -1;
435 dt_dev_set_backbuf(&pipe->backbuf, 0, 0, 0, -1, -1);
438
440 pipe->iscale = 1.0f;
444
446 dt_pthread_mutex_init(&(pipe->busy_mutex), NULL);
447
450
452 return 1;
453}
454
456{
457 if(IS_NULL_PTR(pipe)) return;
459}
460
462{
463 return pipe ? dt_atomic_get_int((dt_atomic_int *)&pipe->realtime) : FALSE;
464}
465
466void dt_dev_pixelpipe_set_input(dt_dev_pixelpipe_t *pipe, int32_t imgid, int width, int height,
468{
469 pipe->iwidth = width;
470 pipe->iheight = height;
471 pipe->iscale = iscale;
472 pipe->imgid = imgid;
473 pipe->dev->image_storage = pipe->dev->image_storage;
474 pipe->size = size;
475}
476
478 const gchar *icc_filename, dt_iop_color_intent_t icc_intent)
479{
480 pipe->icc_type = icc_type;
481 dt_free(pipe->icc_filename);
482 pipe->icc_filename = g_strdup(icc_filename ? icc_filename : "");
483 pipe->icc_intent = icc_intent;
484}
485
487{
488 /* Device-side cache payloads are only an acceleration layer. Once darkroom
489 * leaves and all pipe workers are quiescent, drop all cached cl_mem objects
490 * so a later reopen can only exact-hit host-authoritative cachelines. */
492
493 // blocks while busy and sets shutdown bit:
495 // so now it's safe to clean up cache:
496 const uint64_t old_backbuf_hash = dt_dev_backbuf_get_hash(&pipe->backbuf);
497 if(old_backbuf_hash != DT_PIXELPIPE_CACHE_HASH_INVALID)
498 {
499 /* Backbuffer ownership belongs to the pipeline, not its GUI consumers. Once the pipe itself is
500 * torn down, always release that keepalive ref and invalidate the published backbuffer metadata. */
502
503 if(pipe->no_cache)
504 {
505 dt_pixel_cache_entry_t *old_backbuf_entry
507 if(old_backbuf_entry)
508 {
511 }
512 }
513 }
518 dt_free(pipe->icc_filename);
519
521
523
524 if(pipe->forms)
525 {
526 g_list_free_full(pipe->forms, (void (*)(void *))dt_masks_free_form);
527 pipe->forms = NULL;
528 }
529}
530
531
533{
535 {
536 pipe->reentry = TRUE;
537 pipe->reentry_hash = hash;
538 dt_print(DT_DEBUG_DEV, "[dev_pixelpipe] re-entry flag set for %" PRIu64 "\n", hash);
539 return TRUE;
540 }
541
542 return FALSE;
543}
544
545
547{
548 if(pipe->reentry_hash == hash)
549 {
550 pipe->reentry = FALSE;
552 dt_print(DT_DEBUG_DEV, "[dev_pixelpipe] re-entry flag unset for %" PRIu64 "\n", hash);
553 return TRUE;
554 }
555
556 return FALSE;
557}
558
560{
561 return pipe->reentry;
562}
563
570
572{
573 // destroy all nodes
574 for(GList *nodes = g_list_first(pipe->nodes); nodes; nodes = g_list_next(nodes))
575 {
577 if(IS_NULL_PTR(piece)) continue;
578 // printf("cleanup module `%s'\n", piece->module->name());
579 if(piece->module) dt_iop_cleanup_pipe(piece->module, pipe, piece);
581 dt_free(piece);
582 }
583 g_list_free(pipe->nodes);
584 pipe->nodes = NULL;
585 // and iop order
586 g_list_free_full(pipe->iop_order_list, dt_free_gpointer);
587 pipe->iop_order_list = NULL;
589}
590
592{
593 // check that the pipe was actually properly cleaned up after the last run
594 g_assert(IS_NULL_PTR(pipe->nodes));
595 g_assert(IS_NULL_PTR(pipe->iop_order_list));
597
598 // for all modules in dev:
599 for(GList *modules = g_list_first(pipe->dev->iop); modules; modules = g_list_next(modules))
600 {
601 dt_iop_module_t *module = (dt_iop_module_t *)modules->data;
603 if(IS_NULL_PTR(piece)) continue;
604 piece->enabled = module->enabled;
605 piece->request_histogram = DT_REQUEST_ONLY_IN_GUI;
606 piece->histogram_params.bins_count = 256;
607 piece->iwidth = pipe->iwidth;
608 piece->iheight = pipe->iheight;
609 piece->module = module;
611 piece->blendop_hash = DT_PIXELPIPE_CACHE_HASH_INVALID;
612 piece->global_hash = DT_PIXELPIPE_CACHE_HASH_INVALID;
613 piece->global_mask_hash = DT_PIXELPIPE_CACHE_HASH_INVALID;
615 piece->cache_output_on_ram = TRUE;
616 piece->raster_masks = dt_pixelpipe_raster_alloc();
617
618 // dsc_mask is static, single channel float image
619 piece->dsc_mask.channels = 1;
620 piece->dsc_mask.datatype = TYPE_FLOAT;
621 dt_iop_buffer_dsc_update_bpp(&piece->dsc_mask);
622
623 dt_iop_init_pipe(piece->module, pipe, piece);
624
625 pipe->nodes = g_list_append(pipe->nodes, piece);
626 }
627}
628
630 const dt_dev_pixelpipe_iop_t *const piece,
631 const dt_iop_buffer_dsc_t *const output_dsc)
632{
637
638 const dt_iop_colorspace_type_t blend_cst = dt_develop_blend_colorspace(piece, output_dsc->cst);
640 if(piece->dsc_in.cst != blend_cst
643 if(output_dsc->cst != blend_cst
644 && !(dt_iop_colorspace_is_rgb(output_dsc->cst) && dt_iop_colorspace_is_rgb(blend_cst)))
646
647 return transforms;
648}
649
650#define KILL_SWITCH_ABORT \
651 if(dt_dev_pixelpipe_has_shutdown(pipe)) \
652 { \
653 if(!IS_NULL_PTR(cl_mem_output)) \
654 { \
655 dt_dev_pixelpipe_cache_release_cl_buffer(&cl_mem_output, NULL, NULL, FALSE); \
656 } \
657 return 1; \
658 }
659
660// Once we have a cache, stopping computation before full completion
661// has good chances of leaving it corrupted. So we invalidate it.
662#define KILL_SWITCH_AND_FLUSH_CACHE \
663 if(dt_dev_pixelpipe_has_shutdown(pipe)) \
664 { \
665 return _abort_module_shutdown_cleanup(pipe, piece, module, input_hash, input, input_entry, hash, &output, \
666 &cl_mem_output, output_entry); \
667 }
668
669static void _print_perf_debug(dt_dev_pixelpipe_t *pipe, const dt_pixelpipe_flow_t pixelpipe_flow,
671 const gboolean recycled_output_cacheline, dt_times_t *start)
672{
673 char histogram_log[32] = "";
674 if(!(pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_NONE))
675 {
676 snprintf(histogram_log, sizeof(histogram_log), ", collected histogram on %s",
677 (pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_ON_GPU
678 ? "GPU"
679 : pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_ON_CPU ? "CPU" : ""));
680 }
681
682 gchar *module_label = dt_history_item_get_name(module);
684 start, "[dev_pixelpipe]", "processed `%s' on %s%s%s%s, blended on %s [%s]", module_label,
685 pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_ON_GPU
686 ? "GPU"
687 : pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_ON_CPU ? "CPU" : "",
688 pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_WITH_TILING ? " with tiling" : "",
689 recycled_output_cacheline ? ", recycled cacheline" : "",
690 (!(pixelpipe_flow & PIXELPIPE_FLOW_HISTOGRAM_NONE) && (piece->request_histogram & DT_REQUEST_ON))
691 ? histogram_log
692 : "",
693 pixelpipe_flow & PIXELPIPE_FLOW_BLENDED_ON_GPU
694 ? "GPU"
695 : pixelpipe_flow & PIXELPIPE_FLOW_BLENDED_ON_CPU ? "CPU" : "",
697 dt_free(module_label);
698}
699
700
701static void _print_nan_debug(dt_dev_pixelpipe_t *pipe, void *cl_mem_output, void *output,
702 const dt_iop_roi_t *roi_out, dt_iop_buffer_dsc_t *out_format,
703 dt_iop_module_t *module)
704{
705 if(!(darktable.unmuted & DT_DEBUG_NAN)) return;
706 if(!(darktable.unmuted & DT_DEBUG_VERBOSE)) return;
707 if((darktable.unmuted & DT_DEBUG_NAN) && strcmp(module->op, "gamma") != 0)
708 {
709 gchar *module_label = dt_history_item_get_name(module);
710
711 if(out_format->datatype == TYPE_FLOAT && out_format->channels == 4)
712 {
713 int hasinf = 0, hasnan = 0;
714 dt_aligned_pixel_t min = { FLT_MAX };
715 dt_aligned_pixel_t max = { FLT_MIN };
716
717 for(int k = 0; k < 4 * roi_out->width * roi_out->height; k++)
718 {
719 if((k & 3) < 3)
720 {
721 float f = ((float *)(output))[k];
722 if(isnan(f))
723 hasnan = 1;
724 else if(!isfinite(f))
725 hasinf = 1;
726 else
727 {
728 min[k & 3] = fmin(f, min[k & 3]);
729 max[k & 3] = fmax(f, max[k & 3]);
730 }
731 }
732 }
733 if(hasnan)
734 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs NaNs! [%s]\n", module_label,
736 if(hasinf)
737 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs non-finite floats! [%s]\n", module_label,
739 fprintf(stderr, "[dev_pixelpipe] module `%s' min: (%f; %f; %f) max: (%f; %f; %f) [%s]\n", module_label,
740 min[0], min[1], min[2], max[0], max[1], max[2], dt_pixelpipe_get_pipe_name(pipe->type));
741 }
742 else if(out_format->datatype == TYPE_FLOAT && out_format->channels == 1)
743 {
744 int hasinf = 0, hasnan = 0;
745 float min = FLT_MAX;
746 float max = FLT_MIN;
747
748 for(int k = 0; k < roi_out->width * roi_out->height; k++)
749 {
750 float f = ((float *)(output))[k];
751 if(isnan(f))
752 hasnan = 1;
753 else if(!isfinite(f))
754 hasinf = 1;
755 else
756 {
757 min = fmin(f, min);
758 max = fmax(f, max);
759 }
760 }
761 if(hasnan)
762 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs NaNs! [%s]\n", module_label,
764 if(hasinf)
765 fprintf(stderr, "[dev_pixelpipe] module `%s' outputs non-finite floats! [%s]\n", module_label,
767 fprintf(stderr, "[dev_pixelpipe] module `%s' min: (%f) max: (%f) [%s]\n", module_label, min, max,
769 }
770
771 dt_free(module_label);
772 }
773}
774
776 uint64_t *out_hash, const dt_dev_pixelpipe_iop_t **out_piece,
777 GList *pieces, int pos)
778{
779 // The pipeline is executed recursively, from the end. For each module n, starting from the end,
780 // if output is cached, take it, else if input is cached, take it, process it and output,
781 // else recurse to the previous module n-1 to get a an input.
782 void *input = NULL;
783 void *output = NULL;
784 void *cl_mem_output = NULL;
785
787
788 if(IS_NULL_PTR(pieces))
789 {
791 *out_piece = NULL;
792 return 0;
793 }
794
795 dt_iop_module_t *module = NULL;
797
799
800 // skip this module?
801 if(!piece->enabled)
802 return dt_dev_pixelpipe_process_rec(pipe, out_hash, out_piece, g_list_previous(pieces), pos - 1);
803
804 module = piece->module;
805
806 if(pipe->dev->gui_attached) pipe->dev->progress.total++;
807
809
810 const uint64_t hash = dt_dev_pixelpipe_node_hash(pipe, piece, piece->roi_out, pos);
811
812 // 1) Fast-track:
813 // If we have a cache entry for this hash, return it straight away,
814 // don't recurse through pipeline and don't process, unless this module still
815 // needs GUI-side sampling from its host input or the gamma display histogram
816 // needs the upstream cache entry.
817 dt_pixel_cache_entry_t *existing_cache = NULL;
818 void *existing_output = NULL;
819 const gboolean exact_output_cache_hit
820 = !_bypass_cache(pipe, piece)
821 && dt_dev_pixelpipe_cache_peek(darktable.pixelpipe_cache, hash, &existing_output, &existing_cache,
822 pipe->devid, NULL)
823 && !IS_NULL_PTR(existing_output);
824
825 if(exact_output_cache_hit)
826 {
827 /* An exact-hit child still needs one ref reserved for the immediate caller that will consume it next.
828 * `process_rec()` returns that upcoming-consumer ref as part of its contract instead of asking the caller
829 * to bump the counter again on input acquisition. */
831 _trace_cache_owner(pipe, module, "exact-hit-direct", "output", hash, NULL, existing_cache, FALSE);
832 *out_hash = hash;
833 *out_piece = piece;
834 return 0;
835 }
836
837 // 3) now recurse through the pipeline.
839 const dt_dev_pixelpipe_iop_t *previous_piece = NULL;
840 if(dt_dev_pixelpipe_process_rec(pipe, &input_hash, &previous_piece, g_list_previous(pieces), pos - 1))
841 {
842 /* Child recursion failed before this module acquired any output cache entry.
843 * Dropping `hash` here underflows cached exact-hit outputs during shutdown. */
845 "[pipeline] module=%s child recursion failed input_hash=%" PRIu64 " output_hash=%" PRIu64 "\n",
846 module->op, input_hash, hash);
847 return 1;
848 }
849
851
852 // Child recursion just published or exact-hit returned this hash with one ref already reserved for
853 // this immediate consumer. Reopen the live cache entry directly instead of going through exact-hit
854 // lookup, because exact-hit intentionally rejects auto-destroy entries while the parent recursion
855 // still needs to consume transient outputs in the same run.
856 dt_pixel_cache_entry_t *input_entry
858 if(!IS_NULL_PTR(previous_piece))
860 if(IS_NULL_PTR(input_entry) && !(module->flags() & IOP_FLAGS_TAKE_NO_INPUT))
861 {
863 "[pipeline] module=%s input cache entry missing input_hash=%" PRIu64 " output_hash=%" PRIu64
864 " prev_module=%s prev_hash=%" PRIu64 "\n",
865 module->op, input_hash, hash,
866 !IS_NULL_PTR(previous_piece) ? previous_piece->module->op : "",
867 !IS_NULL_PTR(previous_piece) ? previous_piece->global_hash : -1);
868 return 1;
869 }
870 input = input_entry ? dt_pixel_cache_entry_get_data(input_entry) : NULL;
871 _trace_cache_owner(pipe, module, "acquire", "input", input_hash, input, input_entry, FALSE);
872 if(input_entry)
873 _trace_buffer_content(pipe, module, "input-acquire", input, &piece->dsc_in, &piece->roi_in);
874 const size_t bufsize = (size_t)piece->dsc_out.bpp * piece->roi_out.width * piece->roi_out.height;
875 // Note: IS_NULL_PTR(input) is valid if we are on a GPU-only path, aka previous module ran on GPU
876 // without leaving its output on a RAM cache copy, and current module will also run on GPU.
877 // In this case, we rely on cl_mem_input for best performance (avoid memcpy between RAM and GPU).
878 // Should the GPU path fail at process time, we will init input and flush cl_mem_input into it.
879 // In any case, this avoids carrying a possibly-uninited input buffer, without knowing if it has
880 // data on it (or having to blindly copy back from vRAM to RAM).
881
882 // 3c) actually process this module BUT treat all bypasses first.
883 // special case: user requests to see channel data in the parametric mask of a module, or the blending
884 // mask. In that case we skip all modules manipulating pixel content and only process image distorting
885 // modules. Finally "gamma" is responsible for displaying channel/mask data accordingly.
886 if(pipe->dev->gui_attached
888 && !(module->operation_tags() & IOP_TAG_DISTORT)
889 && (piece->dsc_in.bpp == piece->dsc_out.bpp)
890 && !memcmp(&piece->roi_in, &piece->roi_out, sizeof(struct dt_iop_roi_t)))
891 {
892 /* Mask/channel passthrough keeps the exact child buffer alive for the next
893 * downstream module. This stage does not publish a new cacheline, so it
894 * must forward the child hash and actual previous piece contract exactly as
895 * they came from recursion, including the single reserved ref for the next
896 * real consumer. */
897 *out_hash = input_hash;
898 *out_piece = previous_piece;
899 return 0;
900 }
901
902 if(pipe->dev->gui_attached)
903 {
904 gchar *module_label = dt_history_item_get_name(module);
906 darktable.main_message = g_strdup_printf(_("Processing module `%s` for pipeline %s (%ix%i px @ %0.f%%)..."),
907 module_label, dt_pixelpipe_get_pipe_name(pipe->type),
908 piece->roi_out.width, piece->roi_out.height, piece->roi_out.scale * 100.f);
909 dt_free(module_label);
911 }
912
913 dt_pixel_cache_entry_t *output_entry = NULL;
914 gchar *type = dt_pixelpipe_get_pipe_name(pipe->type);
915
917
918 gchar *name = g_strdup_printf("module %s (%s) for pipe %s", module->op, module->multi_name, type);
919 gboolean cache_ram_output = piece->cache_output_on_ram && !_bypass_cache(pipe, piece);
920 /* `piece->cache_entry` is only valid as a writable-reuse hint for transient outputs that will
921 * be fully overwritten later. As soon as we keep the current output as a published cacheline in
922 * RAM, rekey reuse must stop for that piece so later runs cannot overwrite a long-term state in
923 * place just because the pipe is running in realtime. */
924 const gboolean allow_rekey_reuse = !(darktable.unmuted & DT_DEBUG_NOCACHE_REUSE) && !cache_ram_output;
927 cache_ram_output, allow_rekey_reuse,
928 &piece->cache_entry,
929 &output, &output_entry);
930 dt_free(name);
932 {
933 /* Another pipe already owns a cacheline for this exact hash. If that cacheline is
934 * still write-locked, this is not a processing error: it only means the concurrent
935 * publisher has not finished exposing the exact-hit payload yet. Wait for that
936 * publication to complete instead of aborting the whole recursion. */
937 dt_pixel_cache_entry_t *exact_entry
939 if(IS_NULL_PTR(exact_entry))
940 {
942 "[pipeline] module=%s exact-hit entry missing output_hash=%" PRIu64 "\n",
943 module->op, hash);
944 if(input_entry)
946 return 1;
947 }
948
954
955 _trace_cache_owner(pipe, module, "exact-hit-wait", "output", hash,
956 dt_pixel_cache_entry_get_data(exact_entry), exact_entry, FALSE);
957
958 if(input_entry)
960 *out_hash = hash;
961 *out_piece = piece;
962 return 0;
963 }
964 if(IS_NULL_PTR(output_entry))
965 {
967 "[pipeline] module=%s writable output acquisition failed output_hash=%" PRIu64
968 " acquire_status=%d\n",
969 module->op, hash, acquire_status);
970 if(input_entry)
972 return 1;
973 }
974 const gboolean new_entry = (acquire_status == DT_DEV_PIXELPIPE_CACHE_WRITABLE_CREATED);
975 _trace_cache_owner(pipe, module, (acquire_status == DT_DEV_PIXELPIPE_CACHE_WRITABLE_REKEYED) ? "acquire-rekeyed"
976 : (new_entry ? "acquire-new" : "acquire-existing"),
977 "output", hash, output, output_entry, FALSE);
978
979 /* get tiling requirement of module */
981 tiling.factor_cl = tiling.maxbuf_cl = -1; // set sentinel value to detect whether callback set sizes
982 module->tiling_callback(module, pipe, piece, &tiling);
983 if (tiling.factor_cl < 0) tiling.factor_cl = tiling.factor; // default to CPU size if callback didn't set GPU
984 if (tiling.maxbuf_cl < 0) tiling.maxbuf_cl = tiling.maxbuf;
985
986 /* does this module involve blending? */
987 if(piece->blendop_data && ((dt_develop_blend_params_t *)piece->blendop_data)->mask_mode != DEVELOP_MASK_DISABLED)
988 {
989 /* get specific memory requirement for blending */
990 dt_develop_tiling_t tiling_blendop = { 0 };
991 tiling_callback_blendop(module, pipe, piece, &tiling_blendop);
992
993 /* aggregate in structure tiling */
994 tiling.factor = fmax(tiling.factor, tiling_blendop.factor);
995 tiling.factor_cl = fmax(tiling.factor_cl, tiling_blendop.factor);
996 tiling.maxbuf = fmax(tiling.maxbuf, tiling_blendop.maxbuf);
997 tiling.maxbuf_cl = fmax(tiling.maxbuf_cl, tiling_blendop.maxbuf);
998 tiling.overhead = fmax(tiling.overhead, tiling_blendop.overhead);
999 }
1000
1001 /* remark: we do not do tiling for blendop step, neither in opencl nor on cpu. if overall tiling
1002 requirements (maximum of module and blendop) require tiling for opencl path, then following blend
1003 step is anyhow done on cpu. we assume that blending itself will never require tiling in cpu path,
1004 because memory requirements will still be low enough. */
1005
1006 assert(tiling.factor > 0.0f);
1007 assert(tiling.factor_cl > 0.0f);
1008
1009 // Actual pixel processing for this module
1010 int error = 0;
1011 dt_times_t start;
1012 dt_get_times(&start);
1013
1014 const char *prev_module = dt_pixelpipe_cache_set_current_module(module ? module->op : NULL);
1015
1016#ifdef HAVE_OPENCL
1017 error = pixelpipe_process_on_GPU(pipe, piece, previous_piece, &tiling, &pixelpipe_flow,
1018 &cache_ram_output,
1019 input_entry, output_entry);
1020#else
1021 error = pixelpipe_process_on_CPU(pipe, piece, previous_piece, &tiling, &pixelpipe_flow,
1022 &cache_ram_output,
1023 input_entry, output_entry);
1024#endif
1025
1027 output = dt_pixel_cache_entry_get_data(output_entry);
1028
1029 _print_perf_debug(pipe, pixelpipe_flow, piece, module,
1030 (acquire_status != DT_DEV_PIXELPIPE_CACHE_WRITABLE_CREATED), &start);
1031
1032 if(pipe->dev->gui_attached) pipe->dev->progress.completed++;
1033
1034 if(error)
1035 {
1037 "[pipeline] module=%s backend processing failed input_hash=%" PRIu64 " output_hash=%" PRIu64
1038 " input_cst=%d output_cst=%d roi_in=%dx%d roi_out=%dx%d\n",
1039 module->op, input_hash, hash, piece->dsc_in.cst, piece->dsc_out.cst,
1040 piece->roi_in.width, piece->roi_in.height, piece->roi_out.width, piece->roi_out.height);
1041 _trace_cache_owner(pipe, module, "error-cleanup", "input", input_hash, input, input_entry, FALSE);
1042 _trace_cache_owner(pipe, module, "error-cleanup", "output", hash, output, output_entry, FALSE);
1043 // Ensure we always release locks and cache references on error, otherwise cache eviction/GC will stall.
1046 if(input_entry)
1047 {
1050 }
1051
1052 // No point in keeping garbled output
1056 return 1;
1057 }
1058
1059 // Publish the module output descriptor authored for this stage. The cache entry keeps the
1060 // descriptor of the pixels this module actually published, not the stale descriptor of its input.
1061 _trace_cache_owner(pipe, module, "publish", "output", hash, output, output_entry, FALSE);
1062 _trace_buffer_content(pipe, module, "publish", output, &piece->dsc_out, &piece->roi_out);
1063
1064 if(!IS_NULL_PTR(output_entry))
1065 {
1066 piece->cache_entry = *output_entry;
1067 }
1068 else
1070
1071 if(!IS_NULL_PTR(output_entry) && !IS_NULL_PTR(output) && !(module->flags() & IOP_FLAGS_CPU_WRITES_OPENCL)
1072 && ((pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_ON_CPU)
1073 || (pixelpipe_flow & PIXELPIPE_FLOW_PROCESSED_WITH_TILING)))
1074 {
1075 dt_dev_pixelpipe_gpu_flush_host_pinned_images(pipe, output, output_entry, "module output host rewrite");
1076 /* CPU/tiling processing rewrote the whole host buffer for this output. If the cache entry was rekeyed
1077 * from an older GPU stage, any cached device-only images still hanging off the same entry now point to
1078 * obsolete pixels. Drop them here so later mixed GPU/CPU modules cannot resurrect stale device payloads. */
1080 }
1081
1082 // Flag to throw away intermediate outputs as soon as the next module consumes them.
1083 // `cache_output` only means the backend had to keep a host-authoritative payload for this
1084 // stage (for example because the next module may need RAM or because the current stage ran
1085 // through an OpenCL cache path). In no-cache/bypass pipelines, that does not make the
1086 // published cacheline long-lived: once the downstream module takes its input ref, this
1087 // stage is transient and must disappear on release. Only the final published output needs
1088 // to survive long enough for dt_dev_pixelpipe_process() to promote it to the backbuffer,
1089 // otherwise thumbnail/export callers only see a missing exact-hit and fall back to invalid
1090 // placeholder pixels.
1091 const gboolean keep_final_output = (hash == dt_dev_pixelpipe_get_hash(pipe));
1092 if(_bypass_cache(pipe, piece) && !keep_final_output)
1094
1095 if(pipe->dev->gui_attached)
1096 {
1099 }
1100
1101 // From here on we only publish/inspect the finished output. Keep the writable lock strictly
1102 // around cacheline allocation and backend processing, then release it at one visible point
1103 // before the generic tail cleanup shared by darkroom and headless paths.
1105
1107
1108 // Decrease reference count on input and flush it if it was flagged for auto destroy previously
1109 _trace_cache_owner(pipe, module, "release", "input", input_hash, input, input_entry, FALSE);
1110 if(input_entry)
1111 {
1114 }
1115
1116 // Print min/max/Nan in debug mode only
1117 if((darktable.unmuted & DT_DEBUG_NAN) && strcmp(module->op, "gamma") != 0 && !IS_NULL_PTR(output))
1118 {
1120 _print_nan_debug(pipe, cl_mem_output, output, &piece->roi_out, &piece->dsc_out, module);
1122 }
1123
1125
1126 *out_hash = hash;
1127 *out_piece = piece;
1128 return 0;
1129}
1130
1132{
1133 GList *nodes = g_list_last(pipe->nodes);
1135 while(strcmp(piece->module->op, op))
1136 {
1137 piece->enabled = 0;
1138 piece = NULL;
1139 nodes = g_list_previous(nodes);
1140 if(!nodes) break;
1141 piece = (dt_dev_pixelpipe_iop_t *)nodes->data;
1142 }
1143}
1144
1146{
1147 GList *nodes = pipe->nodes;
1149 while(strcmp(piece->module->op, op))
1150 {
1151 piece->enabled = 0;
1152 piece = NULL;
1153 nodes = g_list_next(nodes);
1154 if(!nodes) break;
1155 piece = (dt_dev_pixelpipe_iop_t *)nodes->data;
1156 }
1157}
1158
1159#define KILL_SWITCH_PIPE \
1160 if(dt_dev_pixelpipe_has_shutdown(pipe)) \
1161 { \
1162 if(pipe->devid >= 0) \
1163 { \
1164 dt_opencl_unlock_device(pipe->devid); \
1165 pipe->devid = -1; \
1166 } \
1167 if(pipe->forms) \
1168 { \
1169 g_list_free_full(pipe->forms, (void (*)(void *))dt_masks_free_form); \
1170 pipe->forms = NULL; \
1171 } \
1172 dt_pthread_mutex_unlock(&darktable.pipeline_threadsafe); \
1173 return 1; \
1174 }
1175
1176
1178{
1179 switch(error)
1180 {
1181 case 1:
1182 dt_print(DT_DEBUG_OPENCL, "[opencl] Opencl errors; disabling opencl for %s pipeline!\n", dt_pixelpipe_get_pipe_name(pipe->type));
1183 dt_control_log(_("Ansel discovered problems with your OpenCL setup; disabling OpenCL for %s pipeline!"), dt_pixelpipe_get_pipe_name(pipe->type));
1184 break;
1185 case 2:
1187 "[opencl] Too many opencl errors; disabling opencl for this session!\n");
1188 dt_control_log(_("Ansel discovered problems with your OpenCL setup; disabling OpenCL for this session!"));
1189 break;
1190 default:
1191 break;
1192 }
1193}
1194
1196{
1197 const uint64_t requested_hash = dt_dev_pixelpipe_get_hash(pipe);
1198 const uint64_t entry_hash = entry->hash;
1199
1200 _trace_cache_owner(pipe, NULL, "backbuf-update", "backbuf", requested_hash,
1201 entry ? entry->data : NULL, entry, FALSE);
1202
1203 if(requested_hash == DT_PIXELPIPE_CACHE_HASH_INVALID
1204 || entry_hash == DT_PIXELPIPE_CACHE_HASH_INVALID
1205 || entry_hash != requested_hash)
1206 {
1210 return;
1211 }
1212
1213 // Keep exactly one cache reference to the last valid output ("backbuf") for display.
1214 // This prevents the cache entry from being evicted while still in use by the GUI,
1215 // without leaking references on repeated cache hits.
1216 const gboolean hash_changed = (dt_dev_backbuf_get_hash(&pipe->backbuf) != entry_hash);
1217 if(hash_changed)
1218 {
1221 }
1222
1223 int bpp = 0;
1224 if(roi.width > 0 && roi.height > 0)
1225 bpp = (int)(dt_pixel_cache_entry_get_size(entry) / ((size_t)roi.width * (size_t)roi.height));
1226
1227 // Always refresh backbuf geometry/state, even when the cache key is unchanged.
1228 // Realtime drawing can update pixels in-place in the same cacheline, so width/height/history
1229 // must stay synchronized independently from key changes.
1230 dt_dev_set_backbuf(&pipe->backbuf, roi.width, roi.height, bpp, entry_hash,
1232}
1233
1234static GList *_get_requested_piece_node(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module, int *pos)
1235{
1236 if(pos) *pos = 0;
1237 if(IS_NULL_PTR(pipe) || IS_NULL_PTR(module)) return NULL;
1238
1239 int current_pos = 1;
1240 for(GList *node = g_list_first(pipe->nodes); node; node = g_list_next(node), current_pos++)
1241 {
1242 dt_dev_pixelpipe_iop_t *const piece = node->data;
1243 if(piece && piece->enabled && piece->module == module)
1244 {
1245 if(pos) *pos = current_pos;
1246 return node;
1247 }
1248 }
1249
1250 return NULL;
1251}
1252
1254{
1255 /* `pipe->devid` is only valid while the current run owns the OpenCL device lock.
1256 * Reset it before any cache probe so callers never reuse a stale device id from a
1257 * previous pipeline pass. */
1258 pipe->devid = -1;
1259
1261 {
1262 fprintf(stderr, "[memory] before pixelpipe process\n");
1264 }
1265
1267
1268 if(pipe->dev->gui_attached)
1269 {
1270 pipe->dev->color_picker.pending_module = NULL;
1271 pipe->dev->color_picker.pending_pipe = NULL;
1273 }
1274
1275 // Get the roi_out hash of all nodes.
1276 // Get the previous output size of the module, for cache invalidation.
1277 dt_dev_pixelpipe_get_roi_in(pipe, roi);
1279 const guint pos = g_list_length(pipe->dev->iop);
1280
1282 const dt_iop_module_t *const requested_module = dt_dev_pixelpipe_get_cache_request_module(pipe);
1284
1285 GList *requested_pieces = g_list_last(pipe->nodes);
1286 int requested_pos = (int)pos;
1287 dt_dev_pixelpipe_iop_t *requested_piece = NULL;
1288 gboolean requested_backbuf = TRUE;
1289
1290 if(cache_request == DT_DEV_PIXELPIPE_CACHE_REQUEST_MODULE && !IS_NULL_PTR(requested_module))
1291 {
1292 requested_pieces = _get_requested_piece_node(pipe, requested_module, &requested_pos);
1293 if(requested_pieces)
1294 {
1295 requested_piece = requested_pieces->data;
1296 requested_backbuf = FALSE;
1297 }
1298 else
1299 {
1300 dt_print(DT_DEBUG_DEV, "[pixelpipe/gui] requested module cache target disappeared pipe=%s module=%s\n",
1301 dt_pixelpipe_get_pipe_name(pipe->type), requested_module->op);
1302 }
1303 }
1304
1305 void *buf = NULL;
1306
1307 /* GUI cache requests can target either the final backbuffer or one module output in the middle of the
1308 current synchronized graph. Exact-hit checks must therefore look at the requested target instead of
1309 always assuming the run goes to the pipe end. */
1310 const uint64_t requested_hash = requested_backbuf ? dt_dev_pixelpipe_get_hash(pipe)
1311 : requested_piece ? requested_piece->global_hash
1313 dt_pixel_cache_entry_t *entry = NULL;
1314 if(!_bypass_cache(pipe, requested_piece)
1315 && requested_hash != DT_PIXELPIPE_CACHE_HASH_INVALID
1316 && dt_dev_pixelpipe_cache_peek(darktable.pixelpipe_cache, requested_hash, &buf, &entry,
1317 pipe->devid, NULL)
1318 && !IS_NULL_PTR(buf))
1319 {
1320 if(requested_backbuf)
1321 _update_backbuf_cache_reference(pipe, roi, entry);
1322 return 0;
1323 }
1324
1325 dt_print(DT_DEBUG_DEV, "[pixelpipe] Started %s pipeline recompute at %i×%i px\n",
1326 dt_pixelpipe_get_pipe_name(pipe->type), roi.width, roi.height);
1327
1328 // get a snapshot of the mask list
1330 pipe->forms = dt_masks_dup_forms_deep(pipe->dev->forms, NULL);
1332
1333 // go through the list of modules from the end:
1334 GList *pieces = g_list_last(pipe->nodes);
1335
1336 // Because it's possible here that we export at full resolution,
1337 // and our memory planning doesn't account for several concurrent pipelines
1338 // at full size, we allow only one pipeline at a time to run.
1339 // This is because wavelets decompositions and such use 6 copies,
1340 // so the RAM usage can go out of control here.
1342
1343 pipe->opencl_enabled = dt_opencl_update_settings(); // update enabled flag and profile from preferences
1344 pipe->devid = (pipe->opencl_enabled) ? dt_opencl_lock_device(pipe->type)
1345 : -1; // try to get/lock opencl resource
1346
1347 if(pipe->devid > -1) dt_opencl_events_reset(pipe->devid);
1348 dt_print(DT_DEBUG_OPENCL, "[pixelpipe_process] [%s] using device %d\n", dt_pixelpipe_get_pipe_name(pipe->type),
1349 pipe->devid);
1350
1352
1353 gboolean keep_running = TRUE;
1354 int runs = 0;
1355 int opencl_error = 0;
1356 int err = 0;
1357
1358 while(keep_running && runs < 3)
1359 {
1360 ++runs;
1361
1362 /* Mask preview is authored while the current run advances through blend.c.
1363 * Reset it for each retry so a stale state from a previous pass cannot leak
1364 * into the next recursion before the active module reaches its own blend. */
1366
1367#ifdef HAVE_OPENCL
1369#endif
1370
1372
1373 dt_times_t start;
1374 dt_get_times(&start);
1375 uint64_t final_hash = -1;
1376 const dt_dev_pixelpipe_iop_t *final_piece = NULL;
1377 err = dt_dev_pixelpipe_process_rec(pipe, &final_hash, &final_piece,
1378 requested_backbuf ? pieces : requested_pieces,
1379 requested_backbuf ? pos : requested_pos);
1380 (void)final_piece;
1381 gchar *msg = g_strdup_printf("[pixelpipe] %s internal pixel pipeline processing", dt_pixelpipe_get_pipe_name(pipe->type));
1382 dt_show_times(&start, msg);
1383 dt_free(msg);
1384
1385 // get status summary of opencl queue by checking the eventlist
1386 const int oclerr = (pipe->devid > -1) ? dt_opencl_events_flush(pipe->devid, TRUE) != 0 : 0;
1387
1388 // Check if we had opencl errors ....
1389 // remark: opencl errors can come in two ways: pipe->opencl_error is TRUE (and err is TRUE) OR oclerr is
1390 // TRUE
1391 keep_running = (oclerr || (err && pipe->opencl_error));
1392 if(keep_running)
1393 {
1394 // Log the error
1395 darktable.opencl->error_count++; // increase error count
1396 opencl_error = 1; // = any OpenCL error, next run goes to CPU
1397
1398 // Disable OpenCL for this pipe
1400 pipe->opencl_enabled = 0;
1401 pipe->opencl_error = 0;
1402 pipe->devid = -1;
1403
1405 {
1406 // Too many errors : dispable OpenCL for this session
1408 dt_capabilities_remove("opencl");
1409 opencl_error = 2; // = too many OpenCL errors, all runs go to CPU
1410 }
1411
1412 _print_opencl_errors(opencl_error, pipe);
1413 }
1414 else if(!dt_dev_pixelpipe_has_shutdown(pipe))
1415 {
1416 // No opencl errors, no killswitch triggered: we should have a valid output buffer now.
1417 dt_pixel_cache_entry_t *final_entry = NULL;
1418 void *final_buf = NULL;
1419 if(!requested_backbuf)
1420 {
1422 }
1424 &final_entry, pipe->devid, NULL)
1425 && !IS_NULL_PTR(final_buf))
1426 {
1427 _update_backbuf_cache_reference(pipe, roi, final_entry);
1429 }
1430 else
1431 {
1433 "[picker/rec] final output cache missing pipe=%s hash=%" PRIu64 " history=%" PRIu64
1434 " devid=%d err=%d\n",
1436 dt_dev_pixelpipe_get_history_hash(pipe), pipe->devid, err);
1438 }
1439
1440 // Note : the last output (backbuf) of the pixelpipe cache is internally locked
1441 // Whatever consuming it will need to unlock it.
1442 }
1443 }
1444
1446
1447 // release resources:
1448 if(pipe->forms)
1449 {
1450 g_list_free_full(pipe->forms, (void (*)(void *))dt_masks_free_form);
1451 pipe->forms = NULL;
1452 }
1453 if(pipe->devid >= 0)
1454 {
1456 pipe->devid = -1;
1457 }
1458
1459 // terminate
1461
1462 // If an intermediate module set that, be sure to reset it at the end
1463 pipe->flush_cache = FALSE;
1464 return err;
1465}
1466
1467// clang-format off
1468// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1469// vim: shiftwidth=2 expandtab tabstop=2 cindent
1470// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1471// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_atomic_set_int(dt_atomic_int *var, int value)
int dt_atomic_get_int(dt_atomic_int *var)
atomic_int dt_atomic_int
Definition atomic.h:66
int levels(struct dt_imageio_module_data_t *data)
Definition avif.c:635
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
void tiling_callback_blendop(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
Definition blend.c:1487
dt_iop_colorspace_type_t dt_develop_blend_colorspace(const dt_dev_pixelpipe_iop_t *const piece, dt_iop_colorspace_type_t cst)
Definition blend.c:186
@ DEVELOP_MASK_DISABLED
Definition blend.h:112
dt_iop_colorspace_type_t
Definition color_conversion.h:30
@ IOP_CS_RAW
Definition color_conversion.h:32
@ IOP_CS_LCH
Definition color_conversion.h:35
@ IOP_CS_JZCZHZ
Definition color_conversion.h:37
@ IOP_CS_RGB
Definition color_conversion.h:34
@ IOP_CS_HSL
Definition color_conversion.h:36
@ IOP_CS_LAB
Definition color_conversion.h:33
@ IOP_CS_NONE
Definition color_conversion.h:31
dt_iop_color_intent_t
Definition colorspaces.h:63
@ DT_INTENT_LAST
Definition colorspaces.h:68
dt_colorspaces_color_profile_type_t
Definition colorspaces.h:81
@ DT_COLORSPACE_NONE
Definition colorspaces.h:82
const dt_aligned_pixel_t f
Definition colorspaces_inline_conversions.h:102
const float d
Definition colorspaces_inline_conversions.h:680
static const float const float const float min
Definition colorspaces_inline_conversions.h:438
const float max
Definition colorspaces_inline_conversions.h:490
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
int type
Definition common/metadata.c:62
char * name
Definition common/metadata.c:61
void dt_control_log(const char *msg,...)
Definition control.c:530
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
Definition control.c:630
void dt_show_times(const dt_times_t *start, const char *prefix)
Definition darktable.c:1486
darktable_t darktable
Definition darktable.c:173
void dt_print_mem_usage()
Definition darktable.c:1707
void dt_capabilities_remove(char *capability)
Definition darktable.c:1690
void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix,...)
Definition darktable.c:1500
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1448
#define UNKNOWN_IMAGE
Definition darktable.h:182
@ DT_DEBUG_OPENCL
Definition darktable.h:721
@ DT_DEBUG_PIPE
Definition darktable.h:740
@ DT_DEBUG_PIPECACHE
Definition darktable.h:719
@ DT_DEBUG_NAN
Definition darktable.h:725
@ DT_DEBUG_MEMORY
Definition darktable.h:723
@ DT_DEBUG_VERBOSE
Definition darktable.h:742
@ DT_DEBUG_DEV
Definition darktable.h:717
@ DT_DEBUG_NOCACHE_REUSE
Definition darktable.h:744
static void dt_free_gpointer(gpointer ptr)
Definition darktable.h:463
#define dt_free(ptr)
Definition darktable.h:456
static void dt_get_times(dt_times_t *t)
Definition darktable.h:920
#define __OMP_FOR_SIMD__(...)
Definition darktable.h:260
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
uint64_t dt_dev_pixelpipe_node_hash(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t roi_out, const int pos)
Definition dev_pixelpipe.c:489
void dt_pixelpipe_get_global_hash(dt_dev_pixelpipe_t *pipe)
Definition dev_pixelpipe.c:854
void dt_dev_pixelpipe_get_roi_in(dt_dev_pixelpipe_t *pipe, const struct dt_iop_roi_t roi_out)
Definition dev_pixelpipe.c:403
void dt_dev_set_backbuf(dt_backbuf_t *backbuf, const int width, const int height, const size_t bpp, const int64_t hash, const int64_t history_hash)
Definition develop.c:1747
gchar * dt_history_item_get_name(const struct dt_iop_module_t *module)
Definition develop.c:1356
@ DT_DEV_PIXELPIPE_DISPLAY_NONE
Definition develop.h:117
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:374
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Definition dtpthread.h:359
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
Definition dtpthread.h:379
#define dt_pthread_rwlock_unlock
Definition dtpthread.h:392
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:364
#define dt_pthread_rwlock_rdlock
Definition dtpthread.h:393
void dt_iop_buffer_dsc_update_bpp(dt_iop_buffer_dsc_t *dsc)
Definition format.c:28
dt_iop_buffer_type_t
Definition format.h:44
@ TYPE_FLOAT
Definition format.h:46
@ TYPE_UNKNOWN
Definition format.h:45
@ TYPE_UINT8
Definition format.h:48
@ TYPE_UINT16
Definition format.h:47
int bpp
Definition imageio/format/pdf.c:88
@ IMAGEIO_RGB
Definition imageio.h:70
@ IMAGEIO_INT8
Definition imageio.h:62
void dt_iop_init_pipe(struct dt_iop_module_t *module, struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece)
Definition imageop.c:526
void dt_iop_cleanup_pipe(struct dt_iop_module_t *module, struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece)
Definition imageop.c:533
static gboolean dt_iop_colorspace_is_rgb(const dt_iop_colorspace_type_t cst)
Definition imageop.h:213
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:167
@ IOP_FLAGS_TAKE_NO_INPUT
Definition imageop.h:176
@ IOP_FLAGS_CPU_WRITES_OPENCL
Definition imageop.h:180
@ IOP_CS_RGB_DISPLAY
Definition imageop.h:210
@ IOP_TAG_DISTORT
Definition imageop.h:151
GList * dt_ioppr_iop_order_copy_deep(GList *iop_order_list)
Deep-copy an order list.
Definition iop_order.c:1935
float *const restrict const size_t k
Definition luminance_mask.h:78
GList * dt_masks_dup_forms_deep(GList *forms, dt_masks_form_t *form)
Duplicate the list of forms, replacing a single item by formid match.
Definition develop/masks/masks.c:719
void dt_masks_free_form(dt_masks_form_t *form)
Definition develop/masks/masks.c:2068
float iscale
Definition mipmap_cache.c:2
size_t size
Definition mipmap_cache.c:3
dt_mipmap_size_t
Definition mipmap_cache.h:41
Definition tiling.py:1
float dt_aligned_pixel_t[4]
Definition noiseprofile.c:28
void dt_opencl_unlock_device(const int dev)
Definition opencl.c:1463
void dt_opencl_events_reset(const int devid)
Definition opencl.c:2705
cl_int dt_opencl_events_flush(const int devid, const int reset)
Definition opencl.c:2782
int dt_opencl_lock_device(const int pipetype)
Definition opencl.c:1378
void dt_opencl_check_tuning(const int devid)
Definition opencl.c:2462
int dt_opencl_update_settings(void)
Definition opencl.c:2568
#define DT_OPENCL_MAX_ERRORS
Definition opencl.h:49
void dt_pixelpipe_raster_cleanup(GHashTable *raster_masks)
Definition pixelpipe.c:70
GHashTable * dt_pixelpipe_raster_alloc()
Definition pixelpipe.c:58
void dt_dev_clear_rawdetail_mask(dt_dev_pixelpipe_t *pipe)
Release the side-band detail mask cache reference currently owned by the pipeline.
Definition pixelpipe.c:63
@ DT_REQUEST_ON
Definition pixelpipe.h:48
@ DT_REQUEST_ONLY_IN_GUI
Definition pixelpipe.h:49
dt_dev_pixelpipe_type_t
Definition pixelpipe.h:36
@ DT_DEV_PIXELPIPE_THUMBNAIL
Definition pixelpipe.h:41
@ DT_DEV_PIXELPIPE_EXPORT
Definition pixelpipe.h:38
@ DT_DEV_PIXELPIPE_PREVIEW
Definition pixelpipe.h:40
@ DT_DEV_PIXELPIPE_FULL
Definition pixelpipe.h:39
void * dt_pixel_cache_entry_get_data(dt_pixel_cache_entry_t *entry)
Definition pixelpipe_cache.c:1495
void dt_dev_pixelpipe_cache_ref_count_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
Definition pixelpipe_cache.c:2225
void dt_dev_pixelpipe_cache_print(dt_dev_pixelpipe_cache_t *cache)
Definition pixelpipe_cache.c:2426
void dt_dev_pixelpipe_cache_unref_hash(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash)
Find the entry matching hash, and decrease its ref_count if found.
Definition pixelpipe_cache.c:2326
void dt_dev_pixelpipe_cache_flag_auto_destroy(dt_dev_pixelpipe_cache_t *cache, dt_pixel_cache_entry_t *cache_entry)
Flag the cache entry as "auto_destroy". This is useful for short-lived/disposable cache entries,...
Definition pixelpipe_cache.c:2268
void dt_dev_pixelpipe_cache_auto_destroy_apply(dt_dev_pixelpipe_cache_t *cache, dt_pixel_cache_entry_t *cache_entry)
Free the entry if it has the flag "auto_destroy". See dt_dev_pixelpipe_cache_flag_auto_destroy()....
Definition pixelpipe_cache.c:2284
void dt_dev_pixelpipe_cache_release_cl_buffer(void **cl_mem_buffer, dt_pixel_cache_entry_t *cache_entry, void *host_ptr, const gboolean cache_device)
Release or cache an OpenCL image associated with a host cache line.
Definition pixelpipe_cache.c:1017
gboolean dt_dev_pixelpipe_cache_peek(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, void **data, dt_pixel_cache_entry_t **entry, const int preferred_devid, void **cl_mem_output)
Non-owning lookup of an existing cache line.
Definition pixelpipe_cache.c:2052
void dt_dev_pixelpipe_cache_flush_entry_clmem(dt_pixel_cache_entry_t *entry)
Flush all reusable OpenCL payloads cached on one cache entry.
Definition pixelpipe_cache.c:731
dt_pixel_cache_entry_t * dt_dev_pixelpipe_cache_get_entry(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash)
Get an internal reference to the cache entry matching hash. If you are going to access this entry mor...
Definition pixelpipe_cache.c:144
int dt_dev_pixelpipe_cache_remove(dt_dev_pixelpipe_cache_t *cache, const gboolean force, dt_pixel_cache_entry_t *cache_entry)
Arbitrarily remove the cache entry matching hash. Entries having a reference count > 0 (inter-thread ...
Definition pixelpipe_cache.c:255
dt_dev_pixelpipe_cache_writable_status_t dt_dev_pixelpipe_cache_get_writable(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, const size_t size, const char *name, const int id, const gboolean alloc, const gboolean allow_rekey_reuse, const dt_pixel_cache_entry_t *reuse_hint, void **data, dt_pixel_cache_entry_t **entry)
Definition pixelpipe_cache.c:1917
void dt_dev_pixelpipe_cache_wrlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the write lock on the entry.
Definition pixelpipe_cache.c:2234
size_t dt_pixel_cache_entry_get_size(dt_pixel_cache_entry_t *entry)
Peek the size (in bytes) reserved for the host buffer of a cache entry.
Definition pixelpipe_cache.c:1500
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
Definition pixelpipe_cache.c:2252
void dt_dev_pixelpipe_cache_flush_clmem(dt_dev_pixelpipe_cache_t *cache, const int devid)
Release cached OpenCL buffers for a device (-1 for all).
Definition pixelpipe_cache.c:444
const char * dt_pixelpipe_cache_set_current_module(const char *module)
Set the current module name for cache diagnostics (thread-local).
Definition pixelpipe_cache.c:78
Pixelpipe cache for storing intermediate results in the pixelpipe.
#define DT_PIXELPIPE_CACHE_HASH_INVALID
Definition pixelpipe_cache.h:42
dt_dev_pixelpipe_cache_writable_status_t
Definition pixelpipe_cache.h:70
@ DT_DEV_PIXELPIPE_CACHE_WRITABLE_REKEYED
Definition pixelpipe_cache.h:74
@ DT_DEV_PIXELPIPE_CACHE_WRITABLE_CREATED
Definition pixelpipe_cache.h:73
@ DT_DEV_PIXELPIPE_CACHE_WRITABLE_EXACT_HIT
Definition pixelpipe_cache.h:72
int pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_dev_pixelpipe_iop_t *previous_piece, dt_develop_tiling_t *tiling, dt_pixelpipe_flow_t *pixelpipe_flow, gboolean *const cache_output, dt_pixel_cache_entry_t *input_entry, dt_pixel_cache_entry_t *output_entry)
Definition pixelpipe_cpu.c:15
int pixelpipe_process_on_GPU(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_dev_pixelpipe_iop_t *previous_piece, dt_develop_tiling_t *tiling, dt_pixelpipe_flow_t *pixelpipe_flow, gboolean *const cache_output, dt_pixel_cache_entry_t *input_entry, dt_pixel_cache_entry_t *output_entry)
Definition pixelpipe_gpu.c:187
void dt_dev_pixelpipe_gpu_flush_host_pinned_images(dt_dev_pixelpipe_t *pipe, void *host_ptr, dt_pixel_cache_entry_t *cache_entry, const char *reason)
Definition pixelpipe_gpu.c:16
void dt_dev_pixelpipe_set_input(dt_dev_pixelpipe_t *pipe, int32_t imgid, int width, int height, float iscale, dt_mipmap_size_t size)
Definition pixelpipe_hb.c:466
dt_pixelpipe_blend_transform_t dt_dev_pixelpipe_transform_for_blend(const dt_iop_module_t *const self, const dt_dev_pixelpipe_iop_t *const piece, const dt_iop_buffer_dsc_t *const output_dsc)
Definition pixelpipe_hb.c:629
static void _trace_buffer_content(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module, const char *phase, const void *buffer, const dt_iop_buffer_dsc_t *format, const dt_iop_roi_t *roi)
Definition pixelpipe_hb.c:118
void dt_dev_pixelpipe_disable_before(dt_dev_pixelpipe_t *pipe, const char *op)
Definition pixelpipe_hb.c:1145
int dt_dev_pixelpipe_init_dummy(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
Definition pixelpipe_hb.c:392
static gboolean _is_focused_realtime_gui_module(const dt_dev_pixelpipe_t *pipe, const dt_develop_t *dev, const dt_iop_module_t *module)
Definition pixelpipe_hb.c:238
void dt_dev_pixelpipe_reset_reentry(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:564
int dt_dev_pixelpipe_init_cached(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:425
static void _update_backbuf_cache_reference(dt_dev_pixelpipe_t *pipe, dt_iop_roi_t roi, dt_pixel_cache_entry_t *entry)
Definition pixelpipe_hb.c:1195
gboolean dt_dev_pixelpipe_has_reentry(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:559
void dt_dev_pixelpipe_disable_after(dt_dev_pixelpipe_t *pipe, const char *op)
Definition pixelpipe_hb.c:1131
int dt_dev_pixelpipe_init(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
Definition pixelpipe_hb.c:414
gboolean dt_dev_pixelpipe_cache_gpu_device_buffer(const dt_dev_pixelpipe_t *pipe, const dt_pixel_cache_entry_t *cache_entry)
Definition pixelpipe_hb.c:247
gboolean dt_dev_pixelpipe_get_realtime(const dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:461
static const char * _debug_type_to_string(const dt_iop_buffer_type_t type)
Definition pixelpipe_hb.c:320
static const char * _debug_cst_to_string(const int cst)
Definition pixelpipe_hb.c:295
#define KILL_SWITCH_ABORT
Definition pixelpipe_hb.c:650
void dt_dev_pixelpipe_set_icc(dt_dev_pixelpipe_t *pipe, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent)
Definition pixelpipe_hb.c:477
static int _abort_module_shutdown_cleanup(dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_module_t *module, const uint64_t input_hash, const void *input, dt_pixel_cache_entry_t *input_entry, const uint64_t output_hash, void **output, void **cl_mem_output, dt_pixel_cache_entry_t *output_entry)
Definition pixelpipe_hb.c:204
static int dt_dev_pixelpipe_process_rec(dt_dev_pixelpipe_t *pipe, uint64_t *out_hash, const dt_dev_pixelpipe_iop_t **out_piece, GList *pieces, int pos)
Definition pixelpipe_hb.c:775
char * dt_pixelpipe_get_pipe_name(dt_dev_pixelpipe_type_t pipe_type)
Definition pixelpipe_hb.c:255
static void _print_opencl_errors(int error, dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:1177
static void _trace_cache_owner(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module, const char *phase, const char *slot, const uint64_t requested_hash, const void *buffer, const dt_pixel_cache_entry_t *entry, const gboolean verbose)
Definition pixelpipe_hb.c:92
static GList * _get_requested_piece_node(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module, int *pos)
Definition pixelpipe_hb.c:1234
int dt_dev_pixelpipe_init_preview(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
Definition pixelpipe_hb.c:401
static void _print_nan_debug(dt_dev_pixelpipe_t *pipe, void *cl_mem_output, void *output, const dt_iop_roi_t *roi_out, dt_iop_buffer_dsc_t *out_format, dt_iop_module_t *module)
Definition pixelpipe_hb.c:701
void dt_dev_pixelpipe_create_nodes(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:591
int dt_dev_pixelpipe_init_thumbnail(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
Definition pixelpipe_hb.c:383
int dt_dev_pixelpipe_init_export(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, int levels, gboolean store_masks)
Definition pixelpipe_hb.c:372
#define KILL_SWITCH_PIPE
Definition pixelpipe_hb.c:1159
void dt_dev_pixelpipe_cleanup(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:486
gboolean dt_dev_pixelpipe_unset_reentry(dt_dev_pixelpipe_t *pipe, uint64_t hash)
Remove the re-entry pipeline flag, only if the object identifier is the one that set it....
Definition pixelpipe_hb.c:546
int dt_dev_pixelpipe_process(dt_dev_pixelpipe_t *pipe, dt_iop_roi_t roi)
Definition pixelpipe_hb.c:1253
static void _print_perf_debug(dt_dev_pixelpipe_t *pipe, const dt_pixelpipe_flow_t pixelpipe_flow, dt_dev_pixelpipe_iop_t *piece, dt_iop_module_t *module, const gboolean recycled_output_cacheline, dt_times_t *start)
Definition pixelpipe_hb.c:669
static void _uint8_to_float(const uint8_t *const input, float *const output, const size_t width, const size_t height, const size_t chan)
Definition pixelpipe_hb.c:280
void dt_dev_pixelpipe_debug_dump_module_io(dt_dev_pixelpipe_t *pipe, dt_iop_module_t *module, const char *stage, const gboolean is_cl, const dt_iop_buffer_dsc_t *in_dsc, const dt_iop_buffer_dsc_t *out_dsc, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, const size_t in_bpp, const size_t out_bpp, const int cst_before, const int cst_after)
Definition pixelpipe_hb.c:336
#define KILL_SWITCH_AND_FLUSH_CACHE
Definition pixelpipe_hb.c:662
gboolean dt_dev_pixelpipe_set_reentry(dt_dev_pixelpipe_t *pipe, uint64_t hash)
Set the re-entry pipeline flag, only if no object is already capturing it. Re-entered pipelines run w...
Definition pixelpipe_hb.c:532
void dt_dev_pixelpipe_set_realtime(dt_dev_pixelpipe_t *pipe, gboolean state)
Definition pixelpipe_hb.c:455
void dt_dev_pixelpipe_cleanup_nodes(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.c:571
static dt_dev_pixelpipe_cache_request_t dt_dev_pixelpipe_get_cache_request(const dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.h:408
static void dt_dev_pixelpipe_set_hash(dt_dev_pixelpipe_t *pipe, const uint64_t hash)
Definition pixelpipe_hb.h:378
static const struct dt_iop_module_t * dt_dev_pixelpipe_get_cache_request_module(const dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.h:414
static uint64_t dt_dev_pixelpipe_get_hash(const dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.h:373
static void dt_dev_pixelpipe_reset_cache_request(dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.h:428
@ DT_DEV_PIPE_UNCHANGED
Definition pixelpipe_hb.h:166
static uint64_t dt_dev_pixelpipe_get_history_hash(const dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.h:383
static void dt_dev_pixelpipe_set_history_hash(dt_dev_pixelpipe_t *pipe, const uint64_t history_hash)
Definition pixelpipe_hb.h:388
static uint64_t dt_dev_backbuf_get_hash(const dt_backbuf_t *backbuf)
Definition pixelpipe_hb.h:197
dt_dev_pixelpipe_cache_request_t
Definition pixelpipe_hb.h:176
@ DT_DEV_PIXELPIPE_CACHE_REQUEST_MODULE
Definition pixelpipe_hb.h:179
static void dt_dev_pixelpipe_set_changed(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_change_t v)
Definition pixelpipe_hb.h:398
static gboolean dt_dev_pixelpipe_has_shutdown(const dt_dev_pixelpipe_t *pipe)
Definition pixelpipe_hb.h:462
dt_pixelpipe_flow_t
Definition pixelpipe_process.h:14
@ PIXELPIPE_FLOW_HISTOGRAM_ON_GPU
Definition pixelpipe_process.h:18
@ PIXELPIPE_FLOW_HISTOGRAM_NONE
Definition pixelpipe_process.h:16
@ PIXELPIPE_FLOW_PROCESSED_ON_CPU
Definition pixelpipe_process.h:19
@ PIXELPIPE_FLOW_PROCESSED_WITH_TILING
Definition pixelpipe_process.h:21
@ PIXELPIPE_FLOW_PROCESSED_ON_GPU
Definition pixelpipe_process.h:20
@ PIXELPIPE_FLOW_NONE
Definition pixelpipe_process.h:15
@ PIXELPIPE_FLOW_BLENDED_ON_CPU
Definition pixelpipe_process.h:22
@ PIXELPIPE_FLOW_HISTOGRAM_ON_CPU
Definition pixelpipe_process.h:17
@ PIXELPIPE_FLOW_BLENDED_ON_GPU
Definition pixelpipe_process.h:23
static void _reset_piece_cache_entry(dt_dev_pixelpipe_iop_t *piece)
Drop the writable-reuse snapshot attached to a pipeline piece.
Definition pixelpipe_process.h:59
static gboolean _bypass_cache(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Tell whether the current pipeline state forbids keeping this module output in cache.
Definition pixelpipe_process.h:45
dt_pixelpipe_blend_transform_t
Definition pixelpipe_process.h:27
@ DT_DEV_PIXELPIPE_BLEND_TRANSFORM_INPUT
Definition pixelpipe_process.h:29
@ DT_DEV_PIXELPIPE_BLEND_TRANSFORM_NONE
Definition pixelpipe_process.h:28
@ DT_DEV_PIXELPIPE_BLEND_TRANSFORM_OUTPUT
Definition pixelpipe_process.h:30
Raster-mask retrieval and transport through already-processed pipeline nodes.
Raw-detail mask transport helpers.
const float uint32_t state[4]
Definition src/develop/noise_generator.h:72
const float r
Definition src/develop/noise_generator.h:101
unsigned __int64 uint64_t
Definition strptime.c:75
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:789
struct dt_opencl_t * opencl
Definition darktable.h:784
int32_t unmuted
Definition darktable.h:759
dt_pthread_mutex_t pipeline_threadsafe
Definition darktable.h:807
char * main_message
Definition darktable.h:836
Definition pixelpipe_hb.h:96
gboolean enabled
Definition pixelpipe_hb.h:111
dt_dev_request_flags_t request_histogram
Definition pixelpipe_hb.h:114
uint64_t global_hash
Definition pixelpipe_hb.h:125
dt_iop_buffer_dsc_t dsc_in
Definition pixelpipe_hb.h:142
struct dt_iop_module_t *void * data
Definition pixelpipe_hb.h:97
GHashTable * raster_masks
Definition pixelpipe_hb.h:161
void * blendop_data
Definition pixelpipe_hb.h:110
Definition pixelpipe_hb.h:218
dt_colorspaces_color_profile_type_t icc_type
Definition pixelpipe_hb.h:310
int iwidth
Definition pixelpipe_hb.h:227
int opencl_error
Definition pixelpipe_hb.h:291
gboolean gui_observable_source
Definition pixelpipe_hb.h:304
gchar * icc_filename
Definition pixelpipe_hb.h:311
uint64_t last_history_hash
Definition pixelpipe_hb.h:323
dt_pthread_mutex_t busy_mutex
Definition pixelpipe_hb.h:259
gboolean flush_cache
Definition pixelpipe_hb.h:354
int mask_display
Definition pixelpipe_hb.h:295
GList * nodes
Definition pixelpipe_hb.h:245
dt_imageio_levels_t levels
Definition pixelpipe_hb.h:306
dt_atomic_int realtime
Definition pixelpipe_hb.h:287
dt_backbuf_t backbuf
Definition pixelpipe_hb.h:250
gboolean reentry
Definition pixelpipe_hb.h:342
dt_mipmap_size_t size
Definition pixelpipe_hb.h:224
dt_iop_color_intent_t icc_intent
Definition pixelpipe_hb.h:312
dt_atomic_int shutdown
Definition pixelpipe_hb.h:276
uint64_t reentry_hash
Definition pixelpipe_hb.h:348
int opencl_enabled
Definition pixelpipe_hb.h:289
dt_dev_pixelpipe_type_t type
Definition pixelpipe_hb.h:300
float iscale
Definition pixelpipe_hb.h:232
int32_t imgid
Definition pixelpipe_hb.h:223
gboolean no_cache
Definition pixelpipe_hb.h:362
gboolean store_all_raster_masks
Definition pixelpipe_hb.h:318
uint64_t rawdetail_mask_hash
Definition pixelpipe_hb.h:266
int iheight
Definition pixelpipe_hb.h:227
GList * forms
Definition pixelpipe_hb.h:316
int devid
Definition pixelpipe_hb.h:308
int output_imgid
Definition pixelpipe_hb.h:270
struct dt_develop_t * dev
Definition pixelpipe_hb.h:220
GList * iop_order_list
Definition pixelpipe_hb.h:314
Definition blend.h:198
Definition develop.h:159
int32_t gui_attached
Definition develop.h:162
GList * iop_order_list
Definition develop.h:274
dt_image_t image_storage
Definition develop.h:248
struct dt_develop_t::@19 color_picker
Authoritative darkroom color-picker state.
GList * iop
Definition develop.h:268
struct dt_iop_module_t * pending_module
Definition develop.h:376
int completed
Definition develop.h:462
struct dt_dev_pixelpipe_t * pending_pipe
Definition develop.h:377
dt_pthread_rwlock_t masks_mutex
Definition develop.h:304
struct dt_develop_t::@26 progress
uint64_t piece_hash
Definition develop.h:372
int total
Definition develop.h:462
GList * forms
Definition develop.h:292
Definition tiling.h:39
float factor
Definition tiling.h:41
unsigned overhead
Definition tiling.h:49
float maxbuf
Definition tiling.h:45
Definition format.h:52
int cst
Definition format.h:88
unsigned int channels
Definition format.h:54
dt_iop_buffer_type_t datatype
Definition format.h:56
Definition imageop.h:246
GModule *dt_dev_operation_t op
Definition imageop.h:256
Region of interest passed through the pixelpipe.
Definition imageop.h:72
int width
Definition imageop.h:73
int height
Definition imageop.h:73
int error_count
Definition opencl.h:226
int stopped
Definition opencl.h:224
Definition pixelpipe_cache.h:87
uint64_t hash
Definition pixelpipe_cache.h:88
void * data
Definition pixelpipe_cache.h:90
Definition darktable.h:840
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29