123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- /*
- * 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();
- end_time = 0.0;
- status = "Initializing";
- substatus = "";
- sync_status = "";
- sync_substatus = "";
- kernel_status = "";
- 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();
- end_time = 0.0;
- status = "Initializing";
- substatus = "";
- sync_status = "";
- sync_substatus = "";
- kernel_status = "";
- 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()> 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();
- end_time = 0.0;
- }
- 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);
- double time = (end_time > 0) ? end_time : time_dt();
- total_time_ = time - start_time;
- render_time_ = time - render_start_time;
- }
- void set_end_time()
- {
- end_time = time_dt();
- }
- 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()
- {
- thread_scoped_lock lock(progress_mutex);
- /* 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()
- {
- thread_scoped_lock lock(progress_mutex);
- return rendered_tiles;
- }
- int get_denoised_tiles()
- {
- thread_scoped_lock lock(progress_mutex);
- 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;
- }
- }
- /* kernel status */
- void set_kernel_status(const string &kernel_status_)
- {
- {
- thread_scoped_lock lock(progress_mutex);
- kernel_status = kernel_status_;
- }
- set_update();
- }
- void get_kernel_status(string &kernel_status_)
- {
- thread_scoped_lock lock(progress_mutex);
- kernel_status_ = kernel_status;
- }
- /* callback */
- void set_update()
- {
- if (update_cb) {
- thread_scoped_lock lock(update_mutex);
- update_cb();
- }
- }
- void set_update_callback(function<void()> function)
- {
- update_cb = function;
- }
- protected:
- thread_mutex progress_mutex;
- thread_mutex update_mutex;
- function<void()> update_cb;
- function<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;
- /* End time written when render is done, so it doesn't keep increasing on redraws. */
- double end_time;
- string status;
- string substatus;
- string sync_status;
- string sync_substatus;
- string kernel_status;
- volatile bool cancel;
- string cancel_message;
- volatile bool error;
- string error_message;
- };
- CCL_NAMESPACE_END
- #endif /* __UTIL_PROGRESS_H__ */
|