Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/blender/addon/engine.py31
-rw-r--r--intern/cycles/blender/blender_python.cpp24
-rw-r--r--intern/cycles/blender/blender_session.cpp55
-rw-r--r--intern/cycles/blender/blender_session.h22
-rw-r--r--intern/cycles/render/tile.cpp21
-rw-r--r--intern/cycles/render/tile.h11
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,
+ &current_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();