[Bf-blender-cvs] [1c675f1] soc-2016-cycles_denoising: Cycles: Implement multi-frame buffer support and loading in standalone mode

Lukas Stockner noreply at git.blender.org
Sat Aug 13 05:12:36 CEST 2016


Commit: 1c675f1cc8597005bbdc282987172aeea4af566e
Author: Lukas Stockner
Date:   Sat Aug 13 03:59:15 2016 +0200
Branches: soc-2016-cycles_denoising
https://developer.blender.org/rB1c675f1cc8597005bbdc282987172aeea4af566e

Cycles: Implement multi-frame buffer support and loading in standalone mode

This commits adds an option to the BufferParams that specifies how many frames are stored in there.
The frames share all other parameters, such as size and passes.
Frames are not stored in order - instead, the first frame is the primary frame, so that all code that uses
the RenderBuffers still works as expected, but code parts that can use the additional frames may do so.

The Standalone Denoising mode now comes with an option to specify the frame range that will be used for denoising.
When doing so, the input filename isn't an actual file, but has to contain a part of the form "%Xd" that specifies how the frame file names are formatted, where X is the length to which frames are zero-padded. That part will be replaced by the padded frame number before loading.

So far, no code actually uses the additional frames yet, that will come in the next commits.

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

M	intern/cycles/app/cycles_denoising.cpp
M	intern/cycles/app/cycles_standalone.cpp
M	intern/cycles/app/cycles_standalone.h
M	intern/cycles/render/buffers.cpp
M	intern/cycles/render/buffers.h
M	intern/cycles/render/session.h

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

diff --git a/intern/cycles/app/cycles_denoising.cpp b/intern/cycles/app/cycles_denoising.cpp
index 5515fb1..3f6c611 100644
--- a/intern/cycles/app/cycles_denoising.cpp
+++ b/intern/cycles/app/cycles_denoising.cpp
@@ -81,18 +81,25 @@ static int find_channel(string channels, string channel)
 	return pos;
 }
 
-static RenderBuffers* load_frame(string file, Device *device)
+static RenderBuffers* load_frame(string file, Device *device, RenderBuffers *buffers, int framenum)
 {
-	RenderBuffers *buffers = NULL;
-
 	ImageInput *frame = ImageInput::open(file);
 	if(!frame) {
-		printf("Couldn't open frame %s!\n", file.c_str());
+		printf("ERROR: Frame %s: Couldn't open file!\n", file.c_str());
+		delete buffers;
 		return NULL;
 	}
 
 	const ImageSpec &spec = frame->spec();
 
+	if(buffers) {
+		if(spec.width != buffers->params.width || spec.height != buffers->params.height) {
+			printf("ERROR: Frame %s: Has different size!\n", file.c_str());
+			delete buffers;
+			return NULL;
+		}
+	}
+
 	/* Find a single RenderLayer to load. */
 	string renderlayer = "";
 	string layer, pass, channel;
@@ -133,61 +140,77 @@ static RenderBuffers* load_frame(string file, Device *device)
 			}
 		}
 
-		if((~passes & EX_TYPE_DENOISE_REQUIRED) == 0) {
-			printf("Found all needed passes in the frame!\n");
-
-			BufferParams params;
-			params.width  = params.full_width  = params.final_width  = spec.width;
-			params.height = params.full_height = params.final_height = spec.height;
-			params.full_x = params.full_y = 0;
-			params.denoising_passes = true;
-			params.selective_denoising = (passes & EX_TYPE_DENOISE_CLEAN);
-
-			buffers = new RenderBuffers(device);
-			buffers->reset(device, params);
+		/* The frame always needs to include all the required denoising passes.
+		 * If the primary frame also included a clean pass, all the secondary frames need to do so as well. */
+		if((~passes & EX_TYPE_DENOISE_REQUIRED) == 0 && !(buffers && buffers->params.selective_denoising && !(passes & EX_TYPE_DENOISE_CLEAN))) {
+			printf("Frame %s: Found all needed passes!\n", file.c_str());
+
+			if(buffers == NULL) {
+				BufferParams params;
+				params.width  = params.full_width  = params.final_width  = spec.width;
+				params.height = params.full_height = params.final_height = spec.height;
+				params.full_x = params.full_y = 0;
+				params.denoising_passes = true;
+				params.selective_denoising = (passes & EX_TYPE_DENOISE_CLEAN);
+				params.frames = options.filepaths.size();
+
+				buffers = new RenderBuffers(device);
+				buffers->reset(device, params);
+			}
 
-			int4 rect = make_int4(0, 0, params.width, params.height);
+			int4 rect = make_int4(0, 0, buffers->params.width, buffers->params.height);
+			float *pass_data = new float[4*buffers->params.width*buffers->params.height];
 
-			float *pass_data = new float[4*params.width*params.height];
 			/* Read all the passes from the file. */
 			for(map<PassTypeInfo, int3>::iterator i = channel_ids.begin(); i != channel_ids.end(); i++)
 			{
 				for(int c = 0; c < i->first.num_channels; c++) {
 					int xstride = i->first.num_channels*sizeof(float);
-					int ystride = params.width * xstride;
+					int ystride = spec.width * xstride;
 					printf("Reading pass %s!            \r", spec.channelnames[i->second[c]].c_str());
 					fflush(stdout);
 					frame->read_image(i->second[c], i->second[c]+1, TypeDesc::FLOAT, pass_data + c, xstride, ystride);
 				}
-				buffers->get_denoising_rect(i->first.type, 1.0f, options.session_params.samples, i->first.num_channels, rect, pass_data, true);
+				buffers->get_denoising_rect(i->first.type, 1.0f, options.session_params.samples, i->first.num_channels, rect, pass_data, true, framenum);
 			}
 
-			/* Read combined channel. */
+			/* Read combined pass. */
+			int read_combined = 0;
 			for(int i = 0; i < spec.nchannels; i++) {
 				if(!split_channel(spec.channelnames[i], layer, pass, channel)) continue;
 				if(layer != renderlayer || pass != "Combined") continue;
 
 				size_t channel_id = find_channel("RGBA", channel);
-				if(channel_id != 1) {
+				if(channel_id != -1) {
 					int xstride = 4*sizeof(float);
-					int ystride = params.width * xstride;
-					printf("Reading pass %s!            \r", spec.channelnames[i].c_str());
+					int ystride = spec.width * xstride;
+					printf("Reading pass %s!            \n", spec.channelnames[i].c_str());
 					fflush(stdout);
 					frame->read_image(i, i+1, TypeDesc::FLOAT, pass_data + channel_id, xstride, ystride);
+					read_combined++;
 				}
 			}
-			buffers->get_pass_rect(PASS_COMBINED, 1.0f, options.session_params.samples, 4, rect, pass_data, true);
+			if(read_combined < 4) {
+				printf("ERROR: Frame %s: Missing combined pass!\n", file.c_str());
+				delete buffers;
+				delete[] pass_data;
+				return NULL;
+			}
 
-			delete[] pass_data;
+			buffers->get_pass_rect(PASS_COMBINED, 1.0f, options.session_params.samples, 4, rect, pass_data, true, framenum);
 
-			buffers->copy_to_device();
+			delete[] pass_data;
 		}
 		else {
-			printf("The frame is missing some pass!\n");
+			printf("ERROR: Frame %s: Missing some pass!\n", file.c_str());
+			delete buffers;
+			return NULL;
 		}
 	}
 	else {
-		printf("Didn't fine a suitable RenderLayer!\n");
+		printf("ERROR: Frame %s: Didn't fine a suitable RenderLayer!\n", file.c_str());
+		delete buffers;
+		return NULL;
 	}
 
 	frame->close();
@@ -205,14 +228,44 @@ bool cycles_denoising_session()
 	options.session_params.tile_order = TILE_BOTTOM_TO_TOP;
 	options.session_params.flip_output = false;
 
+	if(options.frame_range.y >= options.frame_range.x) {
+		string pattern = options.filepaths[0];
+		size_t pos = pattern.find("%");
+		if(options.filepaths.size() != 1 || pos == string::npos || pattern.size() <= pos+3 ||!isdigit(pattern[pos+1]) || pattern[pos+2] != 'd') {
+			printf("ERROR: When using the frame range option, specify the image file as a single filename including %%Xd, there X is the length of the frame numbers.");
+			delete options.session;
+			return false;
+		}
+
+		char pad_length = pattern[pos+1];
+		vector<string> new_filepaths;
+		for(int frame = options.frame_range.x; frame <= options.frame_range.y; frame++) {
+
+			string name = pattern.substr(0, pos);
+			name += string_printf(string_printf("%%0%cd", pad_length).c_str(), frame);
+			name += pattern.substr(pos+3);
+			new_filepaths.push_back(name);
+		}
+
+		options.filepaths.swap(new_filepaths);
+
+		options.session_params.prev_frames -= options.frame_range.x;
+	}
+
 	options.session = new Session(options.session_params);
 	options.session->progress.set_update_callback(function_bind(&session_print_status));
 	options.session->set_pause(false);
 
-	RenderBuffers *buffers = load_frame(options.filepaths[0], options.session->device);
-	if(!buffers) {
-		return false;
+	RenderBuffers *buffers = NULL;
+	for(int f = 0; f < options.filepaths.size(); f++) {
+		buffers = load_frame(options.filepaths[f], options.session->device, buffers, f);
+		if(!buffers) {
+			delete options.session;
+			return false;
+		}
 	}
+	buffers->copy_to_device();
+
 	options.session->buffers = buffers;
 
 	options.session->start_denoise();
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index c07f17f..9f73ffa 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -327,7 +327,8 @@ static void options_parse(int argc, const char **argv)
 	options.filepaths.clear();
 	options.session = NULL;
 	options.quiet = false;
-	options.denoise_frame = 0;
+	options.frame_range.x = -1;
+	options.frame_range.y = -2;
 
 	/* device names */
 	string device_names = "";
@@ -365,8 +366,9 @@ static void options_parse(int argc, const char **argv)
 		"--background", &options.session_params.background, "Render in background, without user interface",
 		"--quiet", &options.quiet, "In background mode, don't print progress messages",
 		"--denoise", &denoise, "Denoise the given input file instead of rendering it",
-		"--denoise-frame %d", &options.denoise_frame, "Which frame to denoise (first frame is 0)",
 		"--half-window %d", &options.session_params.half_window, "Size of the denoising window",
+		"--denoise-frame %d", &options.session_params.prev_frames, "Which frame to denoise (together with --frame-range)",
+		"--frame-range %d %d", &options.frame_range.x, &options.frame_range.y, "Frame Range that's used for denoising",
 		"--samples %d", &options.session_params.samples, "Number of samples to render",
 		"--output %s", &options.session_params.output_path, "File path to write output image",
 		"--output-half", &options.session_params.output_half_float, "Write output image in half float format",
diff --git a/intern/cycles/app/cycles_standalone.h b/intern/cycles/app/cycles_standalone.h
index d247c83..0373a71 100644
--- a/intern/cycles/app/cycles_standalone.h
+++ b/intern/cycles/app/cycles_standalone.h
@@ -33,7 +33,7 @@ struct Options {
 	SessionParams session_params;
 	bool quiet;
 	bool show_help, interactive, pause;
-	int denoise_frame;
+	int2 frame_range;
 };
 
 extern Options options;
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index e056934..221211a 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -36,6 +36,7 @@ BufferParams::BufferParams()
 {
 	width = 0;
 	height = 0;
+	frames = 1;
 
 	full_x = 0;
 	full_y = 0;
@@ -63,6 +64,7 @@ bool BufferParams::modified(const BufferParams& params)
 		&& full_y == params.full_y
 		&& width == params.width
 		&& height == params.height
+	        && frames == params.frames
 		&& full_width == params.full_width
 		&& full_height == params.full_height
 		&& final_width == params.final_width
@@ -153,7 +155,7 @@ void RenderBuffers::reset(Device *device, BufferParams& params_)
 	device_free();
 	
 	/* allocate buffer */
-	buffer.resize(params.width*params.height*params.get_passes_size());
+	buffer.resize(params.width*params.height*params.frames*params.get_passes_size());
 	device->mem_alloc(buffer, MEM_READ_WRITE);
 	device->mem_zero(buffer);
 
@@ -176,7 +178,9 @@ bool RenderBuffers::copy_from_device()
 	if(!buffer.device_pointer)
 		return false;
 
-	device->mem_copy_from(buffer, 0, 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list