[Bf-blender-cvs] [c5d7ea0] master: Changes to partial update during rendering

Sergey Sharybin noreply at git.blender.org
Tue Dec 17 18:43:36 CET 2013


Commit: c5d7ea091fa5a291b270565e456612df1e37b50c
Author: Sergey Sharybin
Date:   Tue Dec 17 23:42:38 2013 +0600
http://developer.blender.org/rBc5d7ea091fa5a291b270565e456612df1e37b50c

Changes to partial update during rendering

Summary:
Mainly addressed to solve old TODO with color managed fallback
to CPU mode when displaying render result during rendering.

That fallback was caused by the fact that partial image update
was always acquiring image buffer for composite output and was
only modifying display buffer directly.

This was a big issue for Cycles rendering which renders layers
one by one and wanted to display progress of each individual
layer. This lead to situations when display buffer was based on
what Cycles passes via RenderResult and didn't take layer/pass
from image editor header into account.

Now made it so image buffer which partial update is operating
with always corresponds to what is set in image editor header.

To make Cycles displaying progress of all the layers one by one
made it so image_rect_update switches image editor user to
newly rendering render layer. It happens only once when render
engine starts rendering next render layer, so should not be
annoying for navigation during rendering.

Additional change to render engines was done to make it so
they're able to merge composite output to final result
without marking tile as done. This is done via do_merge_result
argument to end_result() callback. This argument is optional
so should not break script compatibility.

Additional changes:

- Partial display update for Blender Internal now happens from
  the same thread as tile rendering. This makes it so display
  conversion (which could be pretty heavy actually) is done in
  separate threads. Also gives better UI feedback when rendering
  easy scene with small tiles.

- Avoid freeing/allocating byte buffer for render result
  if it's owned by the image buffer. Only mark it as invalid
  for color management.

  Saves loads of buffer re-allocations in cases when having
  several image editors opened with render result. This change
  in conjunction with the rest of the patch gave around
  50%-100% speedup of render time when displaying non-combined
  pass during rendering on my laptop.

- Partial display buffer update was wrong for buffers with number
  of channels different from 4.

- Remove unused window from RenderJob.

- Made image_buffer_rect_update static since it's only used
  in single file.

Reviewers: brecht

Reviewed By: brecht

CC: dingto

Differential Revision: http://developer.blender.org/D98

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

M	intern/cycles/blender/blender_session.cpp
M	source/blender/blenkernel/intern/image.c
M	source/blender/editors/render/render_intern.h
M	source/blender/editors/render/render_internal.c
M	source/blender/editors/render/render_preview.c
M	source/blender/editors/render/render_view.c
M	source/blender/editors/screen/glutil.c
M	source/blender/imbuf/intern/colormanagement.c
M	source/blender/makesrna/intern/rna_render.c
M	source/blender/render/extern/include/RE_engine.h
M	source/blender/render/extern/include/RE_pipeline.h
M	source/blender/render/intern/include/render_types.h
M	source/blender/render/intern/source/envmap.c
M	source/blender/render/intern/source/external_engine.c
M	source/blender/render/intern/source/pipeline.c
M	source/blender/render/intern/source/rendercore.c

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

diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index db673a8..f81de7d 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -261,9 +261,9 @@ static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, in
 	return b_engine.begin_result(x, y, w, h, layername);
 }
 
-static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel = false)
+static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel, bool do_merge_results)
 {
-	b_engine.end_result(b_rr, (int)cancel);
+	b_engine.end_result(b_rr, (int)cancel, (int)do_merge_results);
 }
 
 void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only)
@@ -302,12 +302,12 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
 			update_render_result(b_rr, b_rlay, rtile);
 		}
 
-		end_render_result(b_engine, b_rr, true);
+		end_render_result(b_engine, b_rr, true, true);
 	}
 	else {
 		/* write result */
 		write_render_result(b_rr, b_rlay, rtile);
-		end_render_result(b_engine, b_rr);
+		end_render_result(b_engine, b_rr, false, true);
 	}
 }
 
@@ -352,7 +352,7 @@ void BlenderSession::render()
 
 		/* layer will be missing if it was disabled in the UI */
 		if(b_single_rlay == b_rr.layers.end()) {
-			end_render_result(b_engine, b_rr, true);
+			end_render_result(b_engine, b_rr, true, false);
 			continue;
 		}
 
@@ -379,7 +379,7 @@ void BlenderSession::render()
 		}
 
 		/* free result without merging */
-		end_render_result(b_engine, b_rr, true);
+		end_render_result(b_engine, b_rr, true, false);
 
 		buffer_params.passes = passes;
 		scene->film->tag_passes_update(scene, passes);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 51c70e8..dc26ced 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -2862,13 +2862,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
 	ibuf->x = rres.rectx;
 	ibuf->y = rres.recty;
 
-	/* free rect buffer if float buffer changes, so it can be recreated with
-	 * the updated result, and also in case we got byte buffer from sequencer,
-	 * so we don't keep reference to freed buffer */
-	if (ibuf->rect_float != rectf || rect)
-		imb_freerectImBuf(ibuf);
-
 	if (rect) {
+		imb_freerectImBuf(ibuf);
 		ibuf->rect = rect;
 	}
 	else {
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index eb09606..8f8cc54 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -35,6 +35,7 @@
 struct wmOperatorType;
 struct RenderResult;
 struct Scene;
+struct ScrArea;
 
 /* render_shading.c */
 void OBJECT_OT_material_slot_add(struct wmOperatorType *ot);
@@ -86,11 +87,8 @@ void RENDER_OT_render(struct wmOperatorType *ot);
 void render_view3d_update(struct RenderEngine *engine, const struct bContext *C);
 void render_view3d_draw(struct RenderEngine *engine, const struct bContext *C);
 
-/* render_opengl.c uses this */
-void image_buffer_rect_update(struct Scene *scene, struct RenderResult *rr, struct ImBuf *ibuf, volatile struct rcti *renrect);
-
 /* render_view.c */
-void render_view_open(struct bContext *C, int mx, int my);
+struct ScrArea *render_view_open(struct bContext *C, int mx, int my);
 
 void RENDER_OT_view_show(struct wmOperatorType *ot);
 void RENDER_OT_view_cancel(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 1b090cb..7ecada9 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -94,11 +94,17 @@
 static int render_break(void *rjv);
 
 /* called inside thread! */
-void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
+static void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect)
 {
 	float *rectf = NULL;
 	int ymin, ymax, xmin, xmax;
 	int rymin, rxmin;
+	int linear_stride, linear_offset_x, linear_offset_y;
+
+	if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) {
+		/* The whole image buffer it so be color managed again anyway. */
+		return;
+	}
 
 	/* if renrect argument, we only refresh scanlines */
 	if (renrect) {
@@ -138,33 +144,55 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
 
 	if (xmax < 1 || ymax < 1) return;
 
-	/* find current float rect for display, first case is after composite... still weak */
-	if (rr->rectf)
-		rectf = rr->rectf;
-	else {
-		if (rr->rect32) {
-			/* special case, currently only happens with sequencer rendering,
-			 * which updates the whole frame, so we can only mark display buffer
-			 * as invalid here (sergey)
-			 */
-			ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-			return;
-		}
+	/* The thing here is, the logic below (which was default behavior
+	 * of how rectf is acquiring since forever) gives float buffer for
+	 * composite output only. This buffer can not be used for other
+	 * passes obviously.
+	 *
+	 * We might try finding corresponding for pass buffer in render result
+	 * (which is actually missing when rendering with Cycles, who only
+	 * writes all the passes when the tile is finished) or use float
+	 * buffer from image buffer as reference, which is easier to use and
+	 * contains all the data we need anyway.
+	 *                                              - sergey -
+	 */
+	/* TODO(sergey): Need to check has_combined here? */
+	if (iuser->pass == 0) {
+		/* find current float rect for display, first case is after composite... still weak */
+		if (rr->rectf)
+			rectf = rr->rectf;
 		else {
-			if (rr->renlay == NULL || rr->renlay->rectf == NULL) return;
-			rectf = rr->renlay->rectf;
+			if (rr->rect32) {
+				/* special case, currently only happens with sequencer rendering,
+				 * which updates the whole frame, so we can only mark display buffer
+				 * as invalid here (sergey)
+				 */
+				ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+				return;
+			}
+			else {
+				if (rr->renlay == NULL || rr->renlay->rectf == NULL) return;
+				rectf = rr->renlay->rectf;
+			}
 		}
-	}
-	if (rectf == NULL) return;
+		if (rectf == NULL) return;
 
-	if (ibuf->rect == NULL)
-		imb_addrectImBuf(ibuf);
-
-	rectf += 4 * (rr->rectx * ymin + xmin);
+		rectf += 4 * (rr->rectx * ymin + xmin);
+		linear_stride = rr->rectx;
+		linear_offset_x = rxmin;
+		linear_offset_y = rymin;
+	}
+	else {
+		rectf = ibuf->rect_float;
+		linear_stride = ibuf->x;
+		linear_offset_x = 0;
+		linear_offset_y = 0;
+	}
 
-	IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
+	IMB_partial_display_buffer_update(ibuf, rectf, NULL,
+	                                  linear_stride, linear_offset_x, linear_offset_y,
 	                                  &scene->view_settings, &scene->display_settings,
-	                                  rxmin, rymin, rxmin + xmax, rymin + ymax, true);
+	                                  rxmin, rymin, rxmin + xmax, rymin + ymax, false);
 }
 
 /* ****************************** render invoking ***************** */
@@ -262,7 +290,6 @@ typedef struct RenderJob {
 	Main *main;
 	Scene *scene;
 	Render *re;
-	wmWindow *win;
 	SceneRenderLayer *srl;
 	struct Object *camera_override;
 	int lay_override;
@@ -275,6 +302,9 @@ typedef struct RenderJob {
 	short *do_update;
 	float *progress;
 	ReportList *reports;
+	int orig_layer;
+	int last_layer;
+	ScrArea *sa;
 } RenderJob;
 
 static void render_freejob(void *rjv)
@@ -402,6 +432,64 @@ static void render_progress_update(void *rjv, float progress)
 	}
 }
 
+/* Not totally reliable, but works fine in most of cases and
+ * in worst case would just make it so extra color management
+ * for the whole render result is applied (which was already
+ * happening already).
+ */
+static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, ImageUser *iuser)
+{
+	wmWindowManager *wm;
+	ScrArea *first_sa = NULL, *matched_sa = NULL;
+
+	/* image window, compo node users */
+	for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */
+		wmWindow *win;
+		for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) {
+			ScrArea *sa;
+			for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+				if (sa->spacetype == SPACE_IMAGE) {
+					SpaceImage *sima = sa->spacedata.first;
+					if (sima->image == rj->image) {
+						if (first_sa == NULL) {
+							first_sa = sa;
+						}
+						if (sa == rj->sa) {
+							matched_sa = sa;
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if (matched_sa == NULL) {
+		matched_sa = first_sa;
+	}
+
+	if (matched_sa) {
+		SpaceImage *sima = matched_sa->spacedata.first;
+		RenderResult *main_rr = RE_AcquireResultRead(rj->re);
+
+		/* TODO(sergey): is there faster way to get the layer index? */
+		if (rr->renlay) {
+			int layer = BLI_findstringindex(&main_rr->layers,
+			                                (char *)rr->renlay->name,
+			                                offsetof(RenderLayer, name));
+			if (layer != rj->last_layer) {
+				sima->iuser.layer = layer;
+				rj->last_layer = layer;
+			}
+		}
+
+		iuser->pass = sima->iuser.pass;
+		iuser->layer = sima->iuser.layer;
+
+		RE_ReleaseResult(rj->re);
+	}
+}
+
 static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
 {
 	RenderJob *rj = rjv;
@@ -423,9 +511,17 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
 	}
 
 	/* update part of render */
+	render_image_update_pass_and_layer(rj, rr, &rj->iuser);
 	ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
 	if (ibuf) {
-		image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
+		/* Don't waste time on CPU side color management if
+		 * image will be displayed using GLSL.
+		 */
+		if (ibuf->channels == 1 ||
+		    U.image_draw_method != IMAGE_DRAW_METHOD_GLSL)
+		{
+			image_buffer_rect_update(rj->scene, rr, ibuf, &rj->iuser, renrect);
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list