diff options
-rw-r--r-- | intern/cycles/blender/addon/engine.py | 31 | ||||
-rw-r--r-- | intern/cycles/blender/blender_python.cpp | 24 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 55 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.h | 22 | ||||
-rw-r--r-- | intern/cycles/render/tile.cpp | 21 | ||||
-rw-r--r-- | intern/cycles/render/tile.h | 11 |
6 files changed, 151 insertions, 13 deletions
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 96dc3a59ef2..d4b7535b9ee 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -50,10 +50,39 @@ def _workaround_buggy_drivers(): _cycles.opencl_disable() +def _parse_command_line(): + import sys + + argv = sys.argv + if "--" not in argv: + return + + argv = argv[argv.index("--") + 1:] + + num_resumable_chunks = None + current_resumable_chunk = None + + # TODO(sergey): Add some nice error ptins if argument is not used properly. + idx = 0 + while idx < len(argv) - 1: + arg = argv[idx] + if arg == '--cycles-resumable-num-chunks': + num_resumable_chunks = int(argv[idx + 1]) + elif arg == '--cycles-resumable-current-chunk': + current_resumable_chunk = int(argv[idx + 1]) + idx += 1 + + if num_resumable_chunks is not None and current_resumable_chunk is not None: + import _cycles + _cycles.set_resumable_chunks(num_resumable_chunks, + current_resumable_chunk) + + def init(): import bpy import _cycles import os.path + import sys # Workaround possibly buggy legacy drivers which crashes on the OpenCL # device enumeration. @@ -72,7 +101,7 @@ def init(): user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', ''))) _cycles.init(path, user_path, bpy.app.background) - + _parse_command_line() def exit(): import _cycles diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index b2294c8b68e..989ba80c001 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -638,6 +638,24 @@ static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/ Py_RETURN_NONE; } +static PyObject *set_resumable_chunks_func(PyObject * /*self*/, PyObject *args) +{ + int num_resumable_chunks, current_resumable_chunk; + if(!PyArg_ParseTuple(args, "ii", + &num_resumable_chunks, + ¤t_resumable_chunk)) { + return NULL; + } + + VLOG(1) << "Initialized resumable render: " + << "num_resumable_chunks=" << num_resumable_chunks << ", " + << "current_resumable_chunk=" << current_resumable_chunk; + BlenderSession::num_resumable_chunks = num_resumable_chunks; + BlenderSession::current_resumable_chunk = current_resumable_chunk; + + Py_RETURN_NONE; +} + static PyMethodDef methods[] = { {"init", init_func, METH_VARARGS, ""}, {"exit", exit_func, METH_VARARGS, ""}, @@ -657,8 +675,14 @@ static PyMethodDef methods[] = { #ifdef WITH_OPENCL {"opencl_disable", opencl_disable_func, METH_NOARGS, ""}, #endif + + /* Debugging routines */ {"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""}, {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""}, + + /* Resumable render */ + {"set_resumable_chunks", set_resumable_chunks_func, METH_VARARGS, ""}, + {NULL, NULL, 0, NULL}, }; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 977ba3d34cf..92b5b7277f4 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -43,6 +43,8 @@ CCL_NAMESPACE_BEGIN bool BlenderSession::headless = false; +int BlenderSession::num_resumable_chunks = 0; +int BlenderSession::current_resumable_chunk = 0; BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, @@ -161,6 +163,8 @@ void BlenderSession::create_session() session->reset(buffer_params, session_params.samples); b_engine.use_highlight_tiles(session_params.progressive_refine == false); + + update_resumable_tile_manager(session_params.samples); } void BlenderSession::reset_session(BL::BlendData& b_data_, BL::Scene& b_scene_) @@ -510,14 +514,21 @@ void BlenderSession::render() &python_thread_state, b_rlay_name.c_str()); - /* update number of samples per layer */ + /* Update number of samples per layer. */ int samples = sync->get_layer_samples(); bool bound_samples = sync->get_layer_bound_samples(); + int effective_layer_samples; if(samples != 0 && (!bound_samples || (samples < session_params.samples))) - session->reset(buffer_params, samples); + effective_layer_samples = samples; else - session->reset(buffer_params, session_params.samples); + effective_layer_samples = session_params.samples; + + /* Update tile manager if we're doing resumable render. */ + update_resumable_tile_manager(effective_layer_samples); + + /* Update session itself. */ + session->reset(buffer_params, effective_layer_samples); /* render */ session->start(); @@ -712,6 +723,13 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr, vector<float> pixels(params.width*params.height*4); + /* Adjust absolute sample number to the range. */ + int sample = rtile.sample; + const int range_start_sample = session->tile_manager.range_start_sample; + if(range_start_sample != -1) { + sample -= range_start_sample; + } + if(!do_update_only) { /* copy each pass */ BL::RenderLayer::passes_iterator b_iter; @@ -724,7 +742,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr, int components = b_pass.channels(); /* copy pixels */ - if(!buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0])) + if(!buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0])) memset(&pixels[0], 0, pixels.size()*sizeof(float)); b_pass.rect(&pixels[0]); @@ -733,7 +751,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr, else { /* copy combined pass */ BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str())); - if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) + if(buffers->get_pass_rect(PASS_COMBINED, exposure, sample, 4, &pixels[0])) b_combined_pass.rect(&pixels[0]); } @@ -909,12 +927,12 @@ void BlenderSession::get_progress(float& progress, double& total_time, double& r int tile, sample, samples_per_tile; int tile_total = session->tile_manager.state.num_tiles; int samples = session->tile_manager.state.sample + 1; - int total_samples = session->tile_manager.num_samples; + int total_samples = session->tile_manager.get_num_effective_samples(); session->progress.get_tile(tile, total_time, render_time, tile_time); sample = session->progress.get_sample(); - samples_per_tile = session->tile_manager.num_samples; + samples_per_tile = session->tile_manager.get_num_effective_samples(); if(background && samples_per_tile && tile_total) progress = ((float)sample / (float)(tile_total * samples_per_tile)); @@ -1277,5 +1295,26 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void return false; } -CCL_NAMESPACE_END +void BlenderSession::update_resumable_tile_manager(int num_samples) +{ + const int num_resumable_chunks = BlenderSession::num_resumable_chunks, + current_resumable_chunk = BlenderSession::current_resumable_chunk; + if(num_resumable_chunks == 0) { + return; + } + + int num_samples_per_chunk = (int)ceilf((float)num_samples / num_resumable_chunks); + int range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1); + int range_num_samples = num_samples_per_chunk; + if(range_start_sample + range_num_samples > num_samples) { + range_num_samples = num_samples - range_num_samples; + } + VLOG(1) << "Samples range start is " << range_start_sample << ", " + << "number of samples to render is " << range_num_samples; + + session->tile_manager.range_start_sample = range_start_sample; + session->tile_manager.range_num_samples = range_num_samples; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 8492d9f2c6b..66a6945cbc1 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -95,7 +95,6 @@ public: void update_bake_progress(); bool background; - static bool headless; Session *session; Scene *scene; BlenderSync *sync; @@ -120,6 +119,24 @@ public: void *python_thread_state; + /* Global state which is common for all render sessions created from Blender. + * Usually denotes command line arguments. + */ + + /* Blender is running from the command line, no windows are shown and some + * extra render optimization is possible (possible to free draw-only data and + * so on. + */ + static bool headless; + + /* ** Resumable render ** */ + + /* Overall number of chunks in which the sample range is to be devided. */ + static int num_resumable_chunks; + + /* Current resumable chunk index to render. */ + static int current_resumable_chunk; + protected: void do_write_update_render_result(BL::RenderResult& b_rr, BL::RenderLayer& b_rlay, @@ -131,6 +148,9 @@ protected: void builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels); bool builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels); bool builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels); + + /* Update tile manager to reflect resumable render settings. */ + void update_resumable_tile_manager(int num_samples); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 3fb60735b65..3a6dfea11a7 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -97,6 +97,9 @@ TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, i preserve_tile_device = preserve_tile_device_; background = background_; + range_start_sample = 0; + range_num_samples = -1; + BufferParams buffer_params; reset(buffer_params, 0); } @@ -124,7 +127,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_) num_samples = num_samples_; state.buffer = BufferParams(); - state.sample = -1; + state.sample = range_start_sample - 1; state.num_tiles = 0; state.num_rendered_tiles = 0; state.num_samples = 0; @@ -325,7 +328,11 @@ bool TileManager::next_tile(Tile& tile, int device) bool TileManager::done() { - return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1); + int end_sample = (range_num_samples == -1) + ? num_samples + : range_start_sample + range_num_samples; + return (state.resolution_divider == 1) && + (state.sample+state.num_samples >= end_sample); } bool TileManager::next() @@ -344,8 +351,10 @@ bool TileManager::next() if(progressive) state.num_samples = 1; - else + else if(range_num_samples == -1) state.num_samples = num_samples; + else + state.num_samples = range_num_samples; state.resolution_divider = 1; set_tiles(); @@ -354,5 +363,11 @@ bool TileManager::next() return true; } +int TileManager::get_num_effective_samples() +{ + return (range_num_samples == -1) ? num_samples + : range_num_samples; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 700e00c9e0a..af1b1ed8b0f 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -82,6 +82,17 @@ public: bool done(); void set_tile_order(TileOrder tile_order_) { tile_order = tile_order_; } + + /* ** Sample range rendering. ** */ + + /* Start sample in the range. */ + int range_start_sample; + + /* Number to samples in the rendering range. */ + int range_num_samples; + + /* get number of actual samples to render. */ + int get_num_effective_samples(); protected: void set_tiles(); |