Skip to content

Commit

Permalink
De-implement the fast pipe mode
Browse files Browse the repository at this point in the history
The fast pipe mode is a hack by someone who didn't know that the mask API already has everything needed to slap a mask preview onto the end of the pipeline while bypassing al the intermediate steps.

The last thing the pipe needs is to handle another special case.
  • Loading branch information
aurelienpierre committed Dec 3, 2023
1 parent c975816 commit b22821d
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 186 deletions.
2 changes: 0 additions & 2 deletions src/develop/pixelpipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ typedef enum dt_dev_pixelpipe_type_t
DT_DEV_PIXELPIPE_PREVIEW2 = 1 << 4,
DT_DEV_PIXELPIPE_ANY = DT_DEV_PIXELPIPE_EXPORT | DT_DEV_PIXELPIPE_FULL | DT_DEV_PIXELPIPE_PREVIEW
| DT_DEV_PIXELPIPE_THUMBNAIL | DT_DEV_PIXELPIPE_PREVIEW2,
DT_DEV_PIXELPIPE_FAST = 1 << 8
} dt_dev_pixelpipe_type_t;

/** when to collect histogram */
Expand Down Expand Up @@ -81,4 +80,3 @@ const char *dt_pixelpipe_name(dt_dev_pixelpipe_type_t pipe);
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
// clang-format on

36 changes: 8 additions & 28 deletions src/develop/pixelpipe_hb.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,31 +69,21 @@ static void get_output_format(dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe,

static char *_pipe_type_to_str(int pipe_type)
{
const gboolean fast = (pipe_type & DT_DEV_PIXELPIPE_FAST) == DT_DEV_PIXELPIPE_FAST;
char *r = NULL;

switch(pipe_type & DT_DEV_PIXELPIPE_ANY)
{
case DT_DEV_PIXELPIPE_PREVIEW:
if(fast)
r = "preview/fast";
else
r = "preview";
r = "preview";
break;
case DT_DEV_PIXELPIPE_FULL:
r = "full";
break;
case DT_DEV_PIXELPIPE_THUMBNAIL:
if(fast)
r = "thumbnail/fast";
else
r = "thumbnail";
r = "thumbnail";
break;
case DT_DEV_PIXELPIPE_EXPORT:
if(fast)
r = "export/fast";
else
r = "export";
r = "export";
break;
default:
r = "unknown";
Expand Down Expand Up @@ -342,7 +332,7 @@ void dt_pixelpipe_get_global_hash(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
*/

// bernstein hash (djb2)
uint64_t hash = 5381 ^ pipe->output_imgid;
uint64_t hash = dt_hash(5381, (const char *)&pipe->output_imgid, sizeof(int));

for(GList *node = pipe->nodes; node; node = g_list_next(node))
{
Expand Down Expand Up @@ -512,7 +502,7 @@ void dt_dev_pixelpipe_change(dt_dev_pixelpipe_t *pipe, struct dt_develop_t *dev)

dt_pthread_mutex_lock(&dev->history_mutex);

dt_print(DT_DEBUG_PARAMS, "[pixelpipe] pipeline state changing for pipe %i, flag %i\n", pipe->type, pipe->changed);
dt_print(DT_DEBUG_DEV, "[pixelpipe] pipeline state changing for pipe %i, flag %i\n", pipe->type, pipe->changed);

/*
* Those cases seem mutually-exclusive but are not.
Expand Down Expand Up @@ -1133,7 +1123,6 @@ static int pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev,
static uint64_t _default_pipe_hash(dt_dev_pixelpipe_t *pipe)
{
uint64_t hash = dt_hash(5381, (const char *)&pipe->image.id, sizeof(uint32_t));
hash += (pipe->type & DT_DEV_PIXELPIPE_FAST);
return hash;
}

Expand All @@ -1150,10 +1139,6 @@ static uint64_t _node_hash(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_
// We need to amend our module global_hash to represent that.
hash = dt_hash(hash, (const char *)roi_out, sizeof(dt_iop_roi_t));

// Again for fast pipe
const uint32_t fast_pipe = (pipe->type & DT_DEV_PIXELPIPE_FAST);
hash = dt_hash(hash, (const char *)&fast_pipe, sizeof(uint32_t));

return hash;
}

Expand All @@ -1174,13 +1159,6 @@ static int dt_dev_pixelpipe_process_rec(dt_dev_pixelpipe_t *pipe, dt_develop_t *
dt_iop_module_t *module = NULL;
dt_dev_pixelpipe_iop_t *piece = NULL;

// if a module is active, check if this module allow a fast pipe run

if(darktable.develop && dev->gui_module && dev->gui_module->flags() & IOP_FLAGS_ALLOW_FAST_PIPE)
pipe->type |= DT_DEV_PIXELPIPE_FAST;
else
pipe->type &= ~DT_DEV_PIXELPIPE_FAST;

if(modules)
{
module = (dt_iop_module_t *)modules->data;
Expand Down Expand Up @@ -1213,8 +1191,10 @@ static int dt_dev_pixelpipe_process_rec(dt_dev_pixelpipe_t *pipe, dt_develop_t *
if(cache_available)
{
if(module)
dt_print(DT_DEBUG_PARAMS, "[pixelpipe] dt_dev_pixelpipe_process_rec, cache available for pipe %i and module %s with hash %lu\n",
dt_print(DT_DEBUG_DEV, "[pixelpipe] dt_dev_pixelpipe_process_rec, cache available for pipe %i and module %s with hash %lu\n",
pipe->type, module->op, hash);
else
dt_print(DT_DEBUG_DEV, "[pixelpipe] dt_dev_pixelpipe_process_rec has no module at pos %i\n", pos);

(void)dt_dev_pixelpipe_cache_get(&(pipe->cache), hash, bufsize, output, out_format);

Expand Down
3 changes: 1 addition & 2 deletions src/iop/cacorrect.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
const uint32_t filters = piece->pipe->dsc.filters;

const gboolean valid = MAX(width, height) >= CA_SIZE_MINIMUM;
const gboolean run_fast = (piece->pipe->type & DT_DEV_PIXELPIPE_FAST) == DT_DEV_PIXELPIPE_FAST;

dt_iop_cacorrect_data_t *d = (dt_iop_cacorrect_data_t *)piece->data;

Expand All @@ -296,7 +295,7 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const

dt_iop_image_copy_by_size(out, in2, width, height, 1);

if(!valid || run_fast) return;
if(!valid) return;

const float *const in = out;

Expand Down
3 changes: 1 addition & 2 deletions src/iop/demosaic.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,6 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
roo.x = roo.y = 0;
// roi_out->scale = global scale: (iscale == 1.0, always when demosaic is on)
const gboolean info = ((darktable.unmuted & (DT_DEBUG_DEMOSAIC | DT_DEBUG_PERF)) && (piece->pipe->type == DT_DEV_PIXELPIPE_FULL));
const gboolean run_fast = (piece->pipe->type & DT_DEV_PIXELPIPE_FAST) == DT_DEV_PIXELPIPE_FAST;

const uint8_t(*const xtrans)[6] = (const uint8_t(*const)[6])piece->pipe->dsc.xtrans;

Expand Down Expand Up @@ -627,7 +626,7 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const

dt_dev_write_rawdetail_mask(piece, tmp, roi_in, DT_DEV_DETAIL_MASK_DEMOSAIC);

if((demosaicing_method & DEMOSAIC_DUAL) && !run_fast)
if((demosaicing_method & DEMOSAIC_DUAL))
{
dual_demosaic(piece, tmp, pixels, &roo, &roi, piece->pipe->dsc.filters, xtrans, showmask, data->dual_thrs);
}
Expand Down
172 changes: 29 additions & 143 deletions src/iop/dither.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,7 @@ static int get_dither_parameters(const dt_iop_dither_data_t *const data, const d
#endif
static void process_floyd_steinberg(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece,
const void *const ivoid, void *const ovoid,
const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out,
int fast_mode)
const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
{
const dt_iop_dither_data_t *const restrict data = (dt_iop_dither_data_t *)piece->data;

Expand Down Expand Up @@ -441,77 +440,23 @@ static void process_floyd_steinberg(struct dt_iop_module_t *self, dt_dev_pixelpi
}

// floyd-steinberg dithering follows here

if (fast_mode)
// do the bulk of the image (all except the last row)
for(int j = 0; j < height - 1; j++)
{
// do the bulk of the image (all except the last one or two rows)
for(int j = 0; j < height - 2; j += 2)
{
const float *const restrict inrow = in + (size_t)4 * j * width;
float *const restrict outrow = out + (size_t)4 * j * width;

// first two columns
PROCESS_PIXEL_LEFT(outrow, inrow); // leftmost pixel in first (upper) row
PROCESS_PIXEL_FULL(outrow + right, inrow + right); // second pixel in first (upper) row
PROCESS_PIXEL_LEFT(outrow + down, inrow + down); // leftmost in second (lower) row
const float *const restrict inrow = in + (size_t)4 * j * width;
float *const restrict outrow = out + (size_t)4 * j * width;

// main part of the current pair of rows
for(int i = 1; i < width - 1; i++)
{
float *const restrict pixel = outrow + 4 * i;
PROCESS_PIXEL_FULL(pixel, inrow + 4 * i);
PROCESS_PIXEL_FULL(pixel + downleft, inrow + 4 * i + downleft);
}
// first two columns
PROCESS_PIXEL_LEFT(outrow, inrow); // leftmost pixel in first (upper) row

// last column of upper row
float *const restrict lastpixel = outrow + 4 * (width-1);
PROCESS_PIXEL_RIGHT(lastpixel);
// we have two pixels left over in the lower row
const float *const restrict lower_in = inrow + 4 * (width-1) + downleft;
PROCESS_PIXEL_FULL(lastpixel + downleft, lower_in);
// and now process the final pixel in the lower row
PROCESS_PIXEL_RIGHT(lastpixel + down);
}

// next-to-last row, if the total number of rows is even
if ((height & 1) == 0)
// main part of the current row
for(int i = 1; i < width - 1; i++)
{
const float *const restrict inrow = in + (size_t)4 * (height - 2) * width;
float *const restrict outrow = out + (size_t)4 * (height - 2) * width;

// first column
PROCESS_PIXEL_LEFT(outrow, inrow);

// main part of image
for(int i = 1; i < width - 1; i++)
{
PROCESS_PIXEL_FULL(outrow + 4 * i, inrow + 4 * i);
}

// last column
PROCESS_PIXEL_RIGHT(outrow + 4 * (width-1));
PROCESS_PIXEL_FULL(outrow + 4 * i, inrow + 4 * i);
}
}
else // use slower version which generates output identical to previous releases
{
// do the bulk of the image (all except the last row)
for(int j = 0; j < height - 1; j++)
{
const float *const restrict inrow = in + (size_t)4 * j * width;
float *const restrict outrow = out + (size_t)4 * j * width;

// first two columns
PROCESS_PIXEL_LEFT(outrow, inrow); // leftmost pixel in first (upper) row

// main part of the current row
for(int i = 1; i < width - 1; i++)
{
PROCESS_PIXEL_FULL(outrow + 4 * i, inrow + 4 * i);
}

// last column of upper row
PROCESS_PIXEL_RIGHT(outrow + 4 * (width-1));
}
// last column of upper row
PROCESS_PIXEL_RIGHT(outrow + 4 * (width-1));
}

// final row
Expand Down Expand Up @@ -541,8 +486,7 @@ static void process_floyd_steinberg(struct dt_iop_module_t *self, dt_dev_pixelpi
#endif
static void process_floyd_steinberg_sse2(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece,
const void *const ivoid, void *const ovoid,
const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out,
int fast_mode)
const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
{
dt_iop_dither_data_t *data = (dt_iop_dither_data_t *)piece->data;

Expand Down Expand Up @@ -621,82 +565,26 @@ static void process_floyd_steinberg_sse2(struct dt_iop_module_t *self, dt_dev_pi
}

// floyd-steinberg dithering follows here

if (fast_mode)
// do the bulk of the image (all except the last one or two rows)
for(int j = 0; j < height - 1; j++)
{
// do the bulk of the image (all except the last one or two rows)
for(int j = 0; j < height - 2; j += 2)
{
const float *const restrict inrow = in + (size_t)4 * j * width;
float *const restrict outrow = out + (size_t)4 * j * width;
__m128 err;

// first two columns
PROCESS_PIXEL_LEFT_SSE(outrow, inrow); // left-most pixel in first (upper) row
PROCESS_PIXEL_FULL_SSE(outrow + right, inrow + right); // second pixel in first (upper) row
PROCESS_PIXEL_LEFT_SSE(outrow + down, inrow + down); // leftmost in second (lower) row

// main part of the current pair of rows
for(int i = 2; i < width - 1; i++)
{
float *const restrict pixel = outrow + 4 * i;
PROCESS_PIXEL_FULL_SSE(pixel, inrow + 4 * i); // pixel in upper row
PROCESS_PIXEL_FULL_SSE(pixel + downleft, inrow + 4 * i + downleft); // pixel in lower row
}
const float *const restrict inrow = in + (size_t)4 * j * width;
float *const restrict outrow = out + (size_t)4 * j * width;
__m128 err;

// last column of upper row
float *const restrict lastpixel = outrow + 4 * (width-1);
PROCESS_PIXEL_RIGHT_SSE(lastpixel);
// we have two pixels left over in the lower row
const float *const restrict lower_in = inrow + 4 * (width-1) + downleft;
PROCESS_PIXEL_FULL_SSE(lastpixel + downleft, lower_in);
// and now process the final pixel in the lower row
PROCESS_PIXEL_RIGHT_SSE(lastpixel + down);
}
// first two columns
PROCESS_PIXEL_LEFT_SSE(outrow, inrow);

// next-to-last row, if the total number of rows is even
if ((height & 1) == 0)
// main part of the current row
for(int i = 1; i < width - 1; i++)
{
const float *const restrict inrow = in + (size_t)4 * (height - 2) * width;
float *const restrict outrow = out + (size_t)4 * (height - 2) * width;
__m128 err;

// first column
PROCESS_PIXEL_LEFT_SSE(outrow, inrow);

// main part of image
for(int i = 1; i < width - 1; i++)
{
PROCESS_PIXEL_FULL_SSE(outrow + 4 * i, inrow + 4 * i);
}

// last column
PROCESS_PIXEL_RIGHT_SSE(outrow + 4 * (width-1));
float *const restrict pixel = outrow + 4 * i;
PROCESS_PIXEL_FULL_SSE(pixel, inrow + 4 * i); // pixel in upper row
}
}
else // use slower version which generates output identical to previous releases
{
// do the bulk of the image (all except the last one or two rows)
for(int j = 0; j < height - 1; j++)
{
const float *const restrict inrow = in + (size_t)4 * j * width;
float *const restrict outrow = out + (size_t)4 * j * width;
__m128 err;

// first two columns
PROCESS_PIXEL_LEFT_SSE(outrow, inrow);

// main part of the current row
for(int i = 1; i < width - 1; i++)
{
float *const restrict pixel = outrow + 4 * i;
PROCESS_PIXEL_FULL_SSE(pixel, inrow + 4 * i); // pixel in upper row
}

// last column of upper row
float *const restrict lastpixel = outrow + 4 * (width-1);
PROCESS_PIXEL_RIGHT_SSE(lastpixel);
}
// last column of upper row
float *const restrict lastpixel = outrow + 4 * (width-1);
PROCESS_PIXEL_RIGHT_SSE(lastpixel);
}

// final row
Expand Down Expand Up @@ -783,8 +671,7 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
process_random(self, piece, ivoid, ovoid, roi_in, roi_out);
else
{
const gboolean fastmode = (piece->pipe->type & DT_DEV_PIXELPIPE_FAST) == DT_DEV_PIXELPIPE_FAST;
process_floyd_steinberg(self, piece, ivoid, ovoid, roi_in, roi_out, fastmode);
process_floyd_steinberg(self, piece, ivoid, ovoid, roi_in, roi_out);
}
}

Expand All @@ -798,8 +685,7 @@ void process_sse2(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, c
process_random(self, piece, ivoid, ovoid, roi_in, roi_out);
else
{
const gboolean fastmode = (piece->pipe->type & DT_DEV_PIXELPIPE_FAST) == DT_DEV_PIXELPIPE_FAST;
process_floyd_steinberg_sse2(self, piece, ivoid, ovoid, roi_in, roi_out, fastmode);
process_floyd_steinberg_sse2(self, piece, ivoid, ovoid, roi_in, roi_out);
}
}
#endif
Expand Down
7 changes: 2 additions & 5 deletions src/iop/filmicrgb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2116,10 +2116,9 @@ void process(dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *c
}

float *const restrict reconstructed = dt_alloc_align_float((size_t)roi_out->width * roi_out->height * 4);
const gboolean run_fast = (piece->pipe->type & DT_DEV_PIXELPIPE_FAST) == DT_DEV_PIXELPIPE_FAST;

// if fast mode is not in use
if(!run_fast && recover_highlights && mask && reconstructed)
if(recover_highlights && mask && reconstructed)
{
// init the blown areas with noise to create particles
float *const restrict inpainted = dt_alloc_align_float((size_t)roi_out->width * roi_out->height * 4);
Expand Down Expand Up @@ -2474,9 +2473,7 @@ int process_cl(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_m
}
}

const gboolean run_fast = (piece->pipe->type & DT_DEV_PIXELPIPE_FAST) == DT_DEV_PIXELPIPE_FAST;

if(!run_fast && is_clipped > 0)
if(is_clipped > 0)
{
// Inpaint noise
const float noise_level = d->noise_level / scale;
Expand Down
Loading

0 comments on commit b22821d

Please sign in to comment.