From 9efbc8d76fecb008c03f7603227f00540359f216 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 6 Feb 2019 11:49:41 +0100 Subject: Cycles: backport samples metadata format changes to 2.7. The render layer name is now always included. Best to keep these consistent, so that animation denoising and sample merging works the same for both and tests can be the same. Ref D4311. --- intern/cycles/blender/blender_session.cpp | 35 +++++++++++++++++++++---------- intern/cycles/blender/blender_session.h | 3 +++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 43d7ff49a3b..ab08b9e146d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -379,6 +379,28 @@ static void add_cryptomatte_layer(BL::RenderResult& b_rr, string name, string ma render_add_metadata(b_rr, prefix+"manifest", manifest); } +void BlenderSession::stamp_view_layer_metadata_do(const string& prefix) +{ + BL::RenderResult b_rr = b_engine.get_result(); + /* Configured number of samples for the view layer. */ + b_rr.stamp_data_add_field((prefix + "samples").c_str(), + to_string(session->params.samples).c_str()); + /* Store ranged samples information. */ + if(session->tile_manager.range_num_samples != -1) { + b_rr.stamp_data_add_field( + (prefix + "range_start_sample").c_str(), + to_string(session->tile_manager.range_start_sample).c_str()); + b_rr.stamp_data_add_field( + (prefix + "range_num_samples").c_str(), + to_string(session->tile_manager.range_num_samples).c_str()); + } +} + +void BlenderSession::stamp_view_layer_metadata(const string& view_layer_name) +{ + stamp_view_layer_metadata_do("cycles." + view_layer_name + "."); +} + void BlenderSession::render() { /* set callback to write out render results */ @@ -394,9 +416,6 @@ void BlenderSession::render() BL::RenderSettings::layers_iterator b_layer_iter; BL::RenderResult::views_iterator b_view_iter; - /* We do some special meta attributes when we only have single layer. */ - const bool is_single_layer = (r.layers.length() == 1); - for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) { b_rlay_name = b_layer_iter->name(); @@ -491,15 +510,9 @@ void BlenderSession::render() break; } - BL::RenderResult b_full_rr = b_engine.get_result(); - if(is_single_layer) { - string num_aa_samples = string_printf("%d", session->params.samples); - render_add_metadata(b_full_rr, "Cycles Samples", num_aa_samples); - /* TODO(sergey): Report whether we're doing resumable render - * and also start/end sample if so. - */ - } + stamp_view_layer_metadata(b_rlay_name); + BL::RenderResult b_full_rr = b_engine.get_result(); if(scene->film->cryptomatte_passes & CRYPT_OBJECT) { add_cryptomatte_layer(b_full_rr, b_rlay_name+".CryptoObject", scene->object_manager->get_cryptomatte_objects(scene)); diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index b8a9096b354..2aa3c77c37d 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -146,6 +146,9 @@ public: static bool print_render_stats; protected: + void stamp_view_layer_metadata(const string& view_layer_name); + void stamp_view_layer_metadata_do(const string& prefix); + void do_write_update_render_result(BL::RenderResult& b_rr, BL::RenderLayer& b_rlay, RenderTile& rtile, -- cgit v1.2.3 From 2a9c8da709593b5b6187002797d9bb4363440bd5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 11 Feb 2019 18:26:47 +0100 Subject: Cycles: add animation denoising test, fix operator to work with single frames. --- intern/cycles/blender/addon/operators.py | 58 ++++++++++++++----------- tests/python/CMakeLists.txt | 1 + tests/python/cycles_render_tests.py | 73 ++++++++++++-------------------- 3 files changed, 60 insertions(+), 72 deletions(-) diff --git a/intern/cycles/blender/addon/operators.py b/intern/cycles/blender/addon/operators.py index c39aa386203..a099970c58c 100644 --- a/intern/cycles/blender/addon/operators.py +++ b/intern/cycles/blender/addon/operators.py @@ -43,15 +43,15 @@ class CYCLES_OT_use_shading_nodes(Operator): class CYCLES_OT_denoise_animation(Operator): - """Denoise rendered animation sequence using current scene and view """ \ - """layer settings. Requires denoising data passes and output to """ \ - """OpenEXR multilayer files""" + "Denoise rendered animation sequence using current scene and view " \ + "layer settings. Requires denoising data passes and output to " \ + "OpenEXR multilayer files" bl_idname = "cycles.denoise_animation" bl_label = "Denoise Animation" input_filepath = StringProperty( name='Input Filepath', - description='File path for frames to denoise. If not specified, uses the render file path from the scene', + description='File path for image to denoise. If not specified, uses the render file path and frame range from the scene', default='', subtype='FILE_PATH') @@ -71,33 +71,41 @@ class CYCLES_OT_denoise_animation(Operator): in_filepath = self.input_filepath out_filepath = self.output_filepath - if in_filepath == '': - in_filepath = scene.render.filepath - if out_filepath == '': - out_filepath = in_filepath - - # Backup since we will overwrite the scene path temporarily - original_filepath = scene.render.filepath - - # Expand filepaths for each frame so we match Blender render output exactly. in_filepaths = [] out_filepaths = [] - for frame in range(scene.frame_start, scene.frame_end + 1): - scene.render.filepath = in_filepath - filepath = scene.render.frame_path(frame=frame) - in_filepaths.append(filepath) + if in_filepath != '': + # Denoise a single file + if out_filepath == '': + out_filepath = in_filepath + + in_filepaths.append(in_filepath) + out_filepaths.append(out_filepath) + else: + # Denoise animation sequence with expanded frames matching + # Blender render output file naming. + in_filepath = scene.render.filepath + if out_filepath == '': + out_filepath = in_filepath + + # Backup since we will overwrite the scene path temporarily + original_filepath = scene.render.filepath + + for frame in range(scene.frame_start, scene.frame_end + 1): + scene.render.filepath = in_filepath + filepath = scene.render.frame_path(frame=frame) + in_filepaths.append(filepath) - if not os.path.isfile(filepath): - scene.render.filepath = original_filepath - self.report({'ERROR'}, f"Frame '{filepath}' not found, animation must be complete.") - return {'CANCELLED'} + if not os.path.isfile(filepath): + scene.render.filepath = original_filepath + self.report({'ERROR'}, f"Frame '{filepath}' not found, animation must be complete.") + return {'CANCELLED'} - scene.render.filepath = out_filepath - filepath = scene.render.frame_path(frame=frame) - out_filepaths.append(filepath) + scene.render.filepath = out_filepath + filepath = scene.render.frame_path(frame=frame) + out_filepaths.append(filepath) - scene.render.filepath = original_filepath + scene.render.filepath = original_filepath # Run denoiser # TODO: support cancel and progress reports. diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index b5cc39ae37a..46e917226e4 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -549,6 +549,7 @@ if(WITH_CYCLES) add_cycles_render_test(bake) add_cycles_render_test(bsdf) add_cycles_render_test(denoise) + add_cycles_render_test(denoise_animation) add_cycles_render_test(displacement) add_cycles_render_test(hair) add_cycles_render_test(image_data_types) diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py index a01a6f74e15..1717210663a 100755 --- a/tests/python/cycles_render_tests.py +++ b/tests/python/cycles_render_tests.py @@ -14,61 +14,40 @@ def render_file(filepath, output_filepath): basedir = os.path.dirname(dirname) subject = os.path.basename(dirname) - custom_args = os.getenv('CYCLESTEST_ARGS') - custom_args = shlex.split(custom_args) if custom_args else [] + frame_filepath = output_filepath + '0001.png' + + common_args = [ + "-noaudio", + "--factory-startup", + "--enable-autoexec", + filepath, + "-E", "CYCLES", + "-o", output_filepath, + "-F", "PNG"] # OSL and GPU examples # custom_args += ["--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True"] # custom_args += ["--python-expr", "import bpy; bpy.context.scene.cycles.device = 'GPU'"] - - frame_filepath = output_filepath + '0001.png' + custom_args = os.getenv('CYCLESTEST_ARGS') + custom_args = shlex.split(custom_args) if custom_args else [] + common_args += custom_args if subject == 'opengl': - command = [ - BLENDER, - "--window-geometry", "0", "0", "1", "1", - "-noaudio", - "--factory-startup", - "--enable-autoexec", - filepath, - "-E", "CYCLES"] - command += custom_args - command += [ - "-o", output_filepath, - "-F", "PNG", - '--python', os.path.join(basedir, - "util", - "render_opengl.py")] + command = [BLENDER, "--window-geometry", "0", "0", "1", "1"] + command += common_args + command += ['--python', os.path.join(basedir, "util", "render_opengl.py")] elif subject == 'bake': - command = [ - BLENDER, - "-b", - "-noaudio", - "--factory-startup", - "--enable-autoexec", - filepath, - "-E", "CYCLES"] - command += custom_args - command += [ - "-o", output_filepath, - "-F", "PNG", - '--python', os.path.join(basedir, - "util", - "render_bake.py")] + command = [BLENDER, "--background"] + command += common_args + command += ['--python', os.path.join(basedir, "util", "render_bake.py")] + elif subject == 'denoise_animation': + command = [BLENDER, "--background"] + command += common_args + command += ['--python', os.path.join(basedir, "util", "render_denoise.py")] else: - command = [ - BLENDER, - "--background", - "-noaudio", - "--factory-startup", - "--enable-autoexec", - filepath, - "-E", "CYCLES"] - command += custom_args - command += [ - "-o", output_filepath, - "-F", "PNG", - "-f", "1"] + command = [BLENDER, "--background"] + command += common_args + command += ["-f", "1"] try: # Success -- cgit v1.2.3