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:
authorLukas Stockner <lukas.stockner@freenet.de>2016-11-26 06:22:34 +0300
committerLukas Stockner <lukas.stockner@freenet.de>2016-12-03 07:02:21 +0300
commita2ebc5268f2b98ee7335e0054c177c849a45cfba (patch)
treef1c08ab691cc93b08df0a387b037d1e0a45e9a53 /intern/cycles/render
parent35d490b3f13c75e9a62cb30f3842ed38a27f6dbc (diff)
Cycles: Refactor Progress system to provide better estimates
The Progress system in Cycles had two limitations so far: - It just counted tiles, but ignored their size. For example, when rendering a 600x500 image with 512x512 tiles, the right 88x500 tile would count for 50% of the progress, although it only covers 15% of the image. - Scene update time was incorrectly counted as rendering time - therefore, the remaining time started very long and gradually decreased. This patch fixes both problems: First of all, the Progress now has a function to ignore time spans, and that is used to ignore scene update time. The larger change is the tile size: Instead of counting samples per tile, so that the final value is num_samples*num_tiles, the code now counts every sample for every pixel, so that the final value is num_samples*num_pixels. Along with that, some unused variables were removed from the Progress and Session classes. Reviewers: brecht, sergey, #cycles Subscribers: brecht, candreacchio, sergey Differential Revision: https://developer.blender.org/D2214
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/bake.cpp20
-rw-r--r--intern/cycles/render/bake.h3
-rw-r--r--intern/cycles/render/session.cpp110
-rw-r--r--intern/cycles/render/session.h9
-rw-r--r--intern/cycles/render/tile.cpp37
-rw-r--r--intern/cycles/render/tile.h6
6 files changed, 79 insertions, 106 deletions
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 13310a61761..d9a297002c6 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -135,20 +135,16 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
{
size_t num_pixels = bake_data->size();
- progress.reset_sample();
- this->num_parts = 0;
+ int num_samples = is_aa_pass(shader_type)? scene->integrator->aa_samples : 1;
- /* calculate the total parts for the progress bar */
+ /* calculate the total pixel samples for the progress bar */
+ total_pixel_samples = 0;
for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
-
- DeviceTask task(DeviceTask::SHADER);
- task.shader_w = shader_size;
-
- this->num_parts += device->get_split_task_count(task);
+ total_pixel_samples += shader_size * num_samples;
}
-
- this->num_samples = is_aa_pass(shader_type)? scene->integrator->aa_samples : 1;
+ progress.reset_sample();
+ progress.set_total_pixel_samples(total_pixel_samples);
for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
@@ -187,9 +183,9 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
task.shader_x = 0;
task.offset = shader_offset;
task.shader_w = d_output.size();
- task.num_samples = this->num_samples;
+ task.num_samples = num_samples;
task.get_cancel = function_bind(&Progress::get_cancel, &progress);
- task.update_progress_sample = function_bind(&Progress::increment_sample_update, &progress);
+ task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
device->task_add(task);
device->task_wait();
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index 8377e387197..25f5eb3c897 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -73,8 +73,7 @@ public:
bool need_update;
- int num_samples;
- int num_parts;
+ int total_pixel_samples;
private:
BakeData *m_bake_data;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 9d8c9fed7af..8e902243211 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -67,10 +67,7 @@ Session::Session(const SessionParams& params_)
session_thread = NULL;
scene = NULL;
- start_time = 0.0;
reset_time = 0.0;
- preview_time = 0.0;
- paused_time = 0.0;
last_update_time = 0.0;
delayed_reset.do_reset = false;
@@ -201,12 +198,10 @@ void Session::run_gpu()
{
bool tiles_written = false;
- start_time = time_dt();
reset_time = time_dt();
- paused_time = 0.0;
last_update_time = time_dt();
- progress.set_render_start_time(start_time + paused_time);
+ progress.set_render_start_time();
while(!progress.get_cancel()) {
/* advance to next tile */
@@ -233,13 +228,9 @@ void Session::run_gpu()
update_status_time(pause, no_tiles);
while(1) {
- double pause_start = time_dt();
+ scoped_timer pause_timer;
pause_cond.wait(pause_lock);
- paused_time += time_dt() - pause_start;
-
- if(!params.background)
- progress.set_start_time(start_time + paused_time);
- progress.set_render_start_time(start_time + paused_time);
+ progress.add_skip_time(pause_timer, params.background);
update_status_time(pause, no_tiles);
progress.set_update();
@@ -255,7 +246,9 @@ void Session::run_gpu()
if(!no_tiles) {
/* update scene */
+ scoped_timer update_timer;
update_scene();
+ progress.add_skip_time(update_timer, params.background);
if(!device->error_message().empty())
progress.set_error(device->error_message());
@@ -523,13 +516,9 @@ void Session::run_cpu()
update_status_time(pause, no_tiles);
while(1) {
- double pause_start = time_dt();
+ scoped_timer pause_timer;
pause_cond.wait(pause_lock);
- paused_time += time_dt() - pause_start;
-
- if(!params.background)
- progress.set_start_time(start_time + paused_time);
- progress.set_render_start_time(start_time + paused_time);
+ progress.add_skip_time(pause_timer, params.background);
update_status_time(pause, no_tiles);
progress.set_update();
@@ -550,7 +539,9 @@ void Session::run_cpu()
thread_scoped_lock buffers_lock(buffers_mutex);
/* update scene */
+ scoped_timer update_timer;
update_scene();
+ progress.add_skip_time(update_timer, params.background);
if(!device->error_message().empty())
progress.set_error(device->error_message());
@@ -718,14 +709,14 @@ void Session::reset_(BufferParams& buffer_params, int samples)
}
tile_manager.reset(buffer_params, samples);
+ progress.reset_sample();
- start_time = time_dt();
- preview_time = 0.0;
- paused_time = 0.0;
+ 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);
if(!params.background)
- progress.set_start_time(start_time);
- progress.set_render_start_time(start_time);
+ progress.set_start_time();
+ progress.set_render_start_time();
}
void Session::reset(BufferParams& buffer_params, int samples)
@@ -827,61 +818,40 @@ void Session::update_scene()
void Session::update_status_time(bool show_pause, bool show_done)
{
- int sample = tile_manager.state.sample;
- int resolution = tile_manager.state.resolution_divider;
- int num_tiles = tile_manager.state.num_tiles;
+ int progressive_sample = tile_manager.state.sample;
+ int num_samples = tile_manager.get_num_effective_samples();
+
int tile = tile_manager.state.num_rendered_tiles;
+ int num_tiles = tile_manager.state.num_tiles;
/* update status */
string status, substatus;
if(!params.progressive) {
- const int progress_sample = progress.get_sample(),
- num_samples = tile_manager.get_num_effective_samples();
- const bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL;
- const bool is_multidevice = params.device.multi_devices.size() > 1;
const bool is_cpu = params.device.type == DEVICE_CPU;
- const bool is_last_tile = (num_samples * num_tiles - progress_sample) < num_samples;
+ const bool is_last_tile = (progress.get_finished_tiles() + 1) == num_tiles;
substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles);
- if((is_gpu && !is_multidevice && !device->info.use_split_kernel) ||
- (is_cpu && (num_tiles == 1 || is_last_tile)))
+ if(device->show_samples() || (is_cpu && is_last_tile))
{
- /* When using split-kernel (OpenCL) each thread in a tile will be working on a different
- * sample. Can't display sample number when device uses split-kernel
+ /* Some devices automatically support showing the sample number:
+ * - CUDADevice
+ * - OpenCLDevice when using the megakernel (the split kernel renders multiple samples at the same time, so the current sample isn't really defined)
+ * - 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.
*/
-
- /* when rendering on GPU multithreading happens within single tile, as in
- * tiles are handling sequentially and in this case we could display
- * currently rendering sample number
- * this helps a lot from feedback point of view.
- * also display the info on CPU, when using 1 tile only
- */
-
- int status_sample = progress_sample;
- if(tile > 1) {
- /* sample counter is global for all tiles, subtract samples
- * from already finished tiles to get sample counter for
- * current tile only
- */
- if(is_cpu && is_last_tile && num_tiles > 1) {
- status_sample = num_samples - (num_samples * num_tiles - progress_sample);
- }
- else {
- status_sample -= (tile - 1) * num_samples;
- }
- }
-
- substatus += string_printf(", Sample %d/%d", status_sample, num_samples);
+ substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
}
}
else if(tile_manager.num_samples == INT_MAX)
- substatus = string_printf("Path Tracing Sample %d", sample+1);
+ substatus = string_printf("Path Tracing Sample %d", progressive_sample+1);
else
substatus = string_printf("Path Tracing Sample %d/%d",
- sample+1,
- tile_manager.get_num_effective_samples());
+ progressive_sample+1,
+ num_samples);
if(show_pause) {
status = "Paused";
@@ -895,22 +865,6 @@ void Session::update_status_time(bool show_pause, bool show_done)
}
progress.set_status(status, substatus);
-
- /* update timing */
- if(preview_time == 0.0 && resolution == 1)
- preview_time = time_dt();
-
- double tile_time = (tile == 0 || sample == 0)? 0.0: (time_dt() - preview_time - paused_time) / sample;
-
- /* negative can happen when we pause a bit before rendering, can discard that */
- if(preview_time < 0.0) preview_time = 0.0;
-
- progress.set_tile(tile, tile_time);
-}
-
-void Session::update_progress_sample()
-{
- progress.increment_sample();
}
void Session::path_trace()
@@ -922,7 +876,7 @@ void Session::path_trace()
task.release_tile = function_bind(&Session::release_tile, this, _1);
task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
- task.update_progress_sample = function_bind(&Session::update_progress_sample, this);
+ task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
task.need_finish_queue = params.progressive_refine;
task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
task.requested_tile_size = params.tile_size;
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 1db4692e171..c7ff1446171 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -145,6 +145,10 @@ public:
void device_free();
+ /* Returns the rendering progress or 0 if no progress can be determined
+ * (for example, when rendering with unlimited samples). */
+ float get_progress();
+
protected:
struct DelayedReset {
thread_mutex mutex;
@@ -173,8 +177,6 @@ protected:
void update_tile_sample(RenderTile& tile);
void release_tile(RenderTile& tile);
- void update_progress_sample();
-
bool device_use_gl;
thread *session_thread;
@@ -194,10 +196,7 @@ protected:
bool kernels_loaded;
- double start_time;
double reset_time;
- double preview_time;
- double paused_time;
/* progressive refine */
double last_update_time;
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index 3a6dfea11a7..e59d0c843a3 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -108,36 +108,57 @@ TileManager::~TileManager()
{
}
-void TileManager::reset(BufferParams& params_, int num_samples_)
+static int get_divider(int w, int h, int start_resolution)
{
- params = params_;
-
int divider = 1;
- int w = params.width, h = params.height;
-
if(start_resolution != INT_MAX) {
while(w*h > start_resolution*start_resolution) {
w = max(1, w/2);
h = max(1, h/2);
- divider *= 2;
+ divider <<= 1;
}
}
+ return divider;
+}
- num_samples = num_samples_;
+void TileManager::reset(BufferParams& params_, int num_samples_)
+{
+ params = params_;
+
+ set_samples(num_samples_);
state.buffer = BufferParams();
state.sample = range_start_sample - 1;
state.num_tiles = 0;
state.num_rendered_tiles = 0;
state.num_samples = 0;
- state.resolution_divider = divider;
+ state.resolution_divider = get_divider(params.width, params.height, start_resolution);
state.tiles.clear();
}
void TileManager::set_samples(int num_samples_)
{
num_samples = num_samples_;
+
+ /* No real progress indication is possible when using unlimited samples. */
+ if(num_samples == INT_MAX) {
+ state.total_pixel_samples = 0;
+ }
+ else {
+ uint64_t pixel_samples = 0;
+ /* While rendering in the viewport, the initial preview resolution is increased to the native resolution
+ * before the actual rendering begins. Therefore, additional pixel samples will be rendered. */
+ int divider = get_divider(params.width, params.height, start_resolution) / 2;
+ while(divider > 1) {
+ int image_w = max(1, params.width/divider);
+ int image_h = max(1, params.height/divider);
+ pixel_samples += image_w * image_h;
+ divider >>= 1;
+ }
+
+ state.total_pixel_samples = pixel_samples + get_num_effective_samples() * params.width*params.height;
+ }
}
/* If sliced is false, splits image into tiles and assigns equal amount of tiles to every render device.
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index af1b1ed8b0f..5d92ebac355 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -64,6 +64,10 @@ public:
int resolution_divider;
int num_tiles;
int num_rendered_tiles;
+
+ /* Total samples over all pixels: Generally num_samples*num_pixels,
+ * but can be higher due to the initial resolution division for previews. */
+ uint64_t total_pixel_samples;
/* This vector contains a list of tiles for every logical device in the session.
* In each list, the tiles are sorted according to the tile order setting. */
vector<list<Tile> > tiles;
@@ -91,7 +95,7 @@ public:
/* Number to samples in the rendering range. */
int range_num_samples;
- /* get number of actual samples to render. */
+ /* Get number of actual samples to render. */
int get_num_effective_samples();
protected: