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:
Diffstat (limited to 'intern/cycles/blender/blender_session.cpp')
-rw-r--r--intern/cycles/blender/blender_session.cpp695
1 files changed, 334 insertions, 361 deletions
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 29de886e4ff..5aafa605526 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -38,9 +38,11 @@
#include "util/util_hash.h"
#include "util/util_logging.h"
#include "util/util_murmurhash.h"
+#include "util/util_path.h"
#include "util/util_progress.h"
#include "util/util_time.h"
+#include "blender/blender_gpu_display.h"
#include "blender/blender_session.h"
#include "blender/blender_sync.h"
#include "blender/blender_util.h"
@@ -49,10 +51,6 @@ CCL_NAMESPACE_BEGIN
DeviceTypeMask BlenderSession::device_override = DEVICE_MASK_ALL;
bool BlenderSession::headless = false;
-int BlenderSession::num_resumable_chunks = 0;
-int BlenderSession::current_resumable_chunk = 0;
-int BlenderSession::start_resumable_chunk = 0;
-int BlenderSession::end_resumable_chunk = 0;
bool BlenderSession::print_render_stats = false;
BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
@@ -103,7 +101,9 @@ BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
width(width),
height(height),
preview_osl(false),
- python_thread_state(NULL)
+ python_thread_state(NULL),
+ use_developer_ui(b_userpref.experimental().use_cycles_debug() &&
+ b_userpref.view().show_developer_ui())
{
/* 3d view render */
background = false;
@@ -119,10 +119,10 @@ BlenderSession::~BlenderSession()
void BlenderSession::create_session()
{
- SessionParams session_params = BlenderSync::get_session_params(
+ const SessionParams session_params = BlenderSync::get_session_params(
b_engine, b_userpref, b_scene, background);
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
- bool session_pause = BlenderSync::get_session_pause(b_scene, background);
+ const SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
+ const bool session_pause = BlenderSync::get_session_pause(b_scene, background);
/* reset status/progress */
last_status = "";
@@ -131,20 +131,18 @@ void BlenderSession::create_session()
start_resize_time = 0.0;
/* create session */
- session = new Session(session_params);
- session->scene = scene;
+ session = new Session(session_params, scene_params);
session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
session->set_pause(session_pause);
/* create scene */
- scene = new Scene(scene_params, session->device);
+ scene = session->scene;
scene->name = b_scene.name();
- session->scene = scene;
-
/* create sync */
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+ sync = new BlenderSync(
+ b_engine, b_data, b_scene, scene, !background, use_developer_ui, session->progress);
BL::Object b_camera_override(b_engine.camera_override());
if (b_v3d) {
sync->sync_view(b_v3d, b_rv3d, width, height);
@@ -154,13 +152,23 @@ void BlenderSession::create_session()
}
/* set buffer parameters */
- BufferParams buffer_params = BlenderSync::get_buffer_params(
- b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
- session->reset(buffer_params, session_params.samples);
+ const BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_v3d, b_rv3d, scene->camera, width, height);
+ session->reset(session_params, buffer_params);
- b_engine.use_highlight_tiles(session_params.progressive_refine == false);
+ /* Create GPU display. */
+ if (!b_engine.is_preview() && !headless) {
+ session->set_gpu_display(make_unique<BlenderGPUDisplay>(b_engine, b_scene));
+ }
- update_resumable_tile_manager(session_params.samples);
+ /* Viewport and preview (as in, material preview) does not do tiled rendering, so can inform
+ * engine that no tracking of the tiles state is needed.
+ * The offline rendering will make a decision when tile is being written. The penalty of asking
+ * the engine to keep track of tiles state is minimal, so there is nothing to worry about here
+ * about possible single-tiled final render. */
+ if (!b_engine.is_preview() && !b_v3d) {
+ b_engine.use_highlight_tiles(true);
+ }
}
void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph)
@@ -202,9 +210,9 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
return;
}
- SessionParams session_params = BlenderSync::get_session_params(
+ const SessionParams session_params = BlenderSync::get_session_params(
b_engine, b_userpref, b_scene, background);
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
+ const SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
if (scene->params.modified(scene_params) || session->params.modified(session_params) ||
!this->b_render.use_persistent_data()) {
@@ -220,8 +228,6 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
session->progress.reset();
- session->tile_manager.set_tile_order(session_params.tile_order);
-
/* peak memory usage should show current render peak, not peak for all renders
* made by this render session
*/
@@ -230,7 +236,8 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
if (is_new_session) {
/* Sync object should be re-created for new scene. */
delete sync;
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+ sync = new BlenderSync(
+ b_engine, b_data, b_scene, scene, !background, use_developer_ui, session->progress);
}
else {
/* Sync recalculations to do just the required updates. */
@@ -242,103 +249,85 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_null_space_view3d,
- b_null_region_view3d,
- scene->camera,
- width,
- height,
- session_params.denoising.use);
- session->reset(buffer_params, session_params.samples);
-
- b_engine.use_highlight_tiles(session_params.progressive_refine == false);
+ const BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_null_space_view3d, b_null_region_view3d, scene->camera, width, height);
+ session->reset(session_params, buffer_params);
/* reset time */
start_resize_time = 0.0;
+
+ {
+ thread_scoped_lock lock(draw_state_.mutex);
+ draw_state_.last_pass_index = -1;
+ }
}
void BlenderSession::free_session()
{
- session->cancel();
+ if (session) {
+ session->cancel(true);
+ }
delete sync;
+ sync = nullptr;
+
delete session;
+ session = nullptr;
}
-static ShaderEvalType get_shader_type(const string &pass_type)
+void BlenderSession::read_render_tile()
{
- const char *shader_type = pass_type.c_str();
+ const int2 tile_offset = session->get_render_tile_offset();
+ const int2 tile_size = session->get_render_tile_size();
- /* data passes */
- if (strcmp(shader_type, "NORMAL") == 0)
- return SHADER_EVAL_NORMAL;
- else if (strcmp(shader_type, "UV") == 0)
- return SHADER_EVAL_UV;
- else if (strcmp(shader_type, "ROUGHNESS") == 0)
- return SHADER_EVAL_ROUGHNESS;
- else if (strcmp(shader_type, "DIFFUSE_COLOR") == 0)
- return SHADER_EVAL_DIFFUSE_COLOR;
- else if (strcmp(shader_type, "GLOSSY_COLOR") == 0)
- return SHADER_EVAL_GLOSSY_COLOR;
- else if (strcmp(shader_type, "TRANSMISSION_COLOR") == 0)
- return SHADER_EVAL_TRANSMISSION_COLOR;
- else if (strcmp(shader_type, "EMIT") == 0)
- return SHADER_EVAL_EMISSION;
+ /* get render result */
+ BL::RenderResult b_rr = b_engine.begin_result(tile_offset.x,
+ tile_offset.y,
+ tile_size.x,
+ tile_size.y,
+ b_rlay_name.c_str(),
+ b_rview_name.c_str());
- /* light passes */
- else if (strcmp(shader_type, "AO") == 0)
- return SHADER_EVAL_AO;
- else if (strcmp(shader_type, "COMBINED") == 0)
- return SHADER_EVAL_COMBINED;
- else if (strcmp(shader_type, "SHADOW") == 0)
- return SHADER_EVAL_SHADOW;
- else if (strcmp(shader_type, "DIFFUSE") == 0)
- return SHADER_EVAL_DIFFUSE;
- else if (strcmp(shader_type, "GLOSSY") == 0)
- return SHADER_EVAL_GLOSSY;
- else if (strcmp(shader_type, "TRANSMISSION") == 0)
- return SHADER_EVAL_TRANSMISSION;
+ /* can happen if the intersected rectangle gives 0 width or height */
+ if (b_rr.ptr.data == NULL) {
+ return;
+ }
- /* extra */
- else if (strcmp(shader_type, "ENVIRONMENT") == 0)
- return SHADER_EVAL_ENVIRONMENT;
+ BL::RenderResult::layers_iterator b_single_rlay;
+ b_rr.layers.begin(b_single_rlay);
- else
- return SHADER_EVAL_BAKE;
-}
+ /* layer will be missing if it was disabled in the UI */
+ if (b_single_rlay == b_rr.layers.end())
+ return;
-static BL::RenderResult begin_render_result(BL::RenderEngine &b_engine,
- int x,
- int y,
- int w,
- int h,
- const char *layername,
- const char *viewname)
-{
- return b_engine.begin_result(x, y, w, h, layername, viewname);
-}
+ BL::RenderLayer b_rlay = *b_single_rlay;
-static void end_render_result(BL::RenderEngine &b_engine,
- BL::RenderResult &b_rr,
- bool cancel,
- bool highlight,
- bool do_merge_results)
-{
- b_engine.end_result(b_rr, (int)cancel, (int)highlight, (int)do_merge_results);
+ vector<float> pixels(tile_size.x * tile_size.y * 4);
+
+ /* Copy each pass.
+ * TODO:copy only the required ones for better performance? */
+ for (BL::RenderPass &b_pass : b_rlay.passes) {
+ session->set_render_tile_pixels(b_pass.name(), b_pass.channels(), (float *)b_pass.rect());
+ }
}
-void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
- bool do_update_only,
- bool do_read_only,
- bool highlight)
+void BlenderSession::write_render_tile()
{
- int x = rtile.x - session->tile_manager.params.full_x;
- int y = rtile.y - session->tile_manager.params.full_y;
- int w = rtile.w;
- int h = rtile.h;
+ const int2 tile_offset = session->get_render_tile_offset();
+ const int2 tile_size = session->get_render_tile_size();
+
+ const string_view render_layer_name = session->get_render_tile_layer();
+ const string_view render_view_name = session->get_render_tile_view();
+
+ b_engine.tile_highlight_clear_all();
/* get render result */
- BL::RenderResult b_rr = begin_render_result(
- b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
+ BL::RenderResult b_rr = b_engine.begin_result(tile_offset.x,
+ tile_offset.y,
+ tile_size.x,
+ tile_size.y,
+ render_layer_name.c_str(),
+ render_view_name.c_str());
/* can happen if the intersected rectangle gives 0 width or height */
if (b_rr.ptr.data == NULL) {
@@ -349,64 +338,34 @@ void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
b_rr.layers.begin(b_single_rlay);
/* layer will be missing if it was disabled in the UI */
- if (b_single_rlay == b_rr.layers.end())
+ if (b_single_rlay == b_rr.layers.end()) {
return;
+ }
BL::RenderLayer b_rlay = *b_single_rlay;
- if (do_read_only) {
- /* copy each pass */
- for (BL::RenderPass &b_pass : b_rlay.passes) {
- /* find matching pass type */
- PassType pass_type = BlenderSync::get_pass_type(b_pass);
- int components = b_pass.channels();
-
- rtile.buffers->set_pass_rect(
- pass_type, components, (float *)b_pass.rect(), rtile.num_samples);
- }
-
- end_render_result(b_engine, b_rr, false, false, false);
- }
- else if (do_update_only) {
- /* Sample would be zero at initial tile update, which is only needed
- * to tag tile form blender side as IN PROGRESS for proper highlight
- * no buffers should be sent to blender yet. For denoise we also
- * keep showing the noisy buffers until denoise is done. */
- bool merge = (rtile.sample != 0) && (rtile.task != RenderTile::DENOISE);
+ write_render_result(b_rlay);
- if (merge) {
- update_render_result(b_rlay, rtile);
- }
-
- end_render_result(b_engine, b_rr, true, highlight, merge);
- }
- else {
- /* Write final render result. */
- write_render_result(b_rlay, rtile);
- end_render_result(b_engine, b_rr, false, false, true);
- }
+ b_engine.end_result(b_rr, true, false, true);
}
-void BlenderSession::read_render_tile(RenderTile &rtile)
+void BlenderSession::update_render_tile()
{
- do_write_update_render_tile(rtile, false, true, false);
-}
+ if (!session->has_multiple_render_tiles()) {
+ /* Don't highlight full-frame tile. */
+ return;
+ }
-void BlenderSession::write_render_tile(RenderTile &rtile)
-{
- do_write_update_render_tile(rtile, false, false, false);
+ const int2 tile_offset = session->get_render_tile_offset();
+ const int2 tile_size = session->get_render_tile_size();
+
+ b_engine.tile_highlight_clear_all();
+ b_engine.tile_highlight_set(tile_offset.x, tile_offset.y, tile_size.x, tile_size.y, true);
}
-void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
+void BlenderSession::full_buffer_written(string_view filename)
{
- /* use final write for preview renders, otherwise render result wouldn't be
- * be updated in blender side
- * would need to be investigated a bit further, but for now shall be fine
- */
- if (!b_engine.is_preview())
- do_write_update_render_tile(rtile, true, false, highlight);
- else
- do_write_update_render_tile(rtile, false, false, false);
+ full_buffer_files_.emplace_back(filename);
}
static void add_cryptomatte_layer(BL::RenderResult &b_rr, string name, string manifest)
@@ -430,12 +389,15 @@ void BlenderSession::stamp_view_layer_metadata(Scene *scene, const string &view_
to_string(session->params.samples).c_str());
/* Store ranged samples information. */
+ /* TODO(sergey): Need to bring this information back. */
+#if 0
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());
}
+#endif
/* Write cryptomatte metadata. */
if (scene->film->get_cryptomatte_passes() & CRYPT_OBJECT) {
@@ -475,38 +437,44 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
}
/* set callback to write out render results */
- session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
- session->update_render_tile_cb = function_bind(
- &BlenderSession::update_render_tile, this, _1, _2);
+ session->write_render_tile_cb = [&]() { write_render_tile(); };
+
+ /* Use final write for preview renders, otherwise render result wouldn't be be updated on Blender
+ * side. */
+ /* TODO(sergey): Investigate whether GPUDisplay can be used for the preview as well. */
+ if (b_engine.is_preview()) {
+ session->update_render_tile_cb = [&]() { write_render_tile(); };
+ }
+ else {
+ session->update_render_tile_cb = [&]() { update_render_tile(); };
+ }
+
+ session->full_buffer_written_cb = [&](string_view filename) { full_buffer_written(filename); };
BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
/* get buffer parameters */
- SessionParams session_params = BlenderSync::get_session_params(
- b_engine, b_userpref, b_scene, background, b_view_layer);
+ const SessionParams session_params = BlenderSync::get_session_params(
+ b_engine, b_userpref, b_scene, background);
BufferParams buffer_params = BlenderSync::get_buffer_params(
- b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
+ b_v3d, b_rv3d, scene->camera, width, height);
/* temporary render result to find needed passes and views */
- BL::RenderResult b_rr = begin_render_result(
- b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL);
+ BL::RenderResult b_rr = b_engine.begin_result(0, 0, 1, 1, b_view_layer.name().c_str(), NULL);
BL::RenderResult::layers_iterator b_single_rlay;
b_rr.layers.begin(b_single_rlay);
BL::RenderLayer b_rlay = *b_single_rlay;
- b_rlay_name = b_view_layer.name();
- /* Update denoising parameters. */
- session->set_denoising(session_params.denoising);
+ {
+ thread_scoped_lock lock(draw_state_.mutex);
+ b_rlay_name = b_view_layer.name();
- /* Compute render passes and film settings. */
- vector<Pass> passes = sync->sync_render_passes(
- b_scene, b_rlay, b_view_layer, session_params.adaptive_sampling, session_params.denoising);
+ /* Signal that the display pass is to be updated. */
+ draw_state_.last_pass_index = -1;
+ }
- /* Set buffer params, using film settings from sync_render_passes. */
- buffer_params.passes = passes;
- buffer_params.denoising_data_pass = scene->film->get_denoising_data_pass();
- buffer_params.denoising_clean_pass = scene->film->get_denoising_clean_pass();
- buffer_params.denoising_prefiltered_pass = scene->film->get_denoising_prefiltered_pass();
+ /* Compute render passes and film settings. */
+ sync->sync_render_passes(b_rlay, b_view_layer);
BL::RenderResult::views_iterator b_view_iter;
@@ -520,6 +488,9 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
++b_view_iter, ++view_index) {
b_rview_name = b_view_iter->name();
+ buffer_params.layer = b_view_layer.name();
+ buffer_params.view = b_rview_name;
+
/* set the current view */
b_engine.active_view_set(b_rview_name.c_str());
@@ -549,20 +520,16 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
}
/* Update number of samples per layer. */
- int samples = sync->get_layer_samples();
- bool bound_samples = sync->get_layer_bound_samples();
- int effective_layer_samples;
+ const int samples = sync->get_layer_samples();
+ const bool bound_samples = sync->get_layer_bound_samples();
- if (samples != 0 && (!bound_samples || (samples < session_params.samples)))
- effective_layer_samples = samples;
- else
- effective_layer_samples = session_params.samples;
-
- /* Update tile manager if we're doing resumable render. */
- update_resumable_tile_manager(effective_layer_samples);
+ SessionParams effective_session_params = session_params;
+ if (samples != 0 && (!bound_samples || (samples < session_params.samples))) {
+ effective_session_params.samples = samples;
+ }
/* Update session itself. */
- session->reset(buffer_params, effective_layer_samples);
+ session->reset(effective_session_params, buffer_params);
/* render */
if (!b_engine.is_preview() && background && print_render_stats) {
@@ -586,65 +553,146 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
stamp_view_layer_metadata(scene, b_rlay_name);
/* free result without merging */
- end_render_result(b_engine, b_rr, true, true, false);
+ b_engine.end_result(b_rr, true, false, false);
double total_time, render_time;
session->progress.get_time(total_time, render_time);
VLOG(1) << "Total render time: " << total_time;
VLOG(1) << "Render time (without synchronization): " << render_time;
+}
+
+void BlenderSession::render_frame_finish()
+{
+ /* Processing of all layers and views is done. Clear the strings so that we can communicate
+ * progress about reading files and denoising them. */
+ b_rlay_name = "";
+ b_rview_name = "";
+
+ if (!b_render.use_persistent_data()) {
+ /* Free the sync object so that it can properly dereference nodes from the scene graph before
+ * the graph is freed. */
+ delete sync;
+ sync = nullptr;
+
+ session->device_free();
+ }
+
+ for (string_view filename : full_buffer_files_) {
+ session->process_full_buffer_from_disk(filename);
+ path_remove(filename);
+ }
/* clear callback */
session->write_render_tile_cb = function_null;
session->update_render_tile_cb = function_null;
+ session->full_buffer_written_cb = function_null;
}
-static int bake_pass_filter_get(const int pass_filter)
+static PassType bake_type_to_pass(const string &bake_type_str, const int bake_filter)
{
- int flag = BAKE_FILTER_NONE;
-
- if ((pass_filter & BL::BakeSettings::pass_filter_DIRECT) != 0)
- flag |= BAKE_FILTER_DIRECT;
- if ((pass_filter & BL::BakeSettings::pass_filter_INDIRECT) != 0)
- flag |= BAKE_FILTER_INDIRECT;
- if ((pass_filter & BL::BakeSettings::pass_filter_COLOR) != 0)
- flag |= BAKE_FILTER_COLOR;
-
- if ((pass_filter & BL::BakeSettings::pass_filter_DIFFUSE) != 0)
- flag |= BAKE_FILTER_DIFFUSE;
- if ((pass_filter & BL::BakeSettings::pass_filter_GLOSSY) != 0)
- flag |= BAKE_FILTER_GLOSSY;
- if ((pass_filter & BL::BakeSettings::pass_filter_TRANSMISSION) != 0)
- flag |= BAKE_FILTER_TRANSMISSION;
-
- if ((pass_filter & BL::BakeSettings::pass_filter_EMIT) != 0)
- flag |= BAKE_FILTER_EMISSION;
- if ((pass_filter & BL::BakeSettings::pass_filter_AO) != 0)
- flag |= BAKE_FILTER_AO;
-
- return flag;
+ const char *bake_type = bake_type_str.c_str();
+
+ /* data passes */
+ if (strcmp(bake_type, "POSITION") == 0) {
+ return PASS_POSITION;
+ }
+ else if (strcmp(bake_type, "NORMAL") == 0) {
+ return PASS_NORMAL;
+ }
+ else if (strcmp(bake_type, "UV") == 0) {
+ return PASS_UV;
+ }
+ else if (strcmp(bake_type, "ROUGHNESS") == 0) {
+ return PASS_ROUGHNESS;
+ }
+ else if (strcmp(bake_type, "EMIT") == 0) {
+ return PASS_EMISSION;
+ }
+ /* light passes */
+ else if (strcmp(bake_type, "AO") == 0) {
+ return PASS_AO;
+ }
+ else if (strcmp(bake_type, "COMBINED") == 0) {
+ return PASS_COMBINED;
+ }
+ else if (strcmp(bake_type, "SHADOW") == 0) {
+ return PASS_SHADOW;
+ }
+ else if (strcmp(bake_type, "DIFFUSE") == 0) {
+ if ((bake_filter & BL::BakeSettings::pass_filter_DIRECT) &&
+ bake_filter & BL::BakeSettings::pass_filter_INDIRECT) {
+ return PASS_DIFFUSE;
+ }
+ else if (bake_filter & BL::BakeSettings::pass_filter_DIRECT) {
+ return PASS_DIFFUSE_DIRECT;
+ }
+ else if (bake_filter & BL::BakeSettings::pass_filter_INDIRECT) {
+ return PASS_DIFFUSE_INDIRECT;
+ }
+ else {
+ return PASS_DIFFUSE_COLOR;
+ }
+ }
+ else if (strcmp(bake_type, "GLOSSY") == 0) {
+ if ((bake_filter & BL::BakeSettings::pass_filter_DIRECT) &&
+ bake_filter & BL::BakeSettings::pass_filter_INDIRECT) {
+ return PASS_GLOSSY;
+ }
+ else if (bake_filter & BL::BakeSettings::pass_filter_DIRECT) {
+ return PASS_GLOSSY_DIRECT;
+ }
+ else if (bake_filter & BL::BakeSettings::pass_filter_INDIRECT) {
+ return PASS_GLOSSY_INDIRECT;
+ }
+ else {
+ return PASS_GLOSSY_COLOR;
+ }
+ }
+ else if (strcmp(bake_type, "TRANSMISSION") == 0) {
+ if ((bake_filter & BL::BakeSettings::pass_filter_DIRECT) &&
+ bake_filter & BL::BakeSettings::pass_filter_INDIRECT) {
+ return PASS_TRANSMISSION;
+ }
+ else if (bake_filter & BL::BakeSettings::pass_filter_DIRECT) {
+ return PASS_TRANSMISSION_DIRECT;
+ }
+ else if (bake_filter & BL::BakeSettings::pass_filter_INDIRECT) {
+ return PASS_TRANSMISSION_INDIRECT;
+ }
+ else {
+ return PASS_TRANSMISSION_COLOR;
+ }
+ }
+ /* extra */
+ else if (strcmp(bake_type, "ENVIRONMENT") == 0) {
+ return PASS_BACKGROUND;
+ }
+
+ return PASS_COMBINED;
}
void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
BL::Object &b_object,
- const string &pass_type,
- const int pass_filter,
+ const string &bake_type,
+ const int bake_filter,
const int bake_width,
const int bake_height)
{
b_depsgraph = b_depsgraph_;
- ShaderEvalType shader_type = get_shader_type(pass_type);
- int bake_pass_filter = bake_pass_filter_get(pass_filter);
-
/* Initialize bake manager, before we load the baking kernels. */
- scene->bake_manager->set(scene, b_object.name(), shader_type, bake_pass_filter);
+ scene->bake_manager->set(scene, b_object.name());
- /* Passes are identified by name, so in order to return the combined pass we need to set the
- * name. */
- Pass::add(PASS_COMBINED, scene->passes, "Combined");
+ /* Add render pass that we want to bake, and name it Combined so that it is
+ * used as that on the Blender side. */
+ Pass *pass = scene->create_node<Pass>();
+ pass->set_name(ustring("Combined"));
+ pass->set_type(bake_type_to_pass(bake_type, bake_filter));
+ pass->set_include_albedo((bake_filter & BL::BakeSettings::pass_filter_COLOR));
- session->read_bake_tile_cb = function_bind(&BlenderSession::read_render_tile, this, _1);
- session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
+ session->read_render_tile_cb = [&]() { read_render_tile(); };
+ session->write_render_tile_cb = [&]() { write_render_tile(); };
+ session->set_gpu_display(nullptr);
if (!session->progress.get_cancel()) {
/* Sync scene. */
@@ -667,18 +715,15 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
if (object_found && !session->progress.get_cancel()) {
/* Get session and buffer parameters. */
- SessionParams session_params = BlenderSync::get_session_params(
+ const SessionParams session_params = BlenderSync::get_session_params(
b_engine, b_userpref, b_scene, background);
- session_params.progressive_refine = false;
BufferParams buffer_params;
buffer_params.width = bake_width;
buffer_params.height = bake_height;
- buffer_params.passes = scene->passes;
/* Update session. */
- session->tile_manager.set_samples(session_params.samples);
- session->reset(buffer_params, session_params.samples);
+ session->reset(session_params, buffer_params);
session->progress.set_update_callback(
function_bind(&BlenderSession::update_bake_progress, this));
@@ -690,71 +735,43 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
session->wait();
}
- session->read_bake_tile_cb = function_null;
+ session->read_render_tile_cb = function_null;
session->write_render_tile_cb = function_null;
}
-void BlenderSession::do_write_update_render_result(BL::RenderLayer &b_rlay,
- RenderTile &rtile,
- bool do_update_only)
+void BlenderSession::write_render_result(BL::RenderLayer &b_rlay)
{
- RenderBuffers *buffers = rtile.buffers;
-
- /* copy data from device */
- if (!buffers->copy_from_device())
+ if (!session->copy_render_tile_from_device()) {
return;
-
- float exposure = scene->film->get_exposure();
-
- vector<float> pixels(rtile.w * rtile.h * 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 */
- for (BL::RenderPass &b_pass : b_rlay.passes) {
- int components = b_pass.channels();
-
- /* Copy pixels from regular render passes. */
- bool read = buffers->get_pass_rect(b_pass.name(), exposure, sample, components, &pixels[0]);
-
- /* If denoising pass, */
- if (!read) {
- int denoising_offset = BlenderSync::get_denoising_pass(b_pass);
- if (denoising_offset >= 0) {
- read = buffers->get_denoising_pass_rect(
- denoising_offset, exposure, sample, components, &pixels[0]);
- }
- }
+ const int2 tile_size = session->get_render_tile_size();
+ vector<float> pixels(tile_size.x * tile_size.y * 4);
- if (!read) {
- memset(&pixels[0], 0, pixels.size() * sizeof(float));
- }
-
- b_pass.rect(&pixels[0]);
+ /* Copy each pass. */
+ for (BL::RenderPass &b_pass : b_rlay.passes) {
+ if (!session->get_render_tile_pixels(b_pass.name(), b_pass.channels(), &pixels[0])) {
+ memset(&pixels[0], 0, pixels.size() * sizeof(float));
}
- }
- else {
- /* copy combined pass */
- BL::RenderPass b_combined_pass(b_rlay.passes.find_by_name("Combined", b_rview_name.c_str()));
- if (buffers->get_pass_rect("Combined", exposure, sample, 4, &pixels[0]))
- b_combined_pass.rect(&pixels[0]);
+
+ b_pass.rect(&pixels[0]);
}
}
-void BlenderSession::write_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile)
+void BlenderSession::update_render_result(BL::RenderLayer &b_rlay)
{
- do_write_update_render_result(b_rlay, rtile, false);
-}
+ if (!session->copy_render_tile_from_device()) {
+ return;
+ }
-void BlenderSession::update_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile)
-{
- do_write_update_render_result(b_rlay, rtile, true);
+ const int2 tile_size = session->get_render_tile_size();
+ vector<float> pixels(tile_size.x * tile_size.y * 4);
+
+ /* Copy combined pass. */
+ BL::RenderPass b_combined_pass(b_rlay.passes.find_by_name("Combined", b_rview_name.c_str()));
+ if (session->get_render_tile_pixels("Combined", b_combined_pass.channels(), &pixels[0])) {
+ b_combined_pass.rect(&pixels[0]);
+ }
}
void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
@@ -764,19 +781,19 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
return;
/* on session/scene parameter changes, we recreate session entirely */
- SessionParams session_params = BlenderSync::get_session_params(
+ const SessionParams session_params = BlenderSync::get_session_params(
b_engine, b_userpref, b_scene, background);
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
- bool session_pause = BlenderSync::get_session_pause(b_scene, background);
+ const SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
+ const bool session_pause = BlenderSync::get_session_pause(b_scene, background);
if (session->params.modified(session_params) || scene->params.modified(scene_params)) {
free_session();
create_session();
}
- /* increase samples, but never decrease */
+ /* increase samples and render time, but never decrease */
session->set_samples(session_params.samples);
- session->set_denoising_start_sample(session_params.denoising.start_sample);
+ session->set_time_limit(session_params.time_limit);
session->set_pause(session_pause);
/* copy recalc flags, outside of mutex so we can decide to do the real
@@ -808,21 +825,12 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
sync->sync_camera(b_render, b_camera_override, width, height, "");
/* get buffer parameters */
- BufferParams buffer_params = BlenderSync::get_buffer_params(
- b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
-
- if (!buffer_params.denoising_data_pass) {
- session_params.denoising.use = false;
- }
-
- session->set_denoising(session_params.denoising);
-
- /* Update film if denoising data was enabled or disabled. */
- scene->film->set_denoising_data_pass(buffer_params.denoising_data_pass);
+ const BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_v3d, b_rv3d, scene->camera, width, height);
/* reset if needed */
if (scene->need_reset()) {
- session->reset(buffer_params, session_params.samples);
+ session->reset(session_params, buffer_params);
/* After session reset, so device is not accessing image data anymore. */
builtin_images_load();
@@ -839,7 +847,41 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
session->start();
}
-bool BlenderSession::draw(int w, int h)
+void BlenderSession::draw(BL::SpaceImageEditor &space_image)
+{
+ if (!session || !session->scene) {
+ /* Offline render drawing does not force the render engine update, which means it's possible
+ * that the Session is not created yet. */
+ return;
+ }
+
+ thread_scoped_lock lock(draw_state_.mutex);
+
+ const int pass_index = space_image.image_user().multilayer_pass();
+ if (pass_index != draw_state_.last_pass_index) {
+ BL::RenderPass b_display_pass(b_engine.pass_by_index_get(b_rlay_name.c_str(), pass_index));
+ if (!b_display_pass) {
+ return;
+ }
+
+ Scene *scene = session->scene;
+
+ thread_scoped_lock lock(scene->mutex);
+
+ const Pass *pass = Pass::find(scene->passes, b_display_pass.name());
+ if (!pass) {
+ return;
+ }
+
+ scene->film->set_display_pass(pass->get_type());
+
+ draw_state_.last_pass_index = pass_index;
+ }
+
+ session->draw();
+}
+
+void BlenderSession::view_draw(int w, int h)
{
/* pause in redraw in case update is not being called due to final render */
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
@@ -885,14 +927,14 @@ bool BlenderSession::draw(int w, int h)
/* reset if requested */
if (reset) {
- SessionParams session_params = BlenderSync::get_session_params(
+ const SessionParams session_params = BlenderSync::get_session_params(
b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(
- b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
- bool session_pause = BlenderSync::get_session_pause(b_scene, background);
+ const BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_v3d, b_rv3d, scene->camera, width, height);
+ const bool session_pause = BlenderSync::get_session_pause(b_scene, background);
if (session_pause == false) {
- session->reset(buffer_params, session_params.samples);
+ session->reset(session_params, buffer_params);
start_resize_time = 0.0;
}
}
@@ -905,18 +947,7 @@ bool BlenderSession::draw(int w, int h)
update_status_progress();
/* draw */
- BufferParams buffer_params = BlenderSync::get_buffer_params(
- b_v3d, b_rv3d, scene->camera, width, height, session->params.denoising.use);
- DeviceDrawParams draw_params;
-
- if (session->params.display_buffer_linear) {
- draw_params.bind_display_space_shader_cb = function_bind(
- &BL::RenderEngine::bind_display_space_shader, &b_engine, b_scene);
- draw_params.unbind_display_space_shader_cb = function_bind(
- &BL::RenderEngine::unbind_display_space_shader, &b_engine);
- }
-
- return !session->draw(buffer_params, draw_params);
+ session->draw();
}
void BlenderSession::get_status(string &status, string &substatus)
@@ -924,11 +955,6 @@ void BlenderSession::get_status(string &status, string &substatus)
session->progress.get_status(status, substatus);
}
-void BlenderSession::get_kernel_status(string &kernel_status)
-{
- session->progress.get_kernel_status(kernel_status);
-}
-
void BlenderSession::get_progress(float &progress, double &total_time, double &render_time)
{
session->progress.get_time(total_time, render_time);
@@ -947,7 +973,7 @@ void BlenderSession::update_bake_progress()
void BlenderSession::update_status_progress()
{
- string timestatus, status, substatus, kernel_status;
+ string timestatus, status, substatus;
string scene_status = "";
float progress;
double total_time, remaining_time = 0, render_time;
@@ -955,7 +981,6 @@ void BlenderSession::update_status_progress()
float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
get_status(status, substatus);
- get_kernel_status(kernel_status);
get_progress(progress, total_time, render_time);
if (progress > 0)
@@ -980,14 +1005,12 @@ void BlenderSession::update_status_progress()
status = " | " + status;
if (substatus.size() > 0)
status += " | " + substatus;
- if (kernel_status.size() > 0)
- status += " | " + kernel_status;
}
double current_time = time_dt();
- /* When rendering in a window, redraw the status at least once per second to keep the elapsed and
- * remaining time up-to-date. For headless rendering, only report when something significant
- * changes to keep the console output readable. */
+ /* When rendering in a window, redraw the status at least once per second to keep the elapsed
+ * and remaining time up-to-date. For headless rendering, only report when something
+ * significant changes to keep the console output readable. */
if (status != last_status || (!headless && (current_time - last_status_time) > 1.0)) {
b_engine.update_stats("", (timestatus + scene_status + status).c_str());
b_engine.update_memory_stats(mem_used, mem_peak);
@@ -1048,56 +1071,6 @@ void BlenderSession::test_cancel()
session->progress.set_cancel("Cancelled");
}
-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;
- }
-
- if (num_resumable_chunks > num_samples) {
- fprintf(stderr,
- "Cycles warning: more sample chunks (%d) than samples (%d), "
- "this will cause some samples to be included in multiple chunks.\n",
- num_resumable_chunks,
- num_samples);
- }
-
- const float num_samples_per_chunk = (float)num_samples / num_resumable_chunks;
-
- float range_start_sample, range_num_samples;
- if (current_resumable_chunk != 0) {
- /* Single chunk rendering. */
- range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
- range_num_samples = num_samples_per_chunk;
- }
- else {
- /* Ranged-chunks. */
- const int num_chunks = end_resumable_chunk - start_resumable_chunk + 1;
- range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1);
- range_num_samples = num_chunks * num_samples_per_chunk;
- }
-
- /* Round after doing the multiplications with num_chunks and num_samples_per_chunk
- * to allow for many small chunks. */
- int rounded_range_start_sample = (int)floorf(range_start_sample + 0.5f);
- int rounded_range_num_samples = max((int)floorf(range_num_samples + 0.5f), 1);
-
- /* Make sure we don't overshoot. */
- if (rounded_range_start_sample + rounded_range_num_samples > num_samples) {
- rounded_range_num_samples = num_samples - rounded_range_num_samples;
- }
-
- VLOG(1) << "Samples range start is " << range_start_sample << ", "
- << "number of samples to render is " << range_num_samples;
-
- scene->integrator->set_start_sample(rounded_range_start_sample);
-
- session->tile_manager.range_start_sample = rounded_range_start_sample;
- session->tile_manager.range_num_samples = rounded_range_num_samples;
-}
-
void BlenderSession::free_blender_memory_if_possible()
{
if (!background) {