[Bf-blender-cvs] [72e0a43] soc-2013-paint: Bring back lazy initialization with less time spent locking. It looks like cause was compile time reordering, nice volatile declarations solved the issue :). Nice speedup too!
Antony Riakiotakis
noreply at git.blender.org
Fri Mar 28 16:14:48 CET 2014
Commit: 72e0a43f2348b52267fa6f220846db54cc4a7b6b
Author: Antony Riakiotakis
Date: Fri Mar 28 17:13:03 2014 +0200
https://developer.blender.org/rB72e0a43f2348b52267fa6f220846db54cc4a7b6b
Bring back lazy initialization with less time spent locking. It looks
like cause was compile time reordering, nice volatile declarations
solved the issue :). Nice speedup too!
===================================================================
M source/blender/editors/sculpt_paint/paint_image.c
M source/blender/editors/sculpt_paint/paint_image_proj.c
===================================================================
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 1a042e5..2eb6382 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -266,9 +266,15 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
+ if (proj)
+ BLI_lock_thread(LOCK_CUSTOM1);
+
undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
BLI_addtail(lb, tile);
+ if (proj)
+ BLI_unlock_thread(LOCK_CUSTOM1);
+
return tile->rect.pt;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 446b32e..c9a2005 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -175,6 +175,9 @@ BLI_INLINE unsigned char f_to_char(const float val)
/* vert flags */
#define PROJ_VERT_CULL 1
+/* to avoid locking in tile initialization */
+#define TILE_PENDING SET_INT_IN_POINTER(-1)
+
/* This is mainly a convenience struct used so we can keep an array of images we use
* Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
* because 'partRedrawRect' and 'touch' values would not be thread safe */
@@ -182,7 +185,7 @@ typedef struct ProjPaintImage {
Image *ima;
ImBuf *ibuf;
ImagePaintPartialRedraw *partRedrawRect;
- void **undoRect; /* only used to build undo tiles after painting */
+ volatile void **undoRect; /* only used to build undo tiles after painting */
unsigned short **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket.
* Here we store the mask rectangle */
bool **valid; /* store flag to enforce validation of undo rectangle */
@@ -1398,22 +1401,35 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
{
ProjPaintImage *pjIma = tinf->pjima;
int tile_index = tx + ty * tinf->tile_width;
+ bool generate_tile = false;
+
+ /* double check lock to avoid locking */
+ if (UNLIKELY(!pjIma->undoRect[tile_index])) {
+ if (tinf->threaded)
+ BLI_lock_thread(LOCK_CUSTOM1);
+ if (LIKELY(!pjIma->undoRect[tile_index])) {
+ pjIma->undoRect[tile_index] = TILE_PENDING;
+ generate_tile = true;
+ }
+ if (tinf->threaded)
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ }
- if (tinf->threaded)
- BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
- if (!pjIma->undoRect[tile_index]) {
+ if (generate_tile) {
+ volatile void *undorect;
if (tinf->masked) {
- pjIma->undoRect[tile_index] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true);
+ undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true);
}
else {
- pjIma->undoRect[tile_index] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true);
+ undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true);
}
+
pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ /* tile ready, publish */
+ pjIma->undoRect[tile_index] = undorect;
}
- if (tinf->threaded)
- BLI_unlock_thread(LOCK_CUSTOM1);
return tile_index;
}
@@ -1434,7 +1450,9 @@ static ProjPixel *project_paint_uvpixel_init(
ProjPixel *projPixel;
int x_tile, y_tile;
int x_round, y_round;
- int tile_offset, tile_index;
+ int tile_offset;
+ /* volatile is important here to ensure pending check is not optimized away by compiler*/
+ volatile int tile_index;
ProjPaintImage *projima = tinf->pjima;
ImBuf *ibuf = projima->ibuf;
@@ -1458,6 +1476,10 @@ static ProjPixel *project_paint_uvpixel_init(
tile_offset = (x_px - x_round) + (y_px - y_round) * IMAPAINT_TILE_SIZE;
tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
+ /* other thread may be initializing the tile so wait here */
+ while (projima->undoRect[tile_index] == TILE_PENDING)
+ ;
+
BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
BLI_assert(tile_offset < (IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE));
@@ -3415,7 +3437,7 @@ static void project_paint_begin(ProjPaintState *ps)
size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- projIma->undoRect = (void **) BLI_memarena_alloc(arena, size);
+ projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
memset(projIma->undoRect, 0, size);
projIma->maskRect = (unsigned short **) BLI_memarena_alloc(arena, size);
memset(projIma->maskRect, 0, size);
More information about the Bf-blender-cvs
mailing list