forked from bartvdbraak/blender
a21277b996
Now rendered and denoised tiles are counted and displayed separately.
355 lines
7.2 KiB
C++
355 lines
7.2 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef __UTIL_PROGRESS_H__
|
|
#define __UTIL_PROGRESS_H__
|
|
|
|
/* Progress
|
|
*
|
|
* Simple class to communicate progress status messages, timing information,
|
|
* update notifications from a job running in another thread. All methods
|
|
* except for the constructor/destructor are thread safe. */
|
|
|
|
#include "util/util_function.h"
|
|
#include "util/util_string.h"
|
|
#include "util/util_time.h"
|
|
#include "util/util_thread.h"
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
class Progress {
|
|
public:
|
|
Progress()
|
|
{
|
|
pixel_samples = 0;
|
|
total_pixel_samples = 0;
|
|
current_tile_sample = 0;
|
|
rendered_tiles = 0;
|
|
denoised_tiles = 0;
|
|
start_time = time_dt();
|
|
render_start_time = time_dt();
|
|
status = "Initializing";
|
|
substatus = "";
|
|
sync_status = "";
|
|
sync_substatus = "";
|
|
update_cb = function_null;
|
|
cancel = false;
|
|
cancel_message = "";
|
|
error = false;
|
|
error_message = "";
|
|
cancel_cb = function_null;
|
|
}
|
|
|
|
Progress(Progress& progress)
|
|
{
|
|
*this = progress;
|
|
}
|
|
|
|
Progress& operator=(Progress& progress)
|
|
{
|
|
thread_scoped_lock lock(progress.progress_mutex);
|
|
|
|
progress.get_status(status, substatus);
|
|
|
|
pixel_samples = progress.pixel_samples;
|
|
total_pixel_samples = progress.total_pixel_samples;
|
|
current_tile_sample = progress.get_current_sample();
|
|
|
|
return *this;
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
pixel_samples = 0;
|
|
total_pixel_samples = 0;
|
|
current_tile_sample = 0;
|
|
rendered_tiles = 0;
|
|
denoised_tiles = 0;
|
|
start_time = time_dt();
|
|
render_start_time = time_dt();
|
|
status = "Initializing";
|
|
substatus = "";
|
|
sync_status = "";
|
|
sync_substatus = "";
|
|
cancel = false;
|
|
cancel_message = "";
|
|
error = false;
|
|
error_message = "";
|
|
}
|
|
|
|
/* cancel */
|
|
void set_cancel(const string& cancel_message_)
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
cancel_message = cancel_message_;
|
|
cancel = true;
|
|
}
|
|
|
|
bool get_cancel()
|
|
{
|
|
if(!cancel && cancel_cb)
|
|
cancel_cb();
|
|
|
|
return cancel;
|
|
}
|
|
|
|
string get_cancel_message()
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
return cancel_message;
|
|
}
|
|
|
|
void set_cancel_callback(function<void(void)> function)
|
|
{
|
|
cancel_cb = function;
|
|
}
|
|
|
|
/* error */
|
|
void set_error(const string& error_message_)
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
error_message = error_message_;
|
|
error = true;
|
|
/* If error happens we also stop rendering. */
|
|
cancel_message = error_message_;
|
|
cancel = true;
|
|
}
|
|
|
|
bool get_error()
|
|
{
|
|
return error;
|
|
}
|
|
|
|
string get_error_message()
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
return error_message;
|
|
}
|
|
|
|
/* tile and timing information */
|
|
|
|
void set_start_time()
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
start_time = time_dt();
|
|
}
|
|
|
|
void set_render_start_time()
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
render_start_time = time_dt();
|
|
}
|
|
|
|
void add_skip_time(const scoped_timer &start_timer, bool only_render)
|
|
{
|
|
double skip_time = time_dt() - start_timer.get_start();
|
|
|
|
render_start_time += skip_time;
|
|
if(!only_render) {
|
|
start_time += skip_time;
|
|
}
|
|
}
|
|
|
|
void get_time(double& total_time_, double& render_time_)
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
total_time_ = time_dt() - start_time;
|
|
render_time_ = time_dt() - render_start_time;
|
|
}
|
|
|
|
void reset_sample()
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
pixel_samples = 0;
|
|
current_tile_sample = 0;
|
|
rendered_tiles = 0;
|
|
denoised_tiles = 0;
|
|
}
|
|
|
|
void set_total_pixel_samples(uint64_t total_pixel_samples_)
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
total_pixel_samples = total_pixel_samples_;
|
|
}
|
|
|
|
float get_progress()
|
|
{
|
|
if(total_pixel_samples > 0) {
|
|
return ((float) pixel_samples) / total_pixel_samples;
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void add_samples(uint64_t pixel_samples_, int tile_sample)
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
pixel_samples += pixel_samples_;
|
|
current_tile_sample = tile_sample;
|
|
}
|
|
|
|
void add_samples_update(uint64_t pixel_samples_, int tile_sample)
|
|
{
|
|
add_samples(pixel_samples_, tile_sample);
|
|
set_update();
|
|
}
|
|
|
|
void add_finished_tile(bool denoised)
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
if(denoised) {
|
|
denoised_tiles++;
|
|
}
|
|
else {
|
|
rendered_tiles++;
|
|
}
|
|
}
|
|
|
|
int get_current_sample()
|
|
{
|
|
/* Note that the value here always belongs to the last tile that updated,
|
|
* so it's only useful if there is only one active tile. */
|
|
return current_tile_sample;
|
|
}
|
|
|
|
int get_rendered_tiles()
|
|
{
|
|
return rendered_tiles;
|
|
}
|
|
|
|
int get_denoised_tiles()
|
|
{
|
|
return denoised_tiles;
|
|
}
|
|
|
|
/* status messages */
|
|
|
|
void set_status(const string& status_, const string& substatus_ = "")
|
|
{
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
status = status_;
|
|
substatus = substatus_;
|
|
}
|
|
|
|
set_update();
|
|
}
|
|
|
|
void set_substatus(const string& substatus_)
|
|
{
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
substatus = substatus_;
|
|
}
|
|
|
|
set_update();
|
|
}
|
|
|
|
void set_sync_status(const string& status_, const string& substatus_ = "")
|
|
{
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
sync_status = status_;
|
|
sync_substatus = substatus_;
|
|
}
|
|
|
|
set_update();
|
|
|
|
}
|
|
|
|
void set_sync_substatus(const string& substatus_)
|
|
{
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
sync_substatus = substatus_;
|
|
}
|
|
|
|
set_update();
|
|
}
|
|
|
|
void get_status(string& status_, string& substatus_)
|
|
{
|
|
thread_scoped_lock lock(progress_mutex);
|
|
|
|
if(sync_status != "") {
|
|
status_ = sync_status;
|
|
substatus_ = sync_substatus;
|
|
}
|
|
else {
|
|
status_ = status;
|
|
substatus_ = substatus;
|
|
}
|
|
}
|
|
|
|
/* callback */
|
|
|
|
void set_update()
|
|
{
|
|
if(update_cb) {
|
|
thread_scoped_lock lock(update_mutex);
|
|
update_cb();
|
|
}
|
|
}
|
|
|
|
void set_update_callback(function<void(void)> function)
|
|
{
|
|
update_cb = function;
|
|
}
|
|
|
|
protected:
|
|
thread_mutex progress_mutex;
|
|
thread_mutex update_mutex;
|
|
function<void(void)> update_cb;
|
|
function<void(void)> cancel_cb;
|
|
|
|
/* pixel_samples counts how many samples have been rendered over all pixel, not just per pixel.
|
|
* This makes the progress estimate more accurate when tiles with different sizes are used.
|
|
*
|
|
* total_pixel_samples is the total amount of pixel samples that will be rendered. */
|
|
uint64_t pixel_samples, total_pixel_samples;
|
|
/* Stores the current sample count of the last tile that called the update function.
|
|
* It's used to display the sample count if only one tile is active. */
|
|
int current_tile_sample;
|
|
/* Stores the number of tiles that's already finished.
|
|
* Used to determine whether all but the last tile are finished rendering, in which case the current_tile_sample is displayed. */
|
|
int rendered_tiles, denoised_tiles;
|
|
|
|
double start_time, render_start_time;
|
|
|
|
string status;
|
|
string substatus;
|
|
|
|
string sync_status;
|
|
string sync_substatus;
|
|
|
|
volatile bool cancel;
|
|
string cancel_message;
|
|
|
|
volatile bool error;
|
|
string error_message;
|
|
};
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
#endif /* __UTIL_PROGRESS_H__ */
|
|
|