[Bf-blender-cvs] [9b948b9] soc-2013-paint: Projective painting optimization:

Antony Riakiotakis noreply at git.blender.org
Thu Mar 27 19:15:57 CET 2014


Commit: 9b948b96a4e50e3b0580656e17cfa7231f54c457
Author: Antony Riakiotakis
Date:   Thu Mar 27 20:15:39 2014 +0200
https://developer.blender.org/rB9b948b96a4e50e3b0580656e17cfa7231f54c457

Projective painting optimization:

* Lazy tile publishing scheme so threads now do not wait for tile to be
initialized.

* Do not search for old tiles in projective painting when pushing since
we already know there is no existing one and we need them.

===================================================================

M	source/blender/editors/sculpt_paint/paint_image.c
M	source/blender/editors/sculpt_paint/paint_image_proj.c
M	source/blender/editors/sculpt_paint/paint_intern.h

===================================================================

diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 176e8c3..8576167 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -219,7 +219,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
 	return NULL;
 }
 
-void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj)
 {
 	ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
 	UndoImageTile *tile;
@@ -228,10 +228,14 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
 	void *data;
 
 	/* check if tile is already pushed */
-	data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
-	if (data)
-		return data;
-	
+
+	/* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
+	if (!proj) {
+		data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
+		if (data)
+			return data;
+	}
+
 	if (*tmpibuf == NULL)
 		*tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
 	
@@ -261,10 +265,18 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
 		*valid = &tile->valid;
 
 	undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
-	undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
 
+
+	/* in projective texturing we need to protect this part */
+	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;
 }
 
@@ -465,7 +477,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
 
 	for (ty = tiley; ty <= tileh; ty++)
 		for (tx = tilex; tx <= tilew; tx++)
-			image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL);
+			image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false);
 
 	ibuf->userflags |= IB_BITMAPDIRTY;
 	
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 711b25e..f660abc 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -175,6 +175,8 @@ BLI_INLINE unsigned char f_to_char(const float val)
 /* vert flags */
 #define PROJ_VERT_CULL 1
 
+#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 */
@@ -183,7 +185,7 @@ typedef struct ProjPaintImage {
 	ImBuf *ibuf;
 	ImagePaintPartialRedraw *partRedrawRect;
 	void **undoRect; /* only used to build undo tiles after painting */
-	void **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket.
+	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 */
 	int touch;
@@ -1394,35 +1396,41 @@ static int project_paint_pixel_sizeof(const short tool)
 	}
 }
 
-static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty, bool **valid)
+static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
 {
-	unsigned short *maskrect;
 	ProjPaintImage *pjIma = tinf->pjima;
+	bool generate_tile = false;
+	int tile_index = tx + ty * tinf->tile_width;
 
-	int tileindex = tx + ty * tinf->tile_width;
+	/* double check lock + lazy initialization will ensure we do not get waiting on other threads while
+	 * tile is copied */
+	if (UNLIKELY(!pjIma->undoRect[tile_index])) {
 
-	if (tinf->threaded)
-		BLI_lock_thread(LOCK_CUSTOM1);  /* Other threads could be modifying these vars */
+		if (tinf->threaded)
+			BLI_lock_thread(LOCK_CUSTOM1);  /* Other threads could be modifying these vars */
 
-	if (UNLIKELY(!pjIma->undoRect[tileindex])) {
-		if (tinf->masked) {
-			pjIma->undoRect[tileindex] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &maskrect, &pjIma->valid[tileindex]);
-			pjIma->maskRect[tileindex] = maskrect;
+		if (!pjIma->undoRect[tile_index]) {
+			generate_tile = true;
+			pjIma->undoRect[tile_index] = TILE_PENDING;
 		}
-		else
-			pjIma->undoRect[tileindex] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tileindex]);
+		if (tinf->threaded)
+			BLI_unlock_thread(LOCK_CUSTOM1);
 
-		*valid = pjIma->valid[tileindex];
-		pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
 	}
-	else {
-		*valid = pjIma->valid[tileindex];
-	}
-
-	if (tinf->threaded)
-		BLI_unlock_thread(LOCK_CUSTOM1);
 
-	return tileindex;
+	if (generate_tile) {
+		void *undorect;
+		if (tinf->masked) {
+			undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true);
+		}
+		else {
+			undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true);
+		}
+		pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+		/* all ready, publish */
+		pjIma->undoRect[tile_index] = undorect;
+	}
+	return tile_index;
 }
 
 /* run this function when we know a bucket's, face's pixel can be initialized,
@@ -1464,18 +1472,24 @@ static ProjPixel *project_paint_uvpixel_init(
 	//memset(projPixel, 0, size);
 
 	tile_offset = (x_px - x_round) + (y_px - y_round) * IMAPAINT_TILE_SIZE;
-	tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile, &projPixel->valid);
+	tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
 
 	BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
 	BLI_assert(tile_offset < (IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE));
 
+	/* wait for other thread to initialize the tile */
+	while (projima->undoRect[tile_index] == TILE_PENDING)
+		;
+
+	projPixel->valid = projima->valid[tile_index];
+
 	if (ibuf->rect_float) {
 		projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
 		projPixel->origColor.f_pt = (float *)projima->undoRect[tile_index] + 4 * tile_offset;
 		zero_v4(projPixel->newColor.f);
 	}
 	else {
-		projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
+		projPixel->pixel.ch_pt = (unsigned char *)(ibuf->rect + (x_px + y_px * ibuf->x));
 		projPixel->origColor.uint_pt = (unsigned int *)projima->undoRect[tile_index] + tile_offset;
 		projPixel->newColor.uint = 0;
 	}
@@ -1492,7 +1506,7 @@ static ProjPixel *project_paint_uvpixel_init(
 
 	projPixel->mask = (unsigned short)(mask * 65535);
 	if (ps->do_masking)
-		projPixel->mask_accum = (unsigned short *)projima->maskRect[tile_index] + tile_offset;
+		projPixel->mask_accum = projima->maskRect[tile_index] + tile_offset;
 	else
 		projPixel->mask_accum = NULL;
 
@@ -3423,7 +3437,7 @@ static void project_paint_begin(ProjPaintState *ps)
 		memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
 		projIma->undoRect = (void **) BLI_memarena_alloc(arena, size);
 		memset(projIma->undoRect, 0, size);
-		projIma->maskRect = (void **) BLI_memarena_alloc(arena, size);
+		projIma->maskRect = (unsigned short **) BLI_memarena_alloc(arena, size);
 		memset(projIma->maskRect, 0, size);
 		projIma->valid = (bool **) BLI_memarena_alloc(arena, size);
 		memset(projIma->valid, 0, size);
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 04a55ae..b3b483d 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -146,7 +146,7 @@ typedef struct ImagePaintPartialRedraw {
 
 int image_texture_paint_poll(struct bContext *C);
 void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate);
-void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile,  unsigned short **, bool **valid);
+void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile,  unsigned short **, bool **valid, bool proj);
 void image_undo_remove_masks(void);
 void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
 struct ImagePaintPartialRedraw *get_imapaintpartial(void);




More information about the Bf-blender-cvs mailing list