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/render/session.cpp')
-rw-r--r--intern/cycles/render/session.cpp631
1 files changed, 0 insertions, 631 deletions
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
deleted file mode 100644
index a18c61599c2..00000000000
--- a/intern/cycles/render/session.cpp
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <limits.h>
-#include <string.h>
-
-#include "device/cpu/device.h"
-#include "device/device.h"
-#include "integrator/pass_accessor_cpu.h"
-#include "integrator/path_trace.h"
-#include "render/background.h"
-#include "render/bake.h"
-#include "render/buffers.h"
-#include "render/camera.h"
-#include "render/display_driver.h"
-#include "render/graph.h"
-#include "render/integrator.h"
-#include "render/light.h"
-#include "render/mesh.h"
-#include "render/object.h"
-#include "render/output_driver.h"
-#include "render/scene.h"
-#include "render/session.h"
-
-#include "util/util_foreach.h"
-#include "util/util_function.h"
-#include "util/util_logging.h"
-#include "util/util_math.h"
-#include "util/util_task.h"
-#include "util/util_time.h"
-
-CCL_NAMESPACE_BEGIN
-
-Session::Session(const SessionParams &params_, const SceneParams &scene_params)
- : params(params_), render_scheduler_(tile_manager_, params)
-{
- TaskScheduler::init(params.threads);
-
- session_thread_ = nullptr;
-
- delayed_reset_.do_reset = false;
-
- pause_ = false;
- cancel_ = false;
- new_work_added_ = false;
-
- device = Device::create(params.device, stats, profiler);
-
- scene = new Scene(scene_params, device);
-
- /* Configure path tracer. */
- path_trace_ = make_unique<PathTrace>(
- device, scene->film, &scene->dscene, render_scheduler_, tile_manager_);
- path_trace_->set_progress(&progress);
- path_trace_->progress_update_cb = [&]() { update_status_time(); };
-
- tile_manager_.full_buffer_written_cb = [&](string_view filename) {
- if (!full_buffer_written_cb) {
- return;
- }
- full_buffer_written_cb(filename);
- };
-}
-
-Session::~Session()
-{
- cancel();
-
- /* Make sure path tracer is destroyed before the device. This is needed because destruction might
- * need to access device for device memory free. */
- /* TODO(sergey): Convert device to be unique_ptr, and rely on C++ to destruct objects in the
- * pre-defined order. */
- path_trace_.reset();
-
- delete scene;
- delete device;
-
- TaskScheduler::exit();
-}
-
-void Session::start()
-{
- if (!session_thread_) {
- session_thread_ = new thread(function_bind(&Session::run, this));
- }
-}
-
-void Session::cancel(bool quick)
-{
- if (quick && path_trace_) {
- path_trace_->cancel();
- }
-
- if (session_thread_) {
- /* wait for session thread to end */
- progress.set_cancel("Exiting");
-
- {
- thread_scoped_lock pause_lock(pause_mutex_);
- pause_ = false;
- cancel_ = true;
- }
- pause_cond_.notify_all();
-
- wait();
- }
-}
-
-bool Session::ready_to_reset()
-{
- return path_trace_->ready_to_reset();
-}
-
-void Session::run_main_render_loop()
-{
- path_trace_->clear_display();
-
- while (true) {
- RenderWork render_work = run_update_for_next_iteration();
-
- if (!render_work) {
- if (VLOG_IS_ON(2)) {
- double total_time, render_time;
- progress.get_time(total_time, render_time);
- VLOG(2) << "Rendering in main loop is done in " << render_time << " seconds.";
- VLOG(2) << path_trace_->full_report();
- }
-
- if (params.background) {
- /* if no work left and in background mode, we can stop immediately. */
- progress.set_status("Finished");
- break;
- }
- }
-
- const bool did_cancel = progress.get_cancel();
- if (did_cancel) {
- render_scheduler_.render_work_reschedule_on_cancel(render_work);
- if (!render_work) {
- break;
- }
- }
- else if (run_wait_for_work(render_work)) {
- continue;
- }
-
- /* Stop rendering if error happened during scene update or other step of preparing scene
- * for render. */
- if (device->have_error()) {
- progress.set_error(device->error_message());
- break;
- }
-
- {
- /* buffers mutex is locked entirely while rendering each
- * sample, and released/reacquired on each iteration to allow
- * reset and draw in between */
- thread_scoped_lock buffers_lock(buffers_mutex_);
-
- /* update status and timing */
- update_status_time();
-
- /* render */
- path_trace_->render(render_work);
-
- /* update status and timing */
- update_status_time();
-
- /* Stop rendering if error happened during path tracing. */
- if (device->have_error()) {
- progress.set_error(device->error_message());
- break;
- }
- }
-
- progress.set_update();
-
- if (did_cancel) {
- break;
- }
- }
-}
-
-void Session::run()
-{
- if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
- profiler.start();
- }
-
- /* session thread loop */
- progress.set_status("Waiting for render to start");
-
- /* run */
- if (!progress.get_cancel()) {
- /* reset number of rendered samples */
- progress.reset_sample();
-
- run_main_render_loop();
- }
-
- profiler.stop();
-
- /* progress update */
- if (progress.get_cancel())
- progress.set_status(progress.get_cancel_message());
- else
- progress.set_update();
-}
-
-RenderWork Session::run_update_for_next_iteration()
-{
- RenderWork render_work;
-
- thread_scoped_lock scene_lock(scene->mutex);
- thread_scoped_lock reset_lock(delayed_reset_.mutex);
-
- bool have_tiles = true;
- bool switched_to_new_tile = false;
-
- const bool did_reset = delayed_reset_.do_reset;
- if (delayed_reset_.do_reset) {
- thread_scoped_lock buffers_lock(buffers_mutex_);
- do_delayed_reset();
-
- /* After reset make sure the tile manager is at the first big tile. */
- have_tiles = tile_manager_.next();
- switched_to_new_tile = true;
- }
-
- /* Update number of samples in the integrator.
- * Ideally this would need to happen once in `Session::set_samples()`, but the issue there is
- * the initial configuration when Session is created where the `set_samples()` is not used.
- *
- * NOTE: Unless reset was requested only allow increasing number of samples. */
- if (did_reset || scene->integrator->get_aa_samples() < params.samples) {
- scene->integrator->set_aa_samples(params.samples);
- }
-
- /* Update denoiser settings. */
- {
- const DenoiseParams denoise_params = scene->integrator->get_denoise_params();
- path_trace_->set_denoiser_params(denoise_params);
- }
-
- /* Update adaptive sampling. */
- {
- const AdaptiveSampling adaptive_sampling = scene->integrator->get_adaptive_sampling();
- path_trace_->set_adaptive_sampling(adaptive_sampling);
- }
-
- render_scheduler_.set_num_samples(params.samples);
- render_scheduler_.set_time_limit(params.time_limit);
-
- while (have_tiles) {
- render_work = render_scheduler_.get_render_work();
- if (render_work) {
- break;
- }
-
- progress.add_finished_tile(false);
-
- have_tiles = tile_manager_.next();
- if (have_tiles) {
- render_scheduler_.reset_for_next_tile();
- switched_to_new_tile = true;
- }
- }
-
- if (render_work) {
- scoped_timer update_timer;
-
- if (switched_to_new_tile) {
- BufferParams tile_params = buffer_params_;
-
- const Tile &tile = tile_manager_.get_current_tile();
-
- tile_params.width = tile.width;
- tile_params.height = tile.height;
-
- tile_params.window_x = tile.window_x;
- tile_params.window_y = tile.window_y;
- tile_params.window_width = tile.window_width;
- tile_params.window_height = tile.window_height;
-
- tile_params.full_x = tile.x + buffer_params_.full_x;
- tile_params.full_y = tile.y + buffer_params_.full_y;
- tile_params.full_width = buffer_params_.full_width;
- tile_params.full_height = buffer_params_.full_height;
-
- tile_params.update_offset_stride();
-
- path_trace_->reset(buffer_params_, tile_params);
- }
-
- const int resolution = render_work.resolution_divider;
- const int width = max(1, buffer_params_.full_width / resolution);
- const int height = max(1, buffer_params_.full_height / resolution);
-
- if (update_scene(width, height)) {
- profiler.reset(scene->shaders.size(), scene->objects.size());
- }
- progress.add_skip_time(update_timer, params.background);
- }
-
- return render_work;
-}
-
-bool Session::run_wait_for_work(const RenderWork &render_work)
-{
- /* In an offline rendering there is no pause, and no tiles will mean the job is fully done. */
- if (params.background) {
- return false;
- }
-
- thread_scoped_lock pause_lock(pause_mutex_);
-
- if (!pause_ && render_work) {
- /* Rendering is not paused and there is work to be done. No need to wait for anything. */
- return false;
- }
-
- const bool no_work = !render_work;
- update_status_time(pause_, no_work);
-
- /* Only leave the loop when rendering is not paused. But even if the current render is un-paused
- * but there is nothing to render keep waiting until new work is added. */
- while (!cancel_) {
- scoped_timer pause_timer;
-
- if (!pause_ && (render_work || new_work_added_ || delayed_reset_.do_reset)) {
- break;
- }
-
- /* Wait for either pause state changed, or extra samples added to render. */
- pause_cond_.wait(pause_lock);
-
- if (pause_) {
- progress.add_skip_time(pause_timer, params.background);
- }
-
- update_status_time(pause_, no_work);
- progress.set_update();
- }
-
- new_work_added_ = false;
-
- return no_work;
-}
-
-void Session::draw()
-{
- path_trace_->draw();
-}
-
-int2 Session::get_effective_tile_size() const
-{
- /* No support yet for baking with tiles. */
- if (!params.use_auto_tile || scene->bake_manager->get_baking()) {
- return make_int2(buffer_params_.width, buffer_params_.height);
- }
-
- /* TODO(sergey): Take available memory into account, and if there is enough memory do not tile
- * and prefer optimal performance. */
- const int tile_size = tile_manager_.compute_render_tile_size(params.tile_size);
- return make_int2(tile_size, tile_size);
-}
-
-void Session::do_delayed_reset()
-{
- if (!delayed_reset_.do_reset) {
- return;
- }
- delayed_reset_.do_reset = false;
-
- params = delayed_reset_.session_params;
- buffer_params_ = delayed_reset_.buffer_params;
-
- /* Store parameters used for buffers access outside of scene graph. */
- buffer_params_.samples = params.samples;
- buffer_params_.exposure = scene->film->get_exposure();
- buffer_params_.use_approximate_shadow_catcher =
- scene->film->get_use_approximate_shadow_catcher();
- buffer_params_.use_transparent_background = scene->background->get_transparent();
-
- /* Tile and work scheduling. */
- tile_manager_.reset_scheduling(buffer_params_, get_effective_tile_size());
- render_scheduler_.reset(buffer_params_, params.samples);
-
- /* Passes. */
- /* When multiple tiles are used SAMPLE_COUNT pass is used to keep track of possible partial
- * tile results. It is safe to use generic update function here which checks for changes since
- * changes in tile settings re-creates session, which ensures film is fully updated on tile
- * changes. */
- scene->film->update_passes(scene, tile_manager_.has_multiple_tiles());
-
- /* Update for new state of scene and passes. */
- buffer_params_.update_passes(scene->passes);
- tile_manager_.update(buffer_params_, scene);
-
- /* Progress. */
- progress.reset_sample();
- progress.set_total_pixel_samples(static_cast<uint64_t>(buffer_params_.width) *
- buffer_params_.height * params.samples);
-
- if (!params.background) {
- progress.set_start_time();
- }
- progress.set_render_start_time();
-}
-
-void Session::reset(const SessionParams &session_params, const BufferParams &buffer_params)
-{
- {
- thread_scoped_lock reset_lock(delayed_reset_.mutex);
- thread_scoped_lock pause_lock(pause_mutex_);
-
- delayed_reset_.do_reset = true;
- delayed_reset_.session_params = session_params;
- delayed_reset_.buffer_params = buffer_params;
-
- path_trace_->cancel();
- }
-
- pause_cond_.notify_all();
-}
-
-void Session::set_samples(int samples)
-{
- if (samples == params.samples) {
- return;
- }
-
- params.samples = samples;
-
- {
- thread_scoped_lock pause_lock(pause_mutex_);
- new_work_added_ = true;
- }
-
- pause_cond_.notify_all();
-}
-
-void Session::set_time_limit(double time_limit)
-{
- if (time_limit == params.time_limit) {
- return;
- }
-
- params.time_limit = time_limit;
-
- {
- thread_scoped_lock pause_lock(pause_mutex_);
- new_work_added_ = true;
- }
-
- pause_cond_.notify_all();
-}
-
-void Session::set_pause(bool pause)
-{
- bool notify = false;
-
- {
- thread_scoped_lock pause_lock(pause_mutex_);
-
- if (pause != pause_) {
- pause_ = pause;
- notify = true;
- }
- }
-
- if (session_thread_) {
- if (notify) {
- pause_cond_.notify_all();
- }
- }
- else if (pause_) {
- update_status_time(pause_);
- }
-}
-
-void Session::set_output_driver(unique_ptr<OutputDriver> driver)
-{
- path_trace_->set_output_driver(move(driver));
-}
-
-void Session::set_display_driver(unique_ptr<DisplayDriver> driver)
-{
- path_trace_->set_display_driver(move(driver));
-}
-
-double Session::get_estimated_remaining_time() const
-{
- const float completed = progress.get_progress();
- if (completed == 0.0f) {
- return 0.0;
- }
-
- double total_time, render_time;
- progress.get_time(total_time, render_time);
- double remaining = (1.0 - (double)completed) * (render_time / (double)completed);
-
- const double time_limit = render_scheduler_.get_time_limit();
- if (time_limit != 0.0) {
- remaining = min(remaining, max(time_limit - render_time, 0.0));
- }
-
- return remaining;
-}
-
-void Session::wait()
-{
- if (session_thread_) {
- session_thread_->join();
- delete session_thread_;
- }
-
- session_thread_ = nullptr;
-}
-
-bool Session::update_scene(int width, int height)
-{
- /* Update camera if dimensions changed for progressive render. the camera
- * knows nothing about progressive or cropped rendering, it just gets the
- * image dimensions passed in. */
- Camera *cam = scene->camera;
- cam->set_screen_size(width, height);
-
- /* First detect which kernel features are used and allocate working memory.
- * This helps estimate how may device memory is available for the scene and
- * how much we need to allocate on the host instead. */
- scene->update_kernel_features();
-
- path_trace_->load_kernels();
- path_trace_->alloc_work_memory();
-
- if (scene->update(progress)) {
- return true;
- }
-
- return false;
-}
-
-static string status_append(const string &status, const string &suffix)
-{
- string prefix = status;
- if (!prefix.empty()) {
- prefix += ", ";
- }
- return prefix + suffix;
-}
-
-void Session::update_status_time(bool show_pause, bool show_done)
-{
- string status, substatus;
-
- const int current_tile = progress.get_rendered_tiles();
- const int num_tiles = tile_manager_.get_num_tiles();
-
- const int current_sample = progress.get_current_sample();
- const int num_samples = render_scheduler_.get_num_samples();
-
- /* TIle. */
- if (tile_manager_.has_multiple_tiles()) {
- substatus = status_append(substatus,
- string_printf("Rendered %d/%d Tiles", current_tile, num_tiles));
- }
-
- /* Sample. */
- if (num_samples == Integrator::MAX_SAMPLES) {
- substatus = status_append(substatus, string_printf("Sample %d", current_sample));
- }
- else {
- substatus = status_append(substatus,
- string_printf("Sample %d/%d", current_sample, num_samples));
- }
-
- /* TODO(sergey): Denoising status from the path trace. */
-
- if (show_pause) {
- status = "Rendering Paused";
- }
- else if (show_done) {
- status = "Rendering Done";
- progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
- }
- else {
- status = substatus;
- substatus.clear();
- }
-
- progress.set_status(status, substatus);
-}
-
-void Session::device_free()
-{
- scene->device_free();
- path_trace_->device_free();
-}
-
-void Session::collect_statistics(RenderStats *render_stats)
-{
- scene->collect_statistics(render_stats);
- if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
- render_stats->collect_profiling(scene, profiler);
- }
-}
-
-/* --------------------------------------------------------------------
- * Full-frame on-disk storage.
- */
-
-void Session::process_full_buffer_from_disk(string_view filename)
-{
- path_trace_->process_full_buffer_from_disk(filename);
-}
-
-CCL_NAMESPACE_END