Skip to content

Commit

Permalink
Implement module in_focus process cache
Browse files Browse the repository at this point in the history
The pixelpipe cache offers *input* data for a module to be fully processed if all parameters including
blending stuff match.

This commit implements a single line cache only effective for a module being in focus *and* doing some blending.
Data are possibly read instead of module->process/_cl, if not found they are written after that.

colorspace correction and blending will be processed as before.

Overall this avoids the possibly costly processing of the module if in focus and response to changes in blending
are much faster.

See #18180
  • Loading branch information
jenshannoschwalm committed Jan 13, 2025
1 parent 57d7f14 commit e963243
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 8 deletions.
2 changes: 2 additions & 0 deletions src/develop/develop.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ void dt_dev_init(dt_develop_t *dev,
dev->iop_order_list = NULL;

dev->proxy.exposure.module = NULL;
dev->focus_cache.data = NULL;
dev->focus_cache.hash = 0;

dt_dev_init_chroma(dev);

Expand Down
7 changes: 7 additions & 0 deletions src/develop/develop.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,13 @@ typedef struct dt_develop_t
gboolean enabled;
} late_scaling;

// cache module processed output if in focus
struct
{
dt_hash_t hash;
float *data;
} focus_cache;

// the display profile related things (softproof, gamut check, profiles ...)
struct
{
Expand Down
7 changes: 6 additions & 1 deletion src/develop/imageop.c
Original file line number Diff line number Diff line change
Expand Up @@ -2357,7 +2357,12 @@ void dt_iop_request_focus(dt_iop_module_t *module)

dev->gui_module = module;
dev->focus_hash = TRUE;

if(dev->focus_cache.data)
{
dt_free_align(dev->focus_cache.data);
dev->focus_cache.data = NULL;
dev->focus_cache.hash = 0;
}
/* lets lose the focus of previous focus module*/
if(out_focus_module)
{
Expand Down
119 changes: 112 additions & 7 deletions src/develop/pixelpipe_hb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,44 @@ static void _collect_histogram_on_CPU(dt_dev_pixelpipe_t *pipe,
}
}

/* calculates a hash including all piece hashes from below this module plus
plus id's from the module-in-questing but don't include blending data.
*/
static inline dt_hash_t _piece_process_hash(dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi, dt_iop_module_t *module)
{
dt_hash_t phash = dt_dev_pixelpipe_cache_hash(piece->pipe->image.id, roi, piece->pipe, module->iop_order -1);
phash = dt_hash(phash, roi, sizeof(dt_iop_roi_t));
phash = dt_hash(phash, &module->so->op, strlen(module->so->op));
phash = dt_hash(phash, &module->instance, sizeof(module->instance));
phash = dt_hash(phash, module->params, module->params_size);

return phash;
}

static inline gboolean _piece_fast_blend(dt_dev_pixelpipe_iop_t *piece, dt_iop_module_t *module)
{
return (piece->pipe->type & DT_DEV_PIXELPIPE_FULL)
&& module->dev
&& module->dev->gui_attached
&& module == module->dev->gui_module
&& dt_dev_modulegroups_test_activated(darktable.develop)
&& _transform_for_blend(module, piece);
}

static inline gboolean _has_blend_cache(const dt_hash_t hash)
{
return darktable.develop->focus_cache.data
&& hash == darktable.develop->focus_cache.hash;
}

static inline float *_get_fast_blendcache(const size_t nfloats, const dt_hash_t phash)
{
dt_free_align(darktable.develop->focus_cache.data);
darktable.develop->focus_cache.data = dt_alloc_align_float(nfloats);
darktable.develop->focus_cache.hash = phash;
return darktable.develop->focus_cache.data;
}

static gboolean _pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe,
dt_develop_t *dev,
float *input,
Expand Down Expand Up @@ -1156,8 +1194,8 @@ static gboolean _pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe,
work_profile ? dt_colorspaces_get_name(work_profile->type, work_profile->filename) : "no work profile");

// transform to module input colorspace
dt_ioppr_transform_image_colorspace
(module, input, input, roi_in->width, roi_in->height, cst_from,
dt_ioppr_transform_image_colorspace(
module, input, input, roi_in->width, roi_in->height, cst_from,
cst_to, &input_format->cst, work_profile);

if(dt_atomic_get_int(&pipe->shutdown))
Expand Down Expand Up @@ -1185,6 +1223,10 @@ static gboolean _pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe,
roi_in->width, roi_in->height, in_bpp,
TRUE, dt_dev_pixelpipe_type_to_str(piece->pipe->type));

const gboolean relevant = _piece_fast_blend(piece, module);
const dt_hash_t phash = relevant ? _piece_process_hash(piece, roi_out, module) : 0;
const size_t nfloats = (size_t)roi_out->width * roi_out->height * piece->colors;

if(!fitting && piece->process_tiling_ready)
{
dt_print_pipe(DT_DEBUG_PIPE,
Expand All @@ -1193,8 +1235,21 @@ static gboolean _pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe,
dt_iop_colorspace_to_name(cst_to),
cst_to != cst_out ? " -> " : "",
cst_to != cst_out ? dt_iop_colorspace_to_name(cst_out) : "");
module->process_tiling(module, piece, input, *output, roi_in, roi_out, in_bpp);

if(relevant && _has_blend_cache(phash))
{
dt_print_pipe(DT_DEBUG_PIPE, "copy from focus cache", piece->pipe, module, DT_DEVICE_CPU, roi_in, roi_out);
dt_iop_image_copy(*output, darktable.develop->focus_cache.data, nfloats);
}
else
{
module->process_tiling(module, piece, input, *output, roi_in, roi_out, in_bpp);
if(relevant)
{
dt_print_pipe(DT_DEBUG_PIPE, "copy to focus cache", piece->pipe, module, DT_DEVICE_CPU, roi_in, roi_out);
dt_iop_image_copy(_get_fast_blendcache(nfloats, phash), *output, nfloats);
}
}
*pixelpipe_flow |= (PIXELPIPE_FLOW_PROCESSED_ON_CPU
| PIXELPIPE_FLOW_PROCESSED_WITH_TILING);
*pixelpipe_flow &= ~(PIXELPIPE_FLOW_PROCESSED_ON_GPU);
Expand Down Expand Up @@ -1240,7 +1295,21 @@ static gboolean _pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe,
darktable.unmuted = old_muted;
}
}
module->process(module, piece, input, *output, roi_in, roi_out);

if(relevant && _has_blend_cache(phash))
{
dt_print_pipe(DT_DEBUG_PIPE, "copy from focus cache", piece->pipe, module, DT_DEVICE_CPU, roi_in, roi_out);
dt_iop_image_copy(*output, darktable.develop->focus_cache.data, nfloats);
}
else
{
module->process(module, piece, input, *output, roi_in, roi_out);
if(relevant)
{
dt_print_pipe(DT_DEBUG_PIPE, "copy to focus cache", piece->pipe, module, DT_DEVICE_CPU, roi_in, roi_out);
dt_iop_image_copy(_get_fast_blendcache(nfloats, phash), *output, nfloats);
}
}

*pixelpipe_flow |= (PIXELPIPE_FLOW_PROCESSED_ON_CPU);
*pixelpipe_flow &= ~(PIXELPIPE_FLOW_PROCESSED_ON_GPU
Expand Down Expand Up @@ -1905,8 +1974,25 @@ static gboolean _dev_pixelpipe_process_rec(dt_dev_pixelpipe_t *pipe,
dt_opencl_dump_pipe_pfm(module->op, pipe->devid, cl_mem_input,
TRUE, dt_dev_pixelpipe_type_to_str(piece->pipe->type));

const cl_int err = module->process_cl(module, piece, cl_mem_input, *cl_mem_output,
&roi_in, roi_out);
const gboolean relevant = _piece_fast_blend(piece, module);
const dt_hash_t phash = relevant ? _piece_process_hash(piece, roi_out, module) : 0;
cl_int err = CL_SUCCESS;

if(relevant && _has_blend_cache(phash))
{
dt_print_pipe(DT_DEBUG_PIPE, "copy from focus cache", piece->pipe, module, pipe->devid, &roi_in, roi_out);
err = dt_opencl_write_host_to_device(pipe->devid, darktable.develop->focus_cache.data, *cl_mem_output, roi_out->width, roi_out->height, out_bpp);
}
else
{
err = module->process_cl(module, piece, cl_mem_input, *cl_mem_output, &roi_in, roi_out);
if(relevant && (err == CL_SUCCESS))
{
const size_t nfloats = (size_t)roi_out->width * roi_out->height * piece->colors;
dt_print_pipe(DT_DEBUG_PIPE, "copy to focus cache", piece->pipe, module, pipe->devid, &roi_in, roi_out);
err = dt_opencl_read_host_from_device(pipe->devid, _get_fast_blendcache(nfloats, phash), *cl_mem_output, roi_out->width, roi_out->height, out_bpp);
}
}
success_opencl = (err == CL_SUCCESS);

if(!success_opencl)
Expand Down Expand Up @@ -2122,7 +2208,26 @@ static gboolean _dev_pixelpipe_process_rec(dt_dev_pixelpipe_t *pipe,
dt_iop_colorspace_to_name(cst_to),
cst_to != cst_out ? " -> " : "",
cst_to != cst_out ? dt_iop_colorspace_to_name(cst_out) : "");
const cl_int err = module->process_tiling_cl(module, piece, input, *output, &roi_in, roi_out, in_bpp);

const gboolean relevant = _piece_fast_blend(piece, module);
const dt_hash_t phash = relevant ? _piece_process_hash(piece, roi_out, module) : 0;
cl_int err = CL_SUCCESS;

if(relevant && _has_blend_cache(phash))
{
dt_print_pipe(DT_DEBUG_PIPE, "copy from focus cache", piece->pipe, module, pipe->devid, &roi_in, roi_out);
err = dt_opencl_write_host_to_device(pipe->devid, darktable.develop->focus_cache.data, *cl_mem_output, roi_out->width, roi_out->height, out_bpp);
}
else
{
err = module->process_tiling_cl(module, piece, input, *output, &roi_in, roi_out, in_bpp);
if(relevant && (err == CL_SUCCESS))
{
const size_t nfloats = (size_t)roi_out->width * roi_out->height * piece->colors;
dt_print_pipe(DT_DEBUG_PIPE, "copy to focus cache", piece->pipe, module, pipe->devid, &roi_in, roi_out);
err = dt_opencl_read_host_from_device(pipe->devid, _get_fast_blendcache(nfloats, phash), *cl_mem_output, roi_out->width, roi_out->height, out_bpp);
}
}
success_opencl = (err == CL_SUCCESS);

if(!success_opencl)
Expand Down

0 comments on commit e963243

Please sign in to comment.