Blender  V3.3
session/session.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include <limits.h>
5 #include <string.h>
6 
7 #include "device/cpu/device.h"
8 #include "device/device.h"
10 #include "integrator/path_trace.h"
11 #include "scene/background.h"
12 #include "scene/bake.h"
13 #include "scene/camera.h"
14 #include "scene/integrator.h"
15 #include "scene/light.h"
16 #include "scene/mesh.h"
17 #include "scene/object.h"
18 #include "scene/scene.h"
19 #include "scene/shader_graph.h"
20 #include "session/buffers.h"
21 #include "session/display_driver.h"
22 #include "session/output_driver.h"
23 #include "session/session.h"
24 
25 #include "util/foreach.h"
26 #include "util/function.h"
27 #include "util/log.h"
28 #include "util/math.h"
29 #include "util/task.h"
30 #include "util/time.h"
31 
33 
34 Session::Session(const SessionParams &params_, const SceneParams &scene_params)
35  : params(params_), render_scheduler_(tile_manager_, params)
36 {
38 
39  delayed_reset_.do_reset = false;
40 
41  pause_ = false;
42  new_work_added_ = false;
43 
45 
46  if (device->have_error()) {
48  }
49 
50  scene = new Scene(scene_params, device);
51 
52  /* Configure path tracer. */
53  path_trace_ = make_unique<PathTrace>(
55  path_trace_->set_progress(&progress);
56  path_trace_->progress_update_cb = [&]() { update_status_time(); };
57 
58  tile_manager_.full_buffer_written_cb = [&](string_view filename) {
60  return;
61  }
62  full_buffer_written_cb(filename);
63  };
64 
65  /* Create session thread. */
67 }
68 
70 {
71  /* Cancel any ongoing render operation. */
72  cancel();
73 
74  /* Signal session thread to end. */
75  {
76  thread_scoped_lock session_thread_lock(session_thread_mutex_);
78  }
79  session_thread_cond_.notify_all();
80 
81  /* Destroy session thread. */
83  delete session_thread_;
84 
85  /* Destroy path tracer, before the device. This is needed because destruction might need to
86  * access device for device memory free.
87  * TODO(sergey): Convert device to be unique_ptr, and rely on C++ to destruct objects in the
88  * pre-defined order. */
89  path_trace_.reset();
90 
91  /* Destroy scene and device. */
92  delete scene;
93  delete device;
94 
95  /* Stop task scheduler. */
97 }
98 
100 {
101  {
102  /* Signal session thread to start rendering. */
103  thread_scoped_lock session_thread_lock(session_thread_mutex_);
105  /* Already rendering, nothing to do. */
106  return;
107  }
109  }
110 
111  session_thread_cond_.notify_all();
112 }
113 
114 void Session::cancel(bool quick)
115 {
116  /* Check if session thread is rendering. */
117  const bool rendering = is_session_thread_rendering();
118 
119  if (rendering) {
120  /* Cancel path trace operations. */
121  if (quick && path_trace_) {
122  path_trace_->cancel();
123  }
124 
125  /* Cancel other operations. */
126  progress.set_cancel("Exiting");
127 
128  /* Signal unpause in case the render was paused. */
129  {
130  thread_scoped_lock pause_lock(pause_mutex_);
131  pause_ = false;
132  }
133  pause_cond_.notify_all();
134 
135  /* Wait for render thread to be cancelled or finished. */
136  wait();
137  }
138 }
139 
141 {
142  return path_trace_->ready_to_reset();
143 }
144 
146 {
147  path_trace_->clear_display();
148 
149  while (true) {
151 
152  if (!render_work) {
153  if (VLOG_INFO_IS_ON) {
154  double total_time, render_time;
155  progress.get_time(total_time, render_time);
156  VLOG_INFO << "Rendering in main loop is done in " << render_time << " seconds.";
157  VLOG_INFO << path_trace_->full_report();
158  }
159 
160  if (params.background) {
161  /* if no work left and in background mode, we can stop immediately. */
162  progress.set_status("Finished");
163  break;
164  }
165  }
166 
167  const bool did_cancel = progress.get_cancel();
168  if (did_cancel) {
170  if (!render_work) {
171  break;
172  }
173  }
174  else if (run_wait_for_work(render_work)) {
175  continue;
176  }
177 
178  /* Stop rendering if error happened during scene update or other step of preparing scene
179  * for render. */
180  if (device->have_error()) {
182  break;
183  }
184 
185  {
186  /* buffers mutex is locked entirely while rendering each
187  * sample, and released/reacquired on each iteration to allow
188  * reset and draw in between */
189  thread_scoped_lock buffers_lock(buffers_mutex_);
190 
191  /* update status and timing */
193 
194  /* render */
195  path_trace_->render(render_work);
196 
197  /* update status and timing */
199 
200  /* Stop rendering if error happened during path tracing. */
201  if (device->have_error()) {
203  break;
204  }
205  }
206 
208 
209  if (did_cancel) {
210  break;
211  }
212  }
213 }
214 
216 {
217  while (true) {
218  {
219  thread_scoped_lock session_thread_lock(session_thread_mutex_);
220 
222  /* Continue waiting for any signal from the main thread. */
223  session_thread_cond_.wait(session_thread_lock);
224  continue;
225  }
227  /* End thread immediately. */
228  break;
229  }
230  }
231 
232  /* Execute a render. */
233  thread_render();
234 
235  /* Go back from rendering to waiting. */
236  {
237  thread_scoped_lock session_thread_lock(session_thread_mutex_);
240  }
241  }
242  session_thread_cond_.notify_all();
243  }
244 
245  /* Flush any remaining operations and destroy display driver here. This ensure
246  * graphics API resources are created and destroyed all in the session thread,
247  * which can avoid problems contexts and multiple threads. */
248  path_trace_->flush_display();
249  path_trace_->set_display_driver(nullptr);
250 }
251 
253 {
255  profiler.start();
256  }
257 
258  /* session thread loop */
259  progress.set_status("Waiting for render to start");
260 
261  /* run */
262  if (!progress.get_cancel()) {
263  /* reset number of rendered samples */
265 
267  }
268 
269  profiler.stop();
270 
271  /* progress update */
272  if (progress.get_cancel())
274  else
276 }
277 
279 {
280  thread_scoped_lock session_thread_lock(session_thread_mutex_);
282 }
283 
285 {
286  RenderWork render_work;
287 
288  thread_scoped_lock scene_lock(scene->mutex);
290 
291  bool have_tiles = true;
292  bool switched_to_new_tile = false;
293 
294  const bool did_reset = delayed_reset_.do_reset;
295  if (delayed_reset_.do_reset) {
296  thread_scoped_lock buffers_lock(buffers_mutex_);
298 
299  /* After reset make sure the tile manager is at the first big tile. */
300  have_tiles = tile_manager_.next();
301  switched_to_new_tile = true;
302  }
303 
304  /* Update number of samples in the integrator.
305  * Ideally this would need to happen once in `Session::set_samples()`, but the issue there is
306  * the initial configuration when Session is created where the `set_samples()` is not used.
307  *
308  * NOTE: Unless reset was requested only allow increasing number of samples. */
309  if (did_reset || scene->integrator->get_aa_samples() < params.samples) {
310  scene->integrator->set_aa_samples(params.samples);
311  }
312 
313  /* Update denoiser settings. */
314  {
315  const DenoiseParams denoise_params = scene->integrator->get_denoise_params();
316  path_trace_->set_denoiser_params(denoise_params);
317  }
318 
319  /* Update adaptive sampling. */
320  {
321  const AdaptiveSampling adaptive_sampling = scene->integrator->get_adaptive_sampling();
322  path_trace_->set_adaptive_sampling(adaptive_sampling);
323  }
324 
328 
329  while (have_tiles) {
330  render_work = render_scheduler_.get_render_work();
331  if (render_work) {
332  break;
333  }
334 
336 
337  have_tiles = tile_manager_.next();
338  if (have_tiles) {
340  switched_to_new_tile = true;
341  }
342  }
343 
344  if (render_work) {
345  scoped_timer update_timer;
346 
347  if (switched_to_new_tile) {
348  BufferParams tile_params = buffer_params_;
349 
351 
352  tile_params.width = tile.width;
353  tile_params.height = tile.height;
354 
355  tile_params.window_x = tile.window_x;
356  tile_params.window_y = tile.window_y;
357  tile_params.window_width = tile.window_width;
358  tile_params.window_height = tile.window_height;
359 
360  tile_params.full_x = tile.x + buffer_params_.full_x;
361  tile_params.full_y = tile.y + buffer_params_.full_y;
362  tile_params.full_width = buffer_params_.full_width;
363  tile_params.full_height = buffer_params_.full_height;
364 
365  tile_params.update_offset_stride();
366 
367  path_trace_->reset(buffer_params_, tile_params, did_reset);
368  }
369 
370  const int resolution = render_work.resolution_divider;
371  const int width = max(1, buffer_params_.full_width / resolution);
372  const int height = max(1, buffer_params_.full_height / resolution);
373 
374  if (update_scene(width, height)) {
375  profiler.reset(scene->shaders.size(), scene->objects.size());
376  }
377 
378  /* Unlock scene mutex before loading denoiser kernels, since that may attempt to activate
379  * graphics interop, which can deadlock when the scene mutex is still being held. */
380  scene_lock.unlock();
381 
382  path_trace_->load_kernels();
383  path_trace_->alloc_work_memory();
384 
385  progress.add_skip_time(update_timer, params.background);
386  }
387 
388  return render_work;
389 }
390 
391 bool Session::run_wait_for_work(const RenderWork &render_work)
392 {
393  /* In an offline rendering there is no pause, and no tiles will mean the job is fully done. */
394  if (params.background) {
395  return false;
396  }
397 
398  thread_scoped_lock pause_lock(pause_mutex_);
399 
400  if (!pause_ && render_work) {
401  /* Rendering is not paused and there is work to be done. No need to wait for anything. */
402  return false;
403  }
404 
405  const bool no_work = !render_work;
406  update_status_time(pause_, no_work);
407 
408  /* Only leave the loop when rendering is not paused. But even if the current render is
409  * un-paused but there is nothing to render keep waiting until new work is added. */
410  while (!progress.get_cancel()) {
411  scoped_timer pause_timer;
412 
413  if (!pause_ && (render_work || new_work_added_ || delayed_reset_.do_reset)) {
414  break;
415  }
416 
417  /* Wait for either pause state changed, or extra samples added to render. */
418  pause_cond_.wait(pause_lock);
419 
420  if (pause_) {
421  progress.add_skip_time(pause_timer, params.background);
422  }
423 
424  update_status_time(pause_, no_work);
426  }
427 
428  new_work_added_ = false;
429 
430  return no_work;
431 }
432 
434 {
435  path_trace_->draw();
436 }
437 
439 {
440  const int image_width = buffer_params_.width;
441  const int image_height = buffer_params_.height;
442 
443  if (!params.use_auto_tile) {
444  return make_int2(image_width, image_height);
445  }
446 
447  const int64_t image_area = static_cast<int64_t>(image_width) * image_height;
448 
449  /* TODO(sergey): Take available memory into account, and if there is enough memory do not
450  * tile and prefer optimal performance. */
451 
453  const int64_t actual_tile_area = static_cast<int64_t>(tile_size) * tile_size;
454 
455  if (actual_tile_area >= image_area && image_width <= TileManager::MAX_TILE_SIZE &&
456  image_height <= TileManager::MAX_TILE_SIZE) {
457  return make_int2(image_width, image_height);
458  }
459 
460  return make_int2(tile_size, tile_size);
461 }
462 
464 {
465  if (!delayed_reset_.do_reset) {
466  return;
467  }
468  delayed_reset_.do_reset = false;
469 
472 
473  /* Store parameters used for buffers access outside of scene graph. */
475  buffer_params_.exposure = scene->film->get_exposure();
477  scene->film->get_use_approximate_shadow_catcher();
479 
480  /* Tile and work scheduling. */
483 
484  /* Passes. */
485  /* When multiple tiles are used SAMPLE_COUNT pass is used to keep track of possible partial
486  * tile results. It is safe to use generic update function here which checks for changes since
487  * changes in tile settings re-creates session, which ensures film is fully updated on tile
488  * changes. */
490 
491  /* Update for new state of scene and passes. */
494 
495  /* Update temp directory on reset.
496  * This potentially allows to finish the existing rendering with a previously configure
497  * temporary
498  * directory in the host software and switch to a new temp directory when new render starts. */
500 
501  /* Progress. */
505 
506  if (!params.background) {
508  }
510 }
511 
512 void Session::reset(const SessionParams &session_params, const BufferParams &buffer_params)
513 {
514  {
516  thread_scoped_lock pause_lock(pause_mutex_);
517 
518  delayed_reset_.do_reset = true;
519  delayed_reset_.session_params = session_params;
520  delayed_reset_.buffer_params = buffer_params;
521 
522  path_trace_->cancel();
523  }
524 
525  pause_cond_.notify_all();
526 }
527 
528 void Session::set_samples(int samples)
529 {
530  if (samples == params.samples) {
531  return;
532  }
533 
534  params.samples = samples;
535 
536  {
537  thread_scoped_lock pause_lock(pause_mutex_);
538  new_work_added_ = true;
539  }
540 
541  pause_cond_.notify_all();
542 }
543 
544 void Session::set_time_limit(double time_limit)
545 {
546  if (time_limit == params.time_limit) {
547  return;
548  }
549 
550  params.time_limit = time_limit;
551 
552  {
553  thread_scoped_lock pause_lock(pause_mutex_);
554  new_work_added_ = true;
555  }
556 
557  pause_cond_.notify_all();
558 }
559 
560 void Session::set_pause(bool pause)
561 {
562  bool notify = false;
563 
564  {
565  thread_scoped_lock pause_lock(pause_mutex_);
566 
567  if (pause != pause_) {
568  pause_ = pause;
569  notify = true;
570  }
571  }
572 
574  if (notify) {
575  pause_cond_.notify_all();
576  }
577  }
578  else if (pause_) {
580  }
581 }
582 
583 void Session::set_output_driver(unique_ptr<OutputDriver> driver)
584 {
585  path_trace_->set_output_driver(move(driver));
586 }
587 
588 void Session::set_display_driver(unique_ptr<DisplayDriver> driver)
589 {
590  path_trace_->set_display_driver(move(driver));
591 }
592 
594 {
595  const double completed = progress.get_progress();
596  if (completed == 0.0) {
597  return 0.0;
598  }
599 
600  double total_time, render_time;
601  progress.get_time(total_time, render_time);
602  double remaining = (1.0 - (double)completed) * (render_time / (double)completed);
603 
604  const double time_limit = render_scheduler_.get_time_limit();
605  if (time_limit != 0.0) {
606  remaining = min(remaining, max(time_limit - render_time, 0.0));
607  }
608 
609  return remaining;
610 }
611 
613 {
614  /* Wait until session thread either is waiting or ending. */
615  while (true) {
616  thread_scoped_lock session_thread_lock(session_thread_mutex_);
618  break;
619  }
620  session_thread_cond_.wait(session_thread_lock);
621  }
622 }
623 
625 {
626  /* Update camera if dimensions changed for progressive render. the camera
627  * knows nothing about progressive or cropped rendering, it just gets the
628  * image dimensions passed in. */
629  Camera *cam = scene->camera;
631 
632  return scene->update(progress);
633 }
634 
635 static string status_append(const string &status, const string &suffix)
636 {
637  string prefix = status;
638  if (!prefix.empty()) {
639  prefix += ", ";
640  }
641  return prefix + suffix;
642 }
643 
644 void Session::update_status_time(bool show_pause, bool show_done)
645 {
646  string status, substatus;
647 
648  const int current_tile = progress.get_rendered_tiles();
649  const int num_tiles = tile_manager_.get_num_tiles();
650 
651  const int current_sample = progress.get_current_sample();
653 
654  /* TIle. */
656  substatus = status_append(substatus,
657  string_printf("Rendered %d/%d Tiles", current_tile, num_tiles));
658  }
659 
660  /* Sample. */
662  substatus = status_append(substatus, string_printf("Sample %d", current_sample));
663  }
664  else {
665  substatus = status_append(substatus,
666  string_printf("Sample %d/%d", current_sample, num_samples));
667  }
668 
669  /* TODO(sergey): Denoising status from the path trace. */
670 
671  if (show_pause) {
672  status = "Rendering Paused";
673  }
674  else if (show_done) {
675  status = "Rendering Done";
676  progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
677  }
678  else {
679  status = substatus;
680  substatus.clear();
681  }
682 
683  progress.set_status(status, substatus);
684 }
685 
687 {
688  scene->device_free();
689  path_trace_->device_free();
690 }
691 
693 {
694  scene->collect_statistics(render_stats);
696  render_stats->collect_profiling(scene, profiler);
697  }
698 }
699 
700 /* --------------------------------------------------------------------
701  * Full-frame on-disk storage.
702  */
703 
704 void Session::process_full_buffer_from_disk(string_view filename)
705 {
706  path_trace_->process_full_buffer_from_disk(filename);
707 }
708 
typedef double(DMatrix)[4][4]
struct Scene Scene
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
int full_x
Definition: buffers.h:84
int full_width
Definition: buffers.h:86
bool use_approximate_shadow_catcher
Definition: buffers.h:101
int height
Definition: buffers.h:72
float exposure
Definition: buffers.h:100
int window_y
Definition: buffers.h:79
void update_offset_stride()
Definition: buffers.cpp:222
int full_height
Definition: buffers.h:87
int window_height
Definition: buffers.h:81
int window_width
Definition: buffers.h:80
NODE_DECLARE int width
Definition: buffers.h:71
int window_x
Definition: buffers.h:78
bool use_transparent_background
Definition: buffers.h:102
int full_y
Definition: buffers.h:85
int samples
Definition: buffers.h:99
void update_passes()
Definition: buffers.cpp:121
DeviceType type
Definition: device/device.h:62
static Device * create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
virtual const string & error_message()
bool have_error()
void update_passes(Scene *scene, bool add_sample_count_pass)
Definition: film.cpp:461
DenoiseParams get_denoise_params() const
Definition: integrator.cpp:372
AdaptiveSampling get_adaptive_sampling() const
Definition: integrator.cpp:329
static const int MAX_SAMPLES
Definition: integrator.h:65
void start()
Definition: profiling.cpp:76
void reset(int num_shaders, int num_objects)
Definition: profiling.cpp:56
void stop()
Definition: profiling.cpp:83
int get_current_sample() const
Definition: progress.h:226
void set_total_pixel_samples(uint64_t total_pixel_samples_)
Definition: progress.h:183
void set_cancel(const string &cancel_message_)
Definition: progress.h:83
void set_end_time()
Definition: progress.h:168
string get_cancel_message() const
Definition: progress.h:98
void get_time(double &total_time_, double &render_time_) const
Definition: progress.h:158
bool get_cancel() const
Definition: progress.h:90
void reset_sample()
Definition: progress.h:173
void set_status(const string &status_, const string &substatus_="")
Definition: progress.h:248
void set_update()
Definition: progress.h:306
void set_error(const string &error_message_)
Definition: progress.h:110
double get_progress() const
Definition: progress.h:190
void set_render_start_time()
Definition: progress.h:141
void add_finished_tile(bool denoised)
Definition: progress.h:214
void add_skip_time(const scoped_timer &start_timer, bool only_render)
Definition: progress.h:148
int get_rendered_tiles() const
Definition: progress.h:234
void set_start_time()
Definition: progress.h:133
void set_time_limit(double time_limit)
void reset(const BufferParams &buffer_params, int num_samples, int sample_offset)
double get_time_limit() const
int get_num_samples() const
void set_num_samples(int num_samples)
void set_start_sample(int start_sample)
void render_work_reschedule_on_cancel(RenderWork &render_work)
RenderWork get_render_work()
int resolution_divider
DeviceInfo device
void thread_run()
void collect_statistics(RenderStats *stats)
RenderScheduler render_scheduler_
Device * device
void update_status_time(bool show_pause=false, bool show_done=false)
void set_pause(bool pause)
thread_mutex pause_mutex_
int2 get_effective_tile_size() const
void process_full_buffer_from_disk(string_view filename)
void set_display_driver(unique_ptr< DisplayDriver > driver)
bool ready_to_reset()
void set_time_limit(double time_limit)
void cancel(bool quick=false)
void do_delayed_reset()
thread_condition_variable pause_cond_
enum Session::@1267 session_thread_state_
void start()
Progress progress
Profiler profiler
bool run_wait_for_work(const RenderWork &render_work)
double get_estimated_remaining_time() const
SessionParams params
thread_condition_variable session_thread_cond_
Session(const SessionParams &params, const SceneParams &scene_params)
bool update_scene(int width, int height)
function< void(string_view)> full_buffer_written_cb
void run_main_render_loop()
void thread_render()
thread_mutex session_thread_mutex_
BufferParams buffer_params_
RenderWork run_update_for_next_iteration()
void reset(const SessionParams &session_params, const BufferParams &buffer_params)
thread * session_thread_
bool is_session_thread_rendering()
void device_free()
thread_mutex buffers_mutex_
Scene * scene
void set_output_driver(unique_ptr< OutputDriver > driver)
struct Session::DelayedReset delayed_reset_
void set_samples(int samples)
unique_ptr< PathTrace > path_trace_
TileManager tile_manager_
@ SESSION_THREAD_END
@ SESSION_THREAD_RENDER
@ SESSION_THREAD_WAIT
bool new_work_added_
static void exit()
Definition: task.cpp:83
static void init(int num_threads=0)
Definition: task.cpp:62
void set_temp_dir(const string &temp_dir)
function< void(string_view)> full_buffer_written_cb
Definition: session/tile.h:40
void reset_scheduling(const BufferParams &params, int2 tile_size)
int compute_render_tile_size(const int suggested_tile_size) const
bool has_multiple_tiles() const
Definition: session/tile.h:68
void update(const BufferParams &params, const Scene *scene)
const Tile & get_current_tile() const
int get_num_tiles() const
Definition: session/tile.h:63
static const int MAX_TILE_SIZE
Definition: session/tile.h:118
Definition: thread.h:34
bool join()
Definition: thread.cpp:42
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
#define function_bind
@ DEVICE_CPU
Definition: device/device.h:38
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_gpu_kernel_postfix ccl_global KernelWorkTile const int num_tiles
ccl_global const KernelWorkTile * tile
ccl_gpu_kernel_postfix ccl_global float int int int int ccl_global const float int int int int int int int int int int int int num_samples
#define VLOG_INFO
Definition: log.h:77
#define VLOG_INFO_IS_ON
Definition: log.h:78
#define make_int2(x, y)
Definition: metal/compat.h:206
static string status_append(const string &status, const string &suffix)
#define min(a, b)
Definition: sort.c:35
__int64 int64_t
Definition: stdint.h:89
unsigned __int64 uint64_t
Definition: stdint.h:90
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22
void set_screen_size(int width_, int height_)
void collect_profiling(Scene *scene, Profiler &prof)
Definition: stats.cpp:249
Film * film
Definition: scene.h:208
bool update(Progress &progress)
Definition: scene.cpp:574
vector< Pass * > passes
Definition: scene.h:218
vector< Shader * > shaders
Definition: scene.h:215
void device_free()
Definition: scene.cpp:468
vector< Object * > objects
Definition: scene.h:213
Background * background
Definition: scene.h:209
Integrator * integrator
Definition: scene.h:210
thread_mutex mutex
Definition: scene.h:246
struct Object * camera
void collect_statistics(RenderStats *stats)
Definition: scene.cpp:473
DeviceScene dscene
Definition: scene.h:240
SessionParams session_params
BufferParams buffer_params
std::unique_lock< std::mutex > thread_scoped_lock
Definition: thread.h:28
float max