[Bf-blender-cvs] [9b89071] master: Multi-thread generated image creation

Sergey Sharybin noreply at git.blender.org
Thu May 5 23:47:28 CEST 2016


Commit: 9b89071c9cdd2a341ba16db44cd4625303fb6e2f
Author: Sergey Sharybin
Date:   Thu May 5 23:33:40 2016 +0200
Branches: master
https://developer.blender.org/rB9b89071c9cdd2a341ba16db44cd4625303fb6e2f

Multi-thread generated image creation

Gives about 2x speedup on laptop when creating new hires generated image,
regardless of it's type (color, color grid, uv grid).

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

M	source/blender/blenkernel/intern/image_gen.c
M	source/blender/imbuf/IMB_imbuf.h
M	source/blender/imbuf/intern/divers.c

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

diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 650ccd4..2c8399a 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -38,7 +38,17 @@
 
 #include "BLF_api.h"
 
-void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4])
+typedef struct FillColorThreadData {
+	unsigned char *rect;
+	float *rect_float;
+	int width;
+	float color[4];
+} FillColorThreadData;
+
+static void image_buf_fill_color_slice(unsigned char *rect,
+                                       float *rect_float,
+                                       int width, int height,
+                                       const float color[4])
 {
 	int x, y;
 
@@ -53,15 +63,12 @@ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width,
 			}
 		}
 	}
-	
+
 	if (rect) {
 		unsigned char ccol[4];
-
 		rgba_float_to_uchar(ccol, color);
-
 		for (y = 0; y < height; y++) {
 			for (x = 0; x < width; x++) {
-				
 				rect[0] = ccol[0];
 				rect[1] = ccol[1];
 				rect[2] = ccol[2];
@@ -72,19 +79,55 @@ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width,
 	}
 }
 
+static void image_buf_fill_color_thread_do(void *data_v,
+                                           int start_scanline,
+                                           int num_scanlines)
+{
+	FillColorThreadData *data = (FillColorThreadData *)data_v;
+	size_t offset = ((size_t)start_scanline) * data->width * 4;
+	unsigned char *rect = (data->rect != NULL) ? (data->rect + offset) : NULL;
+	float *rect_float = (data->rect_float != NULL) ? (data->rect_float + offset) : NULL;
+	image_buf_fill_color_slice(rect,
+	                           rect_float,
+	                           data->width,
+	                           num_scanlines,
+	                           data->color);
+}
 
-void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height)
+void BKE_image_buf_fill_color(unsigned char *rect,
+                              float *rect_float,
+                              int width, int height,
+                              const float color[4])
 {
-	/* these two passes could be combined into one, but it's more readable and 
+	if (((size_t)width) * height < 64 * 64) {
+		image_buf_fill_color_slice(rect, rect_float, width, height, color);
+	}
+	else {
+		FillColorThreadData data;
+		data.rect = rect;
+		data.rect_float = rect_float;
+		data.width = width;
+		copy_v4_v4(data.color, color);
+		IMB_processor_apply_threaded_scanlines(
+		    height, image_buf_fill_color_thread_do, &data);
+	}
+}
+
+static void image_buf_fill_checker_slice(unsigned char *rect,
+                                         float *rect_float,
+                                         int width, int height,
+                                         int offset)
+{
+	/* these two passes could be combined into one, but it's more readable and
 	 * easy to tweak like this, speed isn't really that much of an issue in this situation... */
- 
+
 	int checkerwidth = 32, dark = 1;
 	int x, y;
 
 	unsigned char *rect_orig = rect;
 	float *rect_float_orig = rect_float;
 
-	
+
 	float h = 0.0, hoffs = 0.0;
 	float hsv[3] = {0.0f, 0.9f, 0.9f};
 	float rgb[3];
@@ -96,12 +139,12 @@ void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int widt
 	}
 
 	/* checkers */
-	for (y = 0; y < height; y++) {
+	for (y = offset; y < height + offset; y++) {
 		dark = powf(-1.0f, floorf(y / checkerwidth));
-		
+
 		for (x = 0; x < width; x++) {
 			if (x % checkerwidth == 0) dark = -dark;
-			
+
 			if (rect_float) {
 				if (dark > 0) {
 					rect_float[0] = rect_float[1] = rect_float[2] = dark_linear_color;
@@ -131,12 +174,12 @@ void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int widt
 	rect_float = rect_float_orig;
 
 	/* 2nd pass, colored + */
-	for (y = 0; y < height; y++) {
+	for (y = offset; y < height + offset; y++) {
 		hoffs = 0.125f * floorf(y / checkerwidth);
-		
+
 		for (x = 0; x < width; x++) {
 			h = 0.125f * floorf(x / checkerwidth);
-			
+
 			if ((abs((x % checkerwidth) - (checkerwidth / 2)) < 4) &&
 			    (abs((y % checkerwidth) - (checkerwidth / 2)) < 4))
 			{
@@ -145,14 +188,14 @@ void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int widt
 				{
 					hsv[0] = fmodf(fabsf(h - hoffs), 1.0f);
 					hsv_to_rgb_v(hsv, rgb);
-					
+
 					if (rect) {
 						rect[0] = (char)(rgb[0] * 255.0f);
 						rect[1] = (char)(rgb[1] * 255.0f);
 						rect[2] = (char)(rgb[2] * 255.0f);
 						rect[3] = 255;
 					}
-					
+
 					if (rect_float) {
 						srgb_to_linearrgb_v3_v3(rect_float, rgb);
 						rect_float[3] = 1.0f;
@@ -166,13 +209,55 @@ void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int widt
 	}
 }
 
+typedef struct FillCheckerThreadData {
+	unsigned char *rect;
+	float *rect_float;
+	int width;
+} FillCheckerThreadData;
+
+static void image_buf_fill_checker_thread_do(void *data_v,
+                                             int start_scanline,
+                                             int num_scanlines)
+{
+	FillCheckerThreadData *data = (FillCheckerThreadData *)data_v;
+	size_t offset = ((size_t)start_scanline) * data->width * 4;
+	unsigned char *rect = (data->rect != NULL) ? (data->rect + offset) : NULL;
+	float *rect_float = (data->rect_float != NULL) ? (data->rect_float + offset) : NULL;
+	image_buf_fill_checker_slice(rect,
+	                             rect_float,
+	                             data->width,
+	                             num_scanlines,
+	                             start_scanline);
+}
+
+void BKE_image_buf_fill_checker(unsigned char *rect,
+                                float *rect_float,
+                                int width, int height)
+{
+	if (((size_t)width) * height < 64 * 64) {
+		image_buf_fill_checker_slice(rect, rect_float, width, height, 0);
+	}
+	else {
+		FillCheckerThreadData data;
+		data.rect = rect;
+		data.rect_float = rect_float;
+		data.width = width;
+		IMB_processor_apply_threaded_scanlines(
+		    height, image_buf_fill_checker_thread_do, &data);
+	}
+}
 
 /* Utility functions for BKE_image_buf_fill_checker_color */
 
 #define BLEND_FLOAT(real, add)  (real + add <= 1.0f) ? (real + add) : 1.0f
 #define BLEND_CHAR(real, add) ((real + (char)(add * 255.0f)) <= 255) ? (real + (char)(add * 255.0f)) : 255
 
-static void checker_board_color_fill(unsigned char *rect, float *rect_float, int width, int height)
+static void checker_board_color_fill(unsigned char *rect,
+                                     float *rect_float,
+                                     int width,
+                                     int height,
+                                     int offset,
+                                     int total_height)
 {
 	int hue_step, y, x;
 	float hsv[3], rgb[3];
@@ -182,9 +267,9 @@ static void checker_board_color_fill(unsigned char *rect, float *rect_float, int
 	hue_step = power_of_2_max_i(width / 8);
 	if (hue_step < 8) hue_step = 8;
 
-	for (y = 0; y < height; y++) {
+	for (y = offset; y < height + offset; y++) {
 
-		hsv[2] = 0.1 + (y * (0.4 / height)); /* use a number lower then 1.0 else its too bright */
+		hsv[2] = 0.1 + (y * (0.4 / total_height)); /* use a number lower then 1.0 else its too bright */
 		for (x = 0; x < width; x++) {
 			hsv[0] = (float)((double)(x / hue_step) * 1.0 / width * hue_step);
 			hsv_to_rgb_v(hsv, rgb);
@@ -194,7 +279,7 @@ static void checker_board_color_fill(unsigned char *rect, float *rect_float, int
 				rect[1] = (char)(rgb[1] * 255.0f);
 				rect[2] = (char)(rgb[2] * 255.0f);
 				rect[3] = 255;
-				
+
 				rect += 4;
 			}
 
@@ -203,27 +288,35 @@ static void checker_board_color_fill(unsigned char *rect, float *rect_float, int
 				rect_float[1] = rgb[1];
 				rect_float[2] = rgb[2];
 				rect_float[3] = 1.0f;
-				
+
 				rect_float += 4;
 			}
 		}
 	}
 }
 
-static void checker_board_color_tint(unsigned char *rect, float *rect_float, int width, int height, int size, float blend)
+static void checker_board_color_tint(unsigned char *rect,
+                                     float *rect_float,
+                                     int width,
+                                     int height,
+                                     int size,
+                                     float blend,
+                                     int offset)
 {
 	int x, y;
 	float blend_half = blend * 0.5f;
 
-	for (y = 0; y < height; y++) {
+	for (y = offset; y < height + offset; y++) {
 		for (x = 0; x < width; x++) {
-			if (((y / size) % 2 == 1 && (x / size) % 2 == 1) || ( (y / size) % 2 == 0 && (x / size) % 2 == 0)) {
+			if (((y / size) % 2 == 1 && (x / size) % 2 == 1) ||
+			    ((y / size) % 2 == 0 && (x / size) % 2 == 0))
+			{
 				if (rect) {
 					rect[0] = (char)BLEND_CHAR(rect[0], blend);
 					rect[1] = (char)BLEND_CHAR(rect[1], blend);
 					rect[2] = (char)BLEND_CHAR(rect[2], blend);
 					rect[3] = 255;
-				
+
 					rect += 4;
 				}
 				if (rect_float) {
@@ -231,7 +324,7 @@ static void checker_board_color_tint(unsigned char *rect, float *rect_float, int
 					rect_float[1] = BLEND_FLOAT(rect_float[1], blend);
 					rect_float[2] = BLEND_FLOAT(rect_float[2], blend);
 					rect_float[3] = 1.0f;
-				
+
 					rect_float += 4;
 				}
 			}
@@ -241,7 +334,7 @@ static void checker_board_color_tint(unsigned char *rect, float *rect_float, int
 					rect[1] = (char)BLEND_CHAR(rect[1], blend_half);
 					rect[2] = (char)BLEND_CHAR(rect[2], blend_half);
 					rect[3] = 255;
-				
+
 					rect += 4;
 				}
 				if (rect_float) {
@@ -249,19 +342,24 @@ static void checker_board_color_tint(unsigned char *rect, float *rect_float, int
 					rect_float[1] = BLEND_FLOAT(rect_float[1], blend_half);
 					rect_float[2] = BLEND_FLOAT(rect_float[2], blend_half);
 					rect_float[3] = 1.0f;
-				
+
 					rect_float += 4;
 				}
 			}
-			
+
 		}
 	}
 }
 
-static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int width, int height, float blend)
+static void checker_board_grid_fill(unsigned char *rect,
+                                    f

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list