util_progress.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef __UTIL_PROGRESS_H__
  17. #define __UTIL_PROGRESS_H__
  18. /* Progress
  19. *
  20. * Simple class to communicate progress status messages, timing information,
  21. * update notifications from a job running in another thread. All methods
  22. * except for the constructor/destructor are thread safe. */
  23. #include "util/util_function.h"
  24. #include "util/util_string.h"
  25. #include "util/util_time.h"
  26. #include "util/util_thread.h"
  27. CCL_NAMESPACE_BEGIN
  28. class Progress {
  29. public:
  30. Progress()
  31. {
  32. pixel_samples = 0;
  33. total_pixel_samples = 0;
  34. current_tile_sample = 0;
  35. rendered_tiles = 0;
  36. denoised_tiles = 0;
  37. start_time = time_dt();
  38. render_start_time = time_dt();
  39. end_time = 0.0;
  40. status = "Initializing";
  41. substatus = "";
  42. sync_status = "";
  43. sync_substatus = "";
  44. kernel_status = "";
  45. update_cb = function_null;
  46. cancel = false;
  47. cancel_message = "";
  48. error = false;
  49. error_message = "";
  50. cancel_cb = function_null;
  51. }
  52. Progress(Progress &progress)
  53. {
  54. *this = progress;
  55. }
  56. Progress &operator=(Progress &progress)
  57. {
  58. thread_scoped_lock lock(progress.progress_mutex);
  59. progress.get_status(status, substatus);
  60. pixel_samples = progress.pixel_samples;
  61. total_pixel_samples = progress.total_pixel_samples;
  62. current_tile_sample = progress.get_current_sample();
  63. return *this;
  64. }
  65. void reset()
  66. {
  67. pixel_samples = 0;
  68. total_pixel_samples = 0;
  69. current_tile_sample = 0;
  70. rendered_tiles = 0;
  71. denoised_tiles = 0;
  72. start_time = time_dt();
  73. render_start_time = time_dt();
  74. end_time = 0.0;
  75. status = "Initializing";
  76. substatus = "";
  77. sync_status = "";
  78. sync_substatus = "";
  79. kernel_status = "";
  80. cancel = false;
  81. cancel_message = "";
  82. error = false;
  83. error_message = "";
  84. }
  85. /* cancel */
  86. void set_cancel(const string &cancel_message_)
  87. {
  88. thread_scoped_lock lock(progress_mutex);
  89. cancel_message = cancel_message_;
  90. cancel = true;
  91. }
  92. bool get_cancel()
  93. {
  94. if (!cancel && cancel_cb)
  95. cancel_cb();
  96. return cancel;
  97. }
  98. string get_cancel_message()
  99. {
  100. thread_scoped_lock lock(progress_mutex);
  101. return cancel_message;
  102. }
  103. void set_cancel_callback(function<void()> function)
  104. {
  105. cancel_cb = function;
  106. }
  107. /* error */
  108. void set_error(const string &error_message_)
  109. {
  110. thread_scoped_lock lock(progress_mutex);
  111. error_message = error_message_;
  112. error = true;
  113. /* If error happens we also stop rendering. */
  114. cancel_message = error_message_;
  115. cancel = true;
  116. }
  117. bool get_error()
  118. {
  119. return error;
  120. }
  121. string get_error_message()
  122. {
  123. thread_scoped_lock lock(progress_mutex);
  124. return error_message;
  125. }
  126. /* tile and timing information */
  127. void set_start_time()
  128. {
  129. thread_scoped_lock lock(progress_mutex);
  130. start_time = time_dt();
  131. end_time = 0.0;
  132. }
  133. void set_render_start_time()
  134. {
  135. thread_scoped_lock lock(progress_mutex);
  136. render_start_time = time_dt();
  137. }
  138. void add_skip_time(const scoped_timer &start_timer, bool only_render)
  139. {
  140. double skip_time = time_dt() - start_timer.get_start();
  141. render_start_time += skip_time;
  142. if (!only_render) {
  143. start_time += skip_time;
  144. }
  145. }
  146. void get_time(double &total_time_, double &render_time_)
  147. {
  148. thread_scoped_lock lock(progress_mutex);
  149. double time = (end_time > 0) ? end_time : time_dt();
  150. total_time_ = time - start_time;
  151. render_time_ = time - render_start_time;
  152. }
  153. void set_end_time()
  154. {
  155. end_time = time_dt();
  156. }
  157. void reset_sample()
  158. {
  159. thread_scoped_lock lock(progress_mutex);
  160. pixel_samples = 0;
  161. current_tile_sample = 0;
  162. rendered_tiles = 0;
  163. denoised_tiles = 0;
  164. }
  165. void set_total_pixel_samples(uint64_t total_pixel_samples_)
  166. {
  167. thread_scoped_lock lock(progress_mutex);
  168. total_pixel_samples = total_pixel_samples_;
  169. }
  170. float get_progress()
  171. {
  172. if (total_pixel_samples > 0) {
  173. return ((float)pixel_samples) / total_pixel_samples;
  174. }
  175. return 0.0f;
  176. }
  177. void add_samples(uint64_t pixel_samples_, int tile_sample)
  178. {
  179. thread_scoped_lock lock(progress_mutex);
  180. pixel_samples += pixel_samples_;
  181. current_tile_sample = tile_sample;
  182. }
  183. void add_samples_update(uint64_t pixel_samples_, int tile_sample)
  184. {
  185. add_samples(pixel_samples_, tile_sample);
  186. set_update();
  187. }
  188. void add_finished_tile(bool denoised)
  189. {
  190. thread_scoped_lock lock(progress_mutex);
  191. if (denoised) {
  192. denoised_tiles++;
  193. }
  194. else {
  195. rendered_tiles++;
  196. }
  197. }
  198. int get_current_sample()
  199. {
  200. thread_scoped_lock lock(progress_mutex);
  201. /* Note that the value here always belongs to the last tile that updated,
  202. * so it's only useful if there is only one active tile. */
  203. return current_tile_sample;
  204. }
  205. int get_rendered_tiles()
  206. {
  207. thread_scoped_lock lock(progress_mutex);
  208. return rendered_tiles;
  209. }
  210. int get_denoised_tiles()
  211. {
  212. thread_scoped_lock lock(progress_mutex);
  213. return denoised_tiles;
  214. }
  215. /* status messages */
  216. void set_status(const string &status_, const string &substatus_ = "")
  217. {
  218. {
  219. thread_scoped_lock lock(progress_mutex);
  220. status = status_;
  221. substatus = substatus_;
  222. }
  223. set_update();
  224. }
  225. void set_substatus(const string &substatus_)
  226. {
  227. {
  228. thread_scoped_lock lock(progress_mutex);
  229. substatus = substatus_;
  230. }
  231. set_update();
  232. }
  233. void set_sync_status(const string &status_, const string &substatus_ = "")
  234. {
  235. {
  236. thread_scoped_lock lock(progress_mutex);
  237. sync_status = status_;
  238. sync_substatus = substatus_;
  239. }
  240. set_update();
  241. }
  242. void set_sync_substatus(const string &substatus_)
  243. {
  244. {
  245. thread_scoped_lock lock(progress_mutex);
  246. sync_substatus = substatus_;
  247. }
  248. set_update();
  249. }
  250. void get_status(string &status_, string &substatus_)
  251. {
  252. thread_scoped_lock lock(progress_mutex);
  253. if (sync_status != "") {
  254. status_ = sync_status;
  255. substatus_ = sync_substatus;
  256. }
  257. else {
  258. status_ = status;
  259. substatus_ = substatus;
  260. }
  261. }
  262. /* kernel status */
  263. void set_kernel_status(const string &kernel_status_)
  264. {
  265. {
  266. thread_scoped_lock lock(progress_mutex);
  267. kernel_status = kernel_status_;
  268. }
  269. set_update();
  270. }
  271. void get_kernel_status(string &kernel_status_)
  272. {
  273. thread_scoped_lock lock(progress_mutex);
  274. kernel_status_ = kernel_status;
  275. }
  276. /* callback */
  277. void set_update()
  278. {
  279. if (update_cb) {
  280. thread_scoped_lock lock(update_mutex);
  281. update_cb();
  282. }
  283. }
  284. void set_update_callback(function<void()> function)
  285. {
  286. update_cb = function;
  287. }
  288. protected:
  289. thread_mutex progress_mutex;
  290. thread_mutex update_mutex;
  291. function<void()> update_cb;
  292. function<void()> cancel_cb;
  293. /* pixel_samples counts how many samples have been rendered over all pixel, not just per pixel.
  294. * This makes the progress estimate more accurate when tiles with different sizes are used.
  295. *
  296. * total_pixel_samples is the total amount of pixel samples that will be rendered. */
  297. uint64_t pixel_samples, total_pixel_samples;
  298. /* Stores the current sample count of the last tile that called the update function.
  299. * It's used to display the sample count if only one tile is active. */
  300. int current_tile_sample;
  301. /* Stores the number of tiles that's already finished.
  302. * Used to determine whether all but the last tile are finished rendering,
  303. * in which case the current_tile_sample is displayed. */
  304. int rendered_tiles, denoised_tiles;
  305. double start_time, render_start_time;
  306. /* End time written when render is done, so it doesn't keep increasing on redraws. */
  307. double end_time;
  308. string status;
  309. string substatus;
  310. string sync_status;
  311. string sync_substatus;
  312. string kernel_status;
  313. volatile bool cancel;
  314. string cancel_message;
  315. volatile bool error;
  316. string error_message;
  317. };
  318. CCL_NAMESPACE_END
  319. #endif /* __UTIL_PROGRESS_H__ */