[Bf-blender-cvs] [6f83710] master: Optimize projection painting with big brushes

Sergey Sharybin noreply at git.blender.org
Thu May 5 14:45:50 CEST 2016


Commit: 6f83710af94a9f6d117ef60537329941cd8614fa
Author: Sergey Sharybin
Date:   Thu May 5 14:45:00 2016 +0200
Branches: master
https://developer.blender.org/rB6f83710af94a9f6d117ef60537329941cd8614fa

Optimize projection painting with big brushes

Multi-threaded partial buffer update, gives about 2x speedup with
big brushes.

Thanks Campbell for testing and benchmarking!

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

M	source/blender/imbuf/intern/divers.c

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

diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 455b78b..3aabf7e 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -674,25 +674,24 @@ void IMB_rect_from_float(ImBuf *ibuf)
 	ibuf->userflags &= ~IB_RECT_INVALID;
 }
 
-/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
-void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data)
-{
-	const float *rect_float;
+typedef struct PartialThreadData {
+	ImBuf *ibuf;
+	float *buffer;
 	uchar *rect_byte;
-	int profile_from = IB_PROFILE_LINEAR_RGB;
-
-	/* verify we have a float buffer */
-	if (ibuf->rect_float == NULL || buffer == NULL)
-		return;
-
-	/* create byte rect if it didn't exist yet */
-	if (ibuf->rect == NULL)
-		imb_addrectImBuf(ibuf);
-
-	/* do conversion */
-	rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
-	rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;
-
+	const float *rect_float;
+	int width;
+	bool is_data;
+} PartialThreadData;
+
+static void partial_rect_from_float_slice(float *buffer,
+                                          uchar *rect_byte,
+                                          ImBuf *ibuf,
+                                          const float *rect_float,
+                                          const int w,
+                                          const int h,
+                                          const bool is_data)
+{
+	const int profile_from = IB_PROFILE_LINEAR_RGB;
 	if (is_data) {
 		/* exception for non-color data, just copy float */
 		IMB_buffer_float_from_float(buffer, rect_float,
@@ -715,6 +714,58 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
 		                           4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
 		                           w, h, ibuf->x, w);
 	}
+}
+
+static void partial_rect_from_float_thread_do(void *data_v,
+                                              int start_scanline,
+                                              int num_scanlines)
+{
+	PartialThreadData *data = (PartialThreadData *)data_v;
+	ImBuf *ibuf = data->ibuf;
+	size_t global_offset = ((size_t)ibuf->x) * start_scanline;
+	size_t local_offset = ((size_t)data->width) * start_scanline;
+	partial_rect_from_float_slice(data->buffer + local_offset * ibuf->channels,
+	                              data->rect_byte + global_offset * 4,
+	                              ibuf,
+	                              data->rect_float + global_offset * ibuf->channels,
+	                              data->width,
+	                              num_scanlines,
+	                              data->is_data);
+}
+
+/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
+void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data)
+{
+	const float *rect_float;
+	uchar *rect_byte;
+
+	/* verify we have a float buffer */
+	if (ibuf->rect_float == NULL || buffer == NULL)
+		return;
+
+	/* create byte rect if it didn't exist yet */
+	if (ibuf->rect == NULL)
+		imb_addrectImBuf(ibuf);
+
+	/* do conversion */
+	rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
+	rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;
+
+	if (((size_t)w) * h < 64 * 64) {
+		partial_rect_from_float_slice(
+		        buffer, rect_byte, ibuf, rect_float, w, h, is_data);
+	}
+	else {
+		PartialThreadData data;
+		data.ibuf = ibuf;
+		data.buffer = buffer;
+		data.rect_byte = rect_byte;
+		data.rect_float = rect_float;
+		data.width = w;
+		data.is_data = is_data;
+		IMB_processor_apply_threaded_scanlines(
+		        h, partial_rect_from_float_thread_do, &data);
+	}
 
 	/* ensure user flag is reset */
 	ibuf->userflags &= ~IB_RECT_INVALID;




More information about the Bf-blender-cvs mailing list