Skip to content

Three ways to increase pixelpipe UI responsiveness #21274

Open
jenshannoschwalm wants to merge 5 commits into
darktable-org:masterfrom
jenshannoschwalm:pixelpipe_zoom_knocking
Open

Three ways to increase pixelpipe UI responsiveness #21274
jenshannoschwalm wants to merge 5 commits into
darktable-org:masterfrom
jenshannoschwalm:pixelpipe_zoom_knocking

Conversation

@jenshannoschwalm

@jenshannoschwalm jenshannoschwalm commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

EDIT according to latest commits: In short, this is all about how fast the UI responds to user actions while already processing the pipes, collected work ...

  1. 030c6e0 fixes two bugs when processing the pipe, a) there was a missing "stop pixelpipe check" in CPU code path thus in CPU code the response to changes in history was delayed , b) in some cases we didn't write back input cl_mem to the pixelpipe cache. Thus we were not completely sure about valid input data represented in cache. That was the reason for the two cache invalidations @masterpiga spotted. My code comments were slightly wrong and i was not completeöy sure why they seemed necessary ... Now all is good and those invalidations could go with this commit.
  2. 4e6297c removes pipe processing flag, introduces DT_DEV_PIXELPIPE_PROCESSING as a shutdown "mode" and makes callers aware of this
  3. 7c5ad38 handles faster shutdown response for history changes if we are in the middle of a long diffuse process.
  4. 426419b introduces a new shutdown mode reducing UI responsiveness for drags & zooms quite a lot.
  5. ca0e461 removes pipe obsolete flag as not required any more since pipe cache is now fully implemented.

@jenshannoschwalm jenshannoschwalm added this to the 5.8 milestone Jun 7, 2026
@jenshannoschwalm jenshannoschwalm added feature: enhancement current features to improve scope: UI user interface and interactions scope: image processing correcting pixels scope: performance doing everything the same but faster scope: codebase making darktable source code easier to manage OpenCL Related to darktable OpenCL code labels Jun 7, 2026
@jenshannoschwalm jenshannoschwalm force-pushed the pixelpipe_zoom_knocking branch from 7cb21b7 to 3bcc3bf Compare June 8, 2026 03:45
@jenshannoschwalm jenshannoschwalm force-pushed the pixelpipe_zoom_knocking branch 4 times, most recently from 07a4847 to c404091 Compare June 16, 2026 06:56
@jenshannoschwalm

Copy link
Copy Markdown
Collaborator Author

Latest force-push further adds:

  1. Integrate pipe->processing into the shutdown modes
  2. removal of pipe->obsolete

@jenshannoschwalm jenshannoschwalm force-pushed the pixelpipe_zoom_knocking branch 2 times, most recently from ca0e461 to 21088ad Compare June 19, 2026 06:23
- Major _module_pipe_stop() work
  If we find pipe shutdown reflecting an iop_order we invalidate cachelines for the
  specified iop_order as output is unsafe.
  As the input cacheline either
    - requires updating as we possibly have done some colorspace conversion
    - or does not have any valid data at all
  we write back the cl_mem to host to have valid cacheline data for the next pixelpipe run.

- we don't have to invalidate input data cachelines because of in-space colorspace correctiosn,
  the cache cst has been updated and data have been written back in all cases via (1)

- The pixelpipe CPU path missed a _module_pipe_stop()

- Added and use dt_dev_pixelpipe_cache_invalidate_iop()
  This invalidates cachelines claimed by this iop.

- Activate DT_PIPE_CAS_SHUTDOWN, now we only can set shutdown mode once per pixelpipe run.
  Also some log improvements here, we want this to be logged via -d pipe if relevant & new,
  otherwise the -d verbose switch must be used.

- as dt_opencl_copy_image_to_host() logs errors some dt_prints() got removed

- Some readability maintenance, comments ...
Adding DT_DEV_PIXELPIPE_PROCESSING mode to dt_dev_pixelpipe_stopper_t allows us to distinguish
between a processing pipe and an idle pipe.
- get rid of pipe->processing
- less housekeeping
For a fast UI response when switching darkroom HQ processing mode or changing history (setting pipe
shutdown to DT_DEV_PIXELPIPE_STOP_NODES) we may use dt_dev_pixelpipe_set_shutdown() *while* processing
a module to enforce a clean pipe shutdown asap.

The pixelpipe tests for those UI induced shutdown requests for an early exit at safe locations.
Yet a few heavy processing modules with high number of iterations (most notably diffuse) can lead
to a significant delay until such a safe point has been reached.

With this commit they can test for a requested shutdown via dt_dev_pixelpipe_piece_shutdown() and
possibly stop iterating, cacheline integrity is kept by invalidating incorrect output.
Currently we use dt_dev_pixelpipe_set_shutdown() to stop a running pixelpipe asap, this is
used for changing the nodes involved in the pipe (history changes) or when toggling between
darkroom HQ mode on/off as examples, we do this for UI responsiveness.

Being in darkroom mode **while** the dt_dev_pixelpipe_process() is still running, a UI move of the
the displayed part of the main canvas or zooming-in/out results in a new control job which is
currently processed *after the complete* dt_dev_pixelpipe_process().

This commit adds an early-exit & restart pipe mechanism for a faster UI response, avoiding up to
one pixelpipe run with a good chance of finding valid pixelpipe cache data.

1. A new shutdown mode DT_DEV_PIXELPIPE_STOP_ZOOM has been added to dt_dev_pixelpipe_stopper_t.
   It is
   a) checked, reported and handled in dt_dev_process_image_job()
   b) tested in dt_dev_pixelpipe_process() via _module_pipe_stop() making sure the pipe
      possibly exits with TRUE state and a shutdown mode.
   In all cases we ensure pixelpipe cache integrity via _module_pipe_stop().

2. How is this shutdown mode induced?
   If we zoom in/out or reposition the main canvas we set shutdown to DT_DEV_PIXELPIPE_STOP_ZOOM
   in dt_dev_zoom_move() enforcing the pipe restart.
We had `obsolete` in dt_dev_pixelpipe_t for brute-force invalidation of all pipe cachelines while not
being fully sure about piece hashes and input OpenCL cachelines not written back if changed.

Not necessary any more, **if** we would want further help for cache efficiency that would go via testing
for DT_DEV_PIPE_REMOVE and/or DT_DEV_PIPE_SYNCH
@kofa73

kofa73 commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Rebased on top of current master, it does not look good. :-(
image
I opened a huge file (160 MPx), zoomed in/out like crazy as soon as I entered the darkroom, kept enabling/disabling modules. I don't see errors in the log (-d cache -d pipe -d tiling -d opencl -d cache -d common -d perf -d verbose)
pr-21274-160mpx.zip

I tried disabling OpenCL, turned modules on/off, panned, zoomed -- did not help, the editor preview remained black.

@jenshannoschwalm

Copy link
Copy Markdown
Collaborator Author

Arrg, yes i saw that too and fixed it on my local working brach but forgot to update and force-push.

@kofa73

kofa73 commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

No problem, thanks for the quick response!

I gave the changes to the bots, they came back with these (probably includes the stuff you fixed on your branch):

  • src/develop/pixelpipe_hb.c:2495 — OpenCL input colorspace conversion is written back to the host input cache line without updating that line's cst descriptor, leaving converted pixels labelled with the pre-conversion colorspace (wrong colours / double conversion on cache reuse).

    • Evidence: the OpenCL path transforms cl_mem_input in place to cst_to updating only the local input_cst_cl, not input_format->cst; in the tiling fallback the converted cl_mem_input is copied back into the host input cache buffer and the prior input_format->cst = input_cst_cl; assignment was deleted, while valid_input_on_gpu_only is set FALSE so the later invalidation is skipped; _writeback_clinput copies device data back into the host cache buffer on module pipe stop but has no access to the cache descriptor and never updates cache->dsc / input_format->cst; the early-shutdown writeback paths (_module_pipe_stop at ~2407 and ~2490) return before the normal successful-copy descriptor update at ~2697; during the CL blend step cl_mem_input is transformed to blend_cst before the shutdown check then written back, so the cache line can hold blend-colorspace data under the original descriptor; cache_get returns the cached data with its stale descriptor, so a later hit applies the conversion a second time on already-converted pixels.
  • src/develop/pixelpipe_hb.c:2337 — The blend-cache fast path was changed to gate on fast_blend instead of bcaching, so a candidate whose bcache_data is NULL or whose blend hash no longer matches is treated as a cache hit — copying stale/NULL host data to the GPU and skipping real module processing.

    • Evidence: bcaching is computed separately from fast_blend and additionally verifies pipe->bcache_data != NULL plus a matching hash, yet fast_blend can be true while phash differs from pipe->bcache_hash or while bcache_data is NULL; the direct OpenCL branch now checks fast_blend (not bcaching) and copies pipe->bcache_data into *cl_mem_output via dt_opencl_copy_host_to_image; module->process_cl() and the blend-cache refresh sit in the else branch, so they are skipped whenever fast_blend is true — and the non-tiled cache-refresh block guarded by if(fast_blend && err==CL_SUCCESS) is itself inside that else, making it unreachable on the non-tiled path.
  • src/develop/pixelpipe_hb.c:2251 — When the tiled OpenCL fallback's full-image input pre-copy fails, the path invalidates only the input cache line and returns TRUE without setting pipe->opencl_error or invalidating the already-reserved output cache line, so stale/uninitialised output can be cached and the pipe reported VALID with no CPU fallback.

    • Evidence: even when fits_on_device is false the possible_cl path first tries to copy the full input ROI into an OpenCL image, recording failure only in success_opencl; the tiling branch handles !success_opencl by invalidating only the input cache line and returning TRUE, without setting pipe->opencl_error and without CPU fallback; the module output cache line was already reserved and assigned the current hash (dt_dev_pixelpipe_cache_get writes cache->hash[cline]=hash before processing fills the buffer); CPU restart happens only for err && pipe->opencl_error, so otherwise the GUI job sets pipe->status = DT_DEV_PIXELPIPE_VALID and the stale output line is returned as a cache HIT on the next request for the same hash.

@jenshannoschwalm

jenshannoschwalm commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator Author

I will check again ... thanks EDIT: and will split the first commit from the rest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature: enhancement current features to improve OpenCL Related to darktable OpenCL code release notes: pending scope: codebase making darktable source code easier to manage scope: image processing correcting pixels scope: performance doing everything the same but faster scope: UI user interface and interactions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants