Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/session.cpp
| Show All 37 Lines | |||||
| #include "util/util_math.h" | #include "util/util_math.h" | ||||
| #include "util/util_opengl.h" | #include "util/util_opengl.h" | ||||
| #include "util/util_task.h" | #include "util/util_task.h" | ||||
| #include "util/util_time.h" | #include "util/util_time.h" | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| Session::Session(const SessionParams ¶ms_, const SceneParams &scene_params) | Session::Session(const SessionParams ¶ms_, const SceneParams &scene_params) | ||||
| : params(params_), render_scheduler_(params.headless, params.background, params.pixel_size) | : params(params_), render_scheduler_(tile_manager_, params) | ||||
| { | { | ||||
| TaskScheduler::init(params.threads); | TaskScheduler::init(params.threads); | ||||
| session_thread_ = nullptr; | session_thread_ = nullptr; | ||||
| delayed_reset_.do_reset = false; | delayed_reset_.do_reset = false; | ||||
| delayed_reset_.samples = 0; | delayed_reset_.samples = 0; | ||||
| pause_ = false; | pause_ = false; | ||||
| cancel_ = false; | cancel_ = false; | ||||
| new_work_added_ = false; | new_work_added_ = false; | ||||
| device = Device::create(params.device, stats, profiler); | device = Device::create(params.device, stats, profiler); | ||||
| scene = new Scene(scene_params, device); | scene = new Scene(scene_params, device); | ||||
| /* Configure path tracer. */ | /* Configure path tracer. */ | ||||
| path_trace_ = make_unique<PathTrace>(device, scene->film, &scene->dscene, render_scheduler_); | path_trace_ = make_unique<PathTrace>( | ||||
| device, scene->film, &scene->dscene, render_scheduler_, tile_manager_); | |||||
| path_trace_->set_progress(&progress); | path_trace_->set_progress(&progress); | ||||
| path_trace_->buffer_update_cb = [&]() { | path_trace_->tile_buffer_update_cb = [&]() { | ||||
| if (!update_render_tile_cb) { | if (!update_render_tile_cb) { | ||||
| return; | return; | ||||
| } | } | ||||
| update_render_tile_cb(); | update_render_tile_cb(); | ||||
| }; | }; | ||||
| path_trace_->buffer_write_cb = [&]() { | path_trace_->tile_buffer_write_cb = [&]() { | ||||
| if (!write_render_tile_cb) { | if (!write_render_tile_cb) { | ||||
| return; | return; | ||||
| } | } | ||||
| write_render_tile_cb(); | write_render_tile_cb(); | ||||
| }; | }; | ||||
| path_trace_->buffer_read_cb = [&]() -> bool { | path_trace_->tile_buffer_read_cb = [&]() -> bool { | ||||
| if (!read_render_tile_cb) { | if (!read_render_tile_cb) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| read_render_tile_cb(); | read_render_tile_cb(); | ||||
| return true; | return true; | ||||
| }; | }; | ||||
| path_trace_->progress_update_cb = [&]() { update_status_time(); }; | path_trace_->progress_update_cb = [&]() { update_status_time(); }; | ||||
| } | } | ||||
| Show All 21 Lines | |||||
| #endif | #endif | ||||
| /* Make sure path tracer is destroyed before the deviec. This is needed because destruction might | /* Make sure path tracer is destroyed before the deviec. This is needed because destruction might | ||||
| * need to access device for device memory free. */ | * 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 | /* TODO(sergey): Convert device to be unique_ptr, and rely on C++ to destruct objects in the | ||||
| * pre-defined order. */ | * pre-defined order. */ | ||||
| path_trace_.reset(); | path_trace_.reset(); | ||||
| #if 0 | |||||
| /* clean up */ | |||||
| tile_manager_.device_free(); | |||||
| #endif | |||||
| delete scene; | delete scene; | ||||
| delete device; | delete device; | ||||
| TaskScheduler::exit(); | TaskScheduler::exit(); | ||||
| } | } | ||||
| void Session::start() | void Session::start() | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Lines | RenderWork Session::run_update_for_next_iteration() | ||||
| render_scheduler_.set_time_limit(params.time_limit); | render_scheduler_.set_time_limit(params.time_limit); | ||||
| while (have_tiles) { | while (have_tiles) { | ||||
| render_work = render_scheduler_.get_render_work(); | render_work = render_scheduler_.get_render_work(); | ||||
| if (render_work) { | if (render_work) { | ||||
| break; | break; | ||||
| } | } | ||||
| progress.add_finished_tile(false); | |||||
| have_tiles = tile_manager_.next(); | have_tiles = tile_manager_.next(); | ||||
| if (have_tiles) { | if (have_tiles) { | ||||
| render_scheduler_.reset_for_next_tile(); | render_scheduler_.reset_for_next_tile(); | ||||
| switched_to_new_tile = true; | switched_to_new_tile = true; | ||||
| } | } | ||||
| } | } | ||||
| if (render_work) { | if (render_work) { | ||||
| ▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | bool Session::run_wait_for_work(const RenderWork &render_work) | ||||
| return no_work; | return no_work; | ||||
| } | } | ||||
| void Session::draw() | void Session::draw() | ||||
| { | { | ||||
| path_trace_->draw(); | path_trace_->draw(); | ||||
| } | } | ||||
| int2 Session::get_effective_tile_size() const | |||||
| { | |||||
| if (!params.use_auto_tile) { | |||||
| 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. */ | |||||
| return make_int2(params.tile_size, params.tile_size); | |||||
| } | |||||
| void Session::do_delayed_reset() | void Session::do_delayed_reset() | ||||
| { | { | ||||
| if (!delayed_reset_.do_reset) { | if (!delayed_reset_.do_reset) { | ||||
| return; | return; | ||||
| } | } | ||||
| delayed_reset_.do_reset = false; | delayed_reset_.do_reset = false; | ||||
| scene->film->update_passes(scene); | scene->film->update_passes(scene); | ||||
| buffer_params_ = delayed_reset_.params; | buffer_params_ = delayed_reset_.params; | ||||
| buffer_params_.update_passes(scene->passes); | buffer_params_.update_passes(scene->passes); | ||||
| render_scheduler_.reset(buffer_params_, delayed_reset_.samples); | render_scheduler_.reset(buffer_params_, delayed_reset_.samples); | ||||
| /* TODO(sergey): Use real big tile size. */ | const int2 tile_size = get_effective_tile_size(); | ||||
| tile_manager_.reset(buffer_params_, make_int2(buffer_params_.width, buffer_params_.height)); | tile_manager_.reset(buffer_params_, scene->passes, tile_size); | ||||
| progress.reset_sample(); | progress.reset_sample(); | ||||
| /* TODO(sergey): Progress report needs to be worked on. */ | /* TODO(sergey): Progress report needs to be worked on. */ | ||||
| #if 0 | #if 0 | ||||
| bool show_progress = params.background || tile_manager_.get_num_effective_samples() != INT_MAX; | bool show_progress = params.background || tile_manager_.get_num_effective_samples() != INT_MAX; | ||||
| progress.set_total_pixel_samples(show_progress ? tile_manager_.state.total_pixel_samples : 0); | progress.set_total_pixel_samples(show_progress ? tile_manager_.state.total_pixel_samples : 0); | ||||
| #endif | #endif | ||||
| ▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | bool Session::update_scene(int width, int height) | ||||
| if (scene->update(progress)) { | if (scene->update(progress)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | 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) | void Session::update_status_time(bool show_pause, bool show_done) | ||||
| { | { | ||||
| #if 0 | string status, substatus; | ||||
| int progressive_sample = tile_manager_.state.sample; | |||||
| int num_samples = tile_manager_.get_num_effective_samples(); | |||||
| int tile = progress.get_rendered_tiles(); | const int current_tile = progress.get_rendered_tiles(); | ||||
| int num_tiles = tile_manager_.state.num_tiles; | const int num_tiles = tile_manager_.get_num_tiles(); | ||||
| /* update status */ | const int current_sample = progress.get_current_sample(); | ||||
| string status, substatus; | const int num_samples = render_scheduler_.get_num_samples(); | ||||
| if (!params.progressive) { | /* TIle. */ | ||||
| const bool is_cpu = params.device.type == DEVICE_CPU; | if (tile_manager_.has_multiple_tiles()) { | ||||
| const bool rendering_finished = (tile == num_tiles); | substatus = status_append(substatus, | ||||
| const bool is_last_tile = (tile + 1) == num_tiles; | string_printf("Rendered %d/%d Tiles", current_tile, num_tiles)); | ||||
| substatus = string_printf("Rendered %d/%d Tiles", tile, num_tiles); | |||||
| if (!rendering_finished && (device->show_samples() || (is_cpu && is_last_tile))) { | |||||
| /* Some devices automatically support showing the sample number: | |||||
| * - CUDADevice | |||||
| * - CPUDevice when using one thread | |||||
| * For these devices, the current sample is always shown. | |||||
| * | |||||
| * The other option is when the last tile is currently being rendered by the CPU. | |||||
| */ | |||||
| substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples); | |||||
| } | |||||
| if (params.denoising.use && params.denoising.type != DENOISER_OPENIMAGEDENOISE) { | |||||
| substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles()); | |||||
| } | |||||
| } | } | ||||
| else if (tile_manager_.num_samples == Integrator::MAX_SAMPLES) | |||||
| substatus = string_printf("Path Tracing Sample %d", progressive_sample + 1); | |||||
| else | |||||
| substatus = string_printf("Path Tracing Sample %d/%d", progressive_sample + 1, num_samples); | |||||
| if (show_pause) { | /* Sample. */ | ||||
| status = "Rendering Paused"; | if (num_samples == Integrator::MAX_SAMPLES) { | ||||
| } | substatus = status_append(substatus, string_printf("Sample %d", current_sample)); | ||||
| else if (show_done) { | |||||
| status = "Rendering Done"; | |||||
| progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */ | |||||
| } | } | ||||
| else { | else { | ||||
| status = substatus; | substatus = status_append(substatus, | ||||
| substatus.clear(); | string_printf("Sample %d/%d", current_sample, num_samples)); | ||||
| } | } | ||||
| #else | |||||
| string status, substatus; | |||||
| /* TODO(sergey): Take number of big tiles into account. */ | |||||
| /* TODO(sergey): Take sample range into account. */ | |||||
| substatus += string_printf("Sample %d/%d", progress.get_current_sample(), params.samples); | /* TODO(sergey): Denoising status from the path trace. */ | ||||
| if (show_pause) { | if (show_pause) { | ||||
| status = "Rendering Paused"; | status = "Rendering Paused"; | ||||
| } | } | ||||
| else if (show_done) { | else if (show_done) { | ||||
| status = "Rendering Done"; | status = "Rendering Done"; | ||||
| progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */ | progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */ | ||||
| } | } | ||||
| else { | else { | ||||
| status = substatus; | status = substatus; | ||||
| substatus.clear(); | substatus.clear(); | ||||
| } | } | ||||
| #endif | |||||
| progress.set_status(status, substatus); | progress.set_status(status, substatus); | ||||
| } | } | ||||
| void Session::device_free() | void Session::device_free() | ||||
| { | { | ||||
| scene->device_free(); | scene->device_free(); | ||||
| #if 0 | |||||
| tile_manager_.device_free(); | |||||
| #endif | |||||
| /* used from background render only, so no need to | /* used from background render only, so no need to | ||||
| * re-create render/display buffers here | * re-create render/display buffers here | ||||
| */ | */ | ||||
| } | } | ||||
| void Session::collect_statistics(RenderStats *render_stats) | void Session::collect_statistics(RenderStats *render_stats) | ||||
| { | { | ||||
| scene->collect_statistics(render_stats); | scene->collect_statistics(render_stats); | ||||
| if (params.use_profiling && (params.device.type == DEVICE_CPU)) { | if (params.use_profiling && (params.device.type == DEVICE_CPU)) { | ||||
| render_stats->collect_profiling(scene, profiler); | render_stats->collect_profiling(scene, profiler); | ||||
| } | } | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- | /* -------------------------------------------------------------------- | ||||
| * Tile and tile pixels aceess. | * Tile and tile pixels aceess. | ||||
| */ | */ | ||||
| int2 Session::get_render_tile_size() const | int2 Session::get_render_tile_size() const | ||||
| { | { | ||||
| const Tile &tile = tile_manager_.get_current_tile(); | return path_trace_->get_render_tile_size(); | ||||
| return make_int2(tile.width, tile.height); | |||||
| } | } | ||||
| int2 Session::get_render_tile_offset() const | int2 Session::get_render_tile_offset() const | ||||
| { | { | ||||
| const Tile &tile = tile_manager_.get_current_tile(); | return path_trace_->get_render_tile_offset(); | ||||
| return make_int2(tile.x, tile.y); | |||||
| } | } | ||||
| bool Session::copy_render_tile_from_device() | bool Session::copy_render_tile_from_device() | ||||
| { | { | ||||
| return path_trace_->copy_render_tile_from_device(); | return path_trace_->copy_render_tile_from_device(); | ||||
| } | } | ||||
| bool Session::get_render_tile_pixels(const string &pass_name, int num_components, float *pixels) | bool Session::get_render_tile_pixels(const string &pass_name, int num_components, float *pixels) | ||||
| Show All 10 Lines | if (pass == nullptr) { | ||||
| /* Happens when denoised result pass is requested but is never written by the kernel. */ | /* Happens when denoised result pass is requested but is never written by the kernel. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| pass = scene->film->get_actual_display_pass(scene, pass); | pass = scene->film->get_actual_display_pass(scene, pass); | ||||
| const float exposure = scene->film->get_exposure(); | const float exposure = scene->film->get_exposure(); | ||||
| const int num_samples = render_scheduler_.get_num_rendered_samples(); | const int num_samples = path_trace_->get_num_render_tile_samples(); | ||||
| const PassAccessor::PassAccessInfo pass_access_info( | const PassAccessor::PassAccessInfo pass_access_info( | ||||
| *pass, *scene->film, *scene->background, scene->passes); | *pass, *scene->film, *scene->background, scene->passes); | ||||
| const PassAccessorCPU pass_accessor(pass_access_info, exposure, num_samples); | const PassAccessorCPU pass_accessor(pass_access_info, exposure, num_samples); | ||||
| const PassAccessor::Destination destination(pixels, num_components); | const PassAccessor::Destination destination(pixels, num_components); | ||||
| return path_trace_->get_render_tile_pixels(pass_accessor, destination); | return path_trace_->get_render_tile_pixels(pass_accessor, destination); | ||||
| } | } | ||||
| Show All 23 Lines | |||||