Merge remote-tracking branch 'origin/blender-v2.93-release'
[blender.git] / intern / cycles / render / session.cpp
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
17 #include <limits.h>
18 #include <string.h>
19
20 #include "device/device.h"
21 #include "render/bake.h"
22 #include "render/buffers.h"
23 #include "render/camera.h"
24 #include "render/graph.h"
25 #include "render/integrator.h"
26 #include "render/light.h"
27 #include "render/mesh.h"
28 #include "render/object.h"
29 #include "render/scene.h"
30 #include "render/session.h"
31
32 #include "util/util_foreach.h"
33 #include "util/util_function.h"
34 #include "util/util_logging.h"
35 #include "util/util_math.h"
36 #include "util/util_opengl.h"
37 #include "util/util_task.h"
38 #include "util/util_time.h"
39
40 CCL_NAMESPACE_BEGIN
41
42 /* Note about  preserve_tile_device option for tile manager:
43  * progressive refine and viewport rendering does requires tiles to
44  * always be allocated for the same device
45  */
46 Session::Session(const SessionParams &params_)
47     : params(params_),
48       tile_manager(params.progressive,
49                    params.samples,
50                    params.tile_size,
51                    params.start_resolution,
52                    params.background == false || params.progressive_refine,
53                    params.background,
54                    params.tile_order,
55                    max(params.device.multi_devices.size(), 1),
56                    params.pixel_size),
57       stats(),
58       profiler()
59 {
60   device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
61
62   TaskScheduler::init(params.threads);
63
64   session_thread = NULL;
65   scene = NULL;
66
67   reset_time = 0.0;
68   last_update_time = 0.0;
69
70   delayed_reset.do_reset = false;
71   delayed_reset.samples = 0;
72
73   display_outdated = false;
74   gpu_draw_ready = false;
75   gpu_need_display_buffer_update = false;
76   pause = false;
77
78   buffers = NULL;
79   display = NULL;
80
81   /* Validate denoising parameters. */
82   set_denoising(params.denoising);
83
84   /* Create CPU/GPU devices. */
85   device = Device::create(params.device, stats, profiler, params.background);
86
87   if (!device->error_message().empty()) {
88     progress.set_error(device->error_message());
89     return;
90   }
91
92   /* Create buffers for interactive rendering. */
93   if (!(params.background && !params.write_render_cb)) {
94     buffers = new RenderBuffers(device);
95     display = new DisplayBuffer(device, params.display_buffer_linear);
96   }
97 }
98
99 Session::~Session()
100 {
101   cancel();
102
103   if (buffers && params.write_render_cb) {
104     /* Copy to display buffer and write out image if requested */
105     delete display;
106
107     display = new DisplayBuffer(device, false);
108     display->reset(buffers->params);
109     copy_to_display_buffer(params.samples);
110
111     int w = display->draw_width;
112     int h = display->draw_height;
113     uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h);
114     params.write_render_cb((uchar *)pixels, w, h, 4);
115   }
116
117   /* clean up */
118   tile_manager.device_free();
119
120   delete buffers;
121   delete display;
122   delete scene;
123   delete device;
124
125   TaskScheduler::exit();
126 }
127
128 void Session::start()
129 {
130   if (!session_thread) {
131     session_thread = new thread(function_bind(&Session::run, this));
132   }
133 }
134
135 void Session::cancel()
136 {
137   if (session_thread) {
138     /* wait for session thread to end */
139     progress.set_cancel("Exiting");
140
141     gpu_need_display_buffer_update = false;
142     gpu_need_display_buffer_update_cond.notify_all();
143
144     {
145       thread_scoped_lock pause_lock(pause_mutex);
146       pause = false;
147     }
148     pause_cond.notify_all();
149
150     wait();
151   }
152 }
153
154 bool Session::ready_to_reset()
155 {
156   double dt = time_dt() - reset_time;
157
158   if (!display_outdated)
159     return (dt > params.reset_timeout);
160   else
161     return (dt > params.cancel_timeout);
162 }
163
164 /* GPU Session */
165
166 void Session::reset_gpu(BufferParams &buffer_params, int samples)
167 {
168   thread_scoped_lock pause_lock(pause_mutex);
169
170   /* block for buffer access and reset immediately. we can't do this
171    * in the thread, because we need to allocate an OpenGL buffer, and
172    * that only works in the main thread */
173   thread_scoped_lock display_lock(display_mutex);
174   thread_scoped_lock buffers_lock(buffers_mutex);
175
176   display_outdated = true;
177   reset_time = time_dt();
178
179   reset_(buffer_params, samples);
180
181   gpu_need_display_buffer_update = false;
182   gpu_need_display_buffer_update_cond.notify_all();
183
184   pause_cond.notify_all();
185 }
186
187 bool Session::draw_gpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
188 {
189   /* block for buffer access */
190   thread_scoped_lock display_lock(display_mutex);
191
192   /* first check we already rendered something */
193   if (gpu_draw_ready) {
194     /* then verify the buffers have the expected size, so we don't
195      * draw previous results in a resized window */
196     if (buffer_params.width == display->params.width &&
197         buffer_params.height == display->params.height) {
198       /* for CUDA we need to do tone-mapping still, since we can
199        * only access GL buffers from the main thread. */
200       if (gpu_need_display_buffer_update) {
201         thread_scoped_lock buffers_lock(buffers_mutex);
202         copy_to_display_buffer(tile_manager.state.sample);
203         gpu_need_display_buffer_update = false;
204         gpu_need_display_buffer_update_cond.notify_all();
205       }
206
207       display->draw(device, draw_params);
208
209       if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
210         return false;
211
212       return true;
213     }
214   }
215
216   return false;
217 }
218
219 void Session::run_gpu()
220 {
221   bool tiles_written = false;
222
223   reset_time = time_dt();
224   last_update_time = time_dt();
225   last_display_time = last_update_time;
226
227   progress.set_render_start_time();
228
229   while (!progress.get_cancel()) {
230     /* advance to next tile */
231     bool no_tiles = !tile_manager.next();
232
233     DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
234     if (no_tiles) {
235       kernel_state = device->get_active_kernel_switch_state();
236     }
237
238     if (params.background) {
239       /* if no work left and in background mode, we can stop immediately */
240       if (no_tiles) {
241         progress.set_status("Finished");
242         break;
243       }
244     }
245
246     else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
247       reset_gpu(tile_manager.params, params.samples);
248     }
249
250     else {
251       /* if in interactive mode, and we are either paused or done for now,
252        * wait for pause condition notify to wake up again */
253       thread_scoped_lock pause_lock(pause_mutex);
254
255       if (!pause && !tile_manager.done()) {
256         /* reset could have happened after no_tiles was set, before this lock.
257          * in this case we shall not wait for pause condition
258          */
259       }
260       else if (pause || no_tiles) {
261         update_status_time(pause, no_tiles);
262
263         while (1) {
264           scoped_timer pause_timer;
265           pause_cond.wait(pause_lock);
266           if (pause) {
267             progress.add_skip_time(pause_timer, params.background);
268           }
269
270           update_status_time(pause, no_tiles);
271           progress.set_update();
272
273           if (!pause)
274             break;
275         }
276       }
277
278       if (progress.get_cancel())
279         break;
280     }
281
282     if (!no_tiles) {
283       /* update scene */
284       scoped_timer update_timer;
285       if (update_scene()) {
286         profiler.reset(scene->shaders.size(), scene->objects.size());
287       }
288       progress.add_skip_time(update_timer, params.background);
289
290       if (!device->error_message().empty())
291         progress.set_error(device->error_message());
292
293       if (progress.get_cancel())
294         break;
295
296       /* buffers mutex is locked entirely while rendering each
297        * sample, and released/reacquired on each iteration to allow
298        * reset and draw in between */
299       thread_scoped_lock buffers_lock(buffers_mutex);
300
301       /* update status and timing */
302       update_status_time();
303
304       /* render */
305       bool delayed_denoise = false;
306       const bool need_denoise = render_need_denoise(delayed_denoise);
307       render(need_denoise);
308
309       device->task_wait();
310
311       if (!device->error_message().empty())
312         progress.set_cancel(device->error_message());
313
314       /* update status and timing */
315       update_status_time();
316
317       gpu_need_display_buffer_update = !delayed_denoise;
318       gpu_draw_ready = true;
319       progress.set_update();
320
321       /* wait for until display buffer is updated */
322       if (!params.background) {
323         while (gpu_need_display_buffer_update) {
324           if (progress.get_cancel())
325             break;
326
327           gpu_need_display_buffer_update_cond.wait(buffers_lock);
328         }
329       }
330
331       if (!device->error_message().empty())
332         progress.set_error(device->error_message());
333
334       tiles_written = update_progressive_refine(progress.get_cancel());
335
336       if (progress.get_cancel())
337         break;
338     }
339   }
340
341   if (!tiles_written)
342     update_progressive_refine(true);
343 }
344
345 /* CPU Session */
346
347 void Session::reset_cpu(BufferParams &buffer_params, int samples)
348 {
349   thread_scoped_lock reset_lock(delayed_reset.mutex);
350   thread_scoped_lock pause_lock(pause_mutex);
351
352   display_outdated = true;
353   reset_time = time_dt();
354
355   delayed_reset.params = buffer_params;
356   delayed_reset.samples = samples;
357   delayed_reset.do_reset = true;
358   device->task_cancel();
359
360   pause_cond.notify_all();
361 }
362
363 bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
364 {
365   thread_scoped_lock display_lock(display_mutex);
366
367   /* first check we already rendered something */
368   if (display->draw_ready()) {
369     /* then verify the buffers have the expected size, so we don't
370      * draw previous results in a resized window */
371     if (buffer_params.width == display->params.width &&
372         buffer_params.height == display->params.height) {
373       display->draw(device, draw_params);
374
375       if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
376         return false;
377
378       return true;
379     }
380   }
381
382   return false;
383 }
384
385 bool Session::steal_tile(RenderTile &rtile, Device *tile_device, thread_scoped_lock &tile_lock)
386 {
387   /* Devices that can get their tiles stolen don't steal tiles themselves.
388    * Additionally, if there are no stealable tiles in flight, give up here. */
389   if (tile_device->info.type == DEVICE_CPU || stealable_tiles == 0) {
390     return false;
391   }
392
393   /* Wait until no other thread is trying to steal a tile. */
394   while (tile_stealing_state != NOT_STEALING && stealable_tiles > 0) {
395     /* Someone else is currently trying to get a tile.
396      * Wait on the condition variable and try later. */
397     tile_steal_cond.wait(tile_lock);
398   }
399   /* If another thread stole the last stealable tile in the meantime, give up. */
400   if (stealable_tiles == 0) {
401     return false;
402   }
403
404   /* There are stealable tiles in flight, so signal that one should be released. */
405   tile_stealing_state = WAITING_FOR_TILE;
406
407   /* Wait until a device notices the signal and releases its tile. */
408   while (tile_stealing_state != GOT_TILE && stealable_tiles > 0) {
409     tile_steal_cond.wait(tile_lock);
410   }
411   /* If the last stealable tile finished on its own, give up. */
412   if (tile_stealing_state != GOT_TILE) {
413     tile_stealing_state = NOT_STEALING;
414     return false;
415   }
416
417   /* Successfully stole a tile, now move it to the new device. */
418   rtile = stolen_tile;
419   rtile.buffers->buffer.move_device(tile_device);
420   rtile.buffer = rtile.buffers->buffer.device_pointer;
421   rtile.stealing_state = RenderTile::NO_STEALING;
422   rtile.num_samples -= (rtile.sample - rtile.start_sample);
423   rtile.start_sample = rtile.sample;
424
425   tile_stealing_state = NOT_STEALING;
426
427   /* Poke any threads which might be waiting for NOT_STEALING above. */
428   tile_steal_cond.notify_one();
429
430   return true;
431 }
432
433 bool Session::get_tile_stolen()
434 {
435   /* If tile_stealing_state is WAITING_FOR_TILE, atomically set it to RELEASING_TILE
436    * and return true. */
437   TileStealingState expected = WAITING_FOR_TILE;
438   return tile_stealing_state.compare_exchange_weak(expected, RELEASING_TILE);
439 }
440
441 bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_types)
442 {
443   if (progress.get_cancel()) {
444     if (params.progressive_refine == false) {
445       /* for progressive refine current sample should be finished for all tiles */
446       return false;
447     }
448   }
449
450   thread_scoped_lock tile_lock(tile_mutex);
451
452   /* get next tile from manager */
453   Tile *tile;
454   int device_num = device->device_number(tile_device);
455
456   while (!tile_manager.next_tile(tile, device_num, tile_types)) {
457     /* Can only steal tiles on devices that support rendering
458      * This is because denoising tiles cannot be stolen (see below)
459      */
460     if ((tile_types & (RenderTile::PATH_TRACE | RenderTile::BAKE)) &&
461         steal_tile(rtile, tile_device, tile_lock)) {
462       return true;
463     }
464
465     /* Wait for denoising tiles to become available */
466     if ((tile_types & RenderTile::DENOISE) && !progress.get_cancel() && tile_manager.has_tiles()) {
467       denoising_cond.wait(tile_lock);
468       continue;
469     }
470
471     return false;
472   }
473
474   /* fill render tile */
475   rtile.x = tile_manager.state.buffer.full_x + tile->x;
476   rtile.y = tile_manager.state.buffer.full_y + tile->y;
477   rtile.w = tile->w;
478   rtile.h = tile->h;
479   rtile.start_sample = tile_manager.state.sample;
480   rtile.num_samples = tile_manager.state.num_samples;
481   rtile.resolution = tile_manager.state.resolution_divider;
482   rtile.tile_index = tile->index;
483   rtile.stealing_state = RenderTile::NO_STEALING;
484
485   if (tile->state == Tile::DENOISE) {
486     rtile.task = RenderTile::DENOISE;
487   }
488   else {
489     if (tile_device->info.type == DEVICE_CPU) {
490       stealable_tiles++;
491       rtile.stealing_state = RenderTile::CAN_BE_STOLEN;
492     }
493
494     if (read_bake_tile_cb) {
495       rtile.task = RenderTile::BAKE;
496     }
497     else {
498       rtile.task = RenderTile::PATH_TRACE;
499     }
500   }
501
502   tile_lock.unlock();
503
504   /* in case of a permanent buffer, return it, otherwise we will allocate
505    * a new temporary buffer */
506   if (buffers) {
507     tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
508
509     rtile.buffer = buffers->buffer.device_pointer;
510     rtile.buffers = buffers;
511
512     device->map_tile(tile_device, rtile);
513
514     /* Reset copy state, since buffer contents change after the tile was acquired */
515     buffers->map_neighbor_copied = false;
516
517     /* This hack ensures that the copy in 'MultiDevice::map_neighbor_tiles' accounts
518      * for the buffer resolution divider. */
519     buffers->buffer.data_width = (buffers->params.width * buffers->params.get_passes_size()) /
520                                  tile_manager.state.resolution_divider;
521     buffers->buffer.data_height = buffers->params.height / tile_manager.state.resolution_divider;
522
523     return true;
524   }
525
526   if (tile->buffers == NULL) {
527     /* fill buffer parameters */
528     BufferParams buffer_params = tile_manager.params;
529     buffer_params.full_x = rtile.x;
530     buffer_params.full_y = rtile.y;
531     buffer_params.width = rtile.w;
532     buffer_params.height = rtile.h;
533
534     /* allocate buffers */
535     tile->buffers = new RenderBuffers(tile_device);
536     tile->buffers->reset(buffer_params);
537   }
538   else if (tile->buffers->buffer.device != tile_device) {
539     /* Move buffer to current tile device again in case it was stolen before.
540      * Not needed for denoising since that already handles mapping of tiles and
541      * neighbors to its own device. */
542     if (rtile.task != RenderTile::DENOISE) {
543       tile->buffers->buffer.move_device(tile_device);
544     }
545   }
546
547   tile->buffers->map_neighbor_copied = false;
548
549   tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
550
551   rtile.buffer = tile->buffers->buffer.device_pointer;
552   rtile.buffers = tile->buffers;
553   rtile.sample = tile_manager.state.sample;
554
555   if (read_bake_tile_cb) {
556     /* This will read any passes needed as input for baking. */
557     if (tile_manager.state.sample == tile_manager.range_start_sample) {
558       {
559         thread_scoped_lock tile_lock(tile_mutex);
560         read_bake_tile_cb(rtile);
561       }
562       rtile.buffers->buffer.copy_to_device();
563     }
564   }
565   else {
566     /* This will tag tile as IN PROGRESS in blender-side render pipeline,
567      * which is needed to highlight currently rendering tile before first
568      * sample was processed for it. */
569     update_tile_sample(rtile);
570   }
571
572   return true;
573 }
574
575 void Session::update_tile_sample(RenderTile &rtile)
576 {
577   thread_scoped_lock tile_lock(tile_mutex);
578
579   if (update_render_tile_cb) {
580     if (params.progressive_refine == false) {
581       /* todo: optimize this by making it thread safe and removing lock */
582
583       update_render_tile_cb(rtile, true);
584     }
585   }
586
587   update_status_time();
588 }
589
590 void Session::release_tile(RenderTile &rtile, const bool need_denoise)
591 {
592   thread_scoped_lock tile_lock(tile_mutex);
593
594   if (rtile.stealing_state != RenderTile::NO_STEALING) {
595     stealable_tiles--;
596     if (rtile.stealing_state == RenderTile::WAS_STOLEN) {
597       /* If the tile is being stolen, don't release it here - the new device will pick up where
598        * the old one left off. */
599
600       assert(tile_stealing_state == RELEASING_TILE);
601       assert(rtile.sample < rtile.start_sample + rtile.num_samples);
602
603       tile_stealing_state = GOT_TILE;
604       stolen_tile = rtile;
605       tile_steal_cond.notify_all();
606       return;
607     }
608     else if (stealable_tiles == 0) {
609       /* If this was the last stealable tile, wake up any threads still waiting for one. */
610       tile_steal_cond.notify_all();
611     }
612   }
613
614   progress.add_finished_tile(rtile.task == RenderTile::DENOISE);
615
616   bool delete_tile;
617
618   if (tile_manager.finish_tile(rtile.tile_index, need_denoise, delete_tile)) {
619     /* Finished tile pixels write. */
620     if (write_render_tile_cb && params.progressive_refine == false) {
621       write_render_tile_cb(rtile);
622     }
623
624     if (delete_tile) {
625       delete rtile.buffers;
626       tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
627     }
628   }
629   else {
630     /* In progress tile pixels update. */
631     if (update_render_tile_cb && params.progressive_refine == false) {
632       update_render_tile_cb(rtile, false);
633     }
634   }
635
636   update_status_time();
637
638   /* Notify denoising thread that a tile was finished. */
639   denoising_cond.notify_all();
640 }
641
642 void Session::map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
643 {
644   thread_scoped_lock tile_lock(tile_mutex);
645
646   const int4 image_region = make_int4(
647       tile_manager.state.buffer.full_x,
648       tile_manager.state.buffer.full_y,
649       tile_manager.state.buffer.full_x + tile_manager.state.buffer.width,
650       tile_manager.state.buffer.full_y + tile_manager.state.buffer.height);
651
652   RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
653
654   if (!tile_manager.schedule_denoising) {
655     /* Fix up tile slices with overlap. */
656     if (tile_manager.slice_overlap != 0) {
657       int y = max(center_tile.y - tile_manager.slice_overlap, image_region.y);
658       center_tile.h = min(center_tile.y + center_tile.h + tile_manager.slice_overlap,
659                           image_region.w) -
660                       y;
661       center_tile.y = y;
662     }
663
664     /* Tiles are not being denoised individually, which means the entire image is processed. */
665     neighbors.set_bounds_from_center();
666   }
667   else {
668     int center_idx = center_tile.tile_index;
669     assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE);
670
671     for (int dy = -1, i = 0; dy <= 1; dy++) {
672       for (int dx = -1; dx <= 1; dx++, i++) {
673         RenderTile &rtile = neighbors.tiles[i];
674         int nindex = tile_manager.get_neighbor_index(center_idx, i);
675         if (nindex >= 0) {
676           Tile *tile = &tile_manager.state.tiles[nindex];
677
678           rtile.x = image_region.x + tile->x;
679           rtile.y = image_region.y + tile->y;
680           rtile.w = tile->w;
681           rtile.h = tile->h;
682
683           if (buffers) {
684             tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
685
686             rtile.buffer = buffers->buffer.device_pointer;
687             rtile.buffers = buffers;
688           }
689           else {
690             assert(tile->buffers);
691             tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
692
693             rtile.buffer = tile->buffers->buffer.device_pointer;
694             rtile.buffers = tile->buffers;
695           }
696         }
697         else {
698           int px = center_tile.x + dx * params.tile_size.x;
699           int py = center_tile.y + dy * params.tile_size.y;
700
701           rtile.x = clamp(px, image_region.x, image_region.z);
702           rtile.y = clamp(py, image_region.y, image_region.w);
703           rtile.w = rtile.h = 0;
704
705           rtile.buffer = (device_ptr)NULL;
706           rtile.buffers = NULL;
707         }
708       }
709     }
710   }
711
712   assert(center_tile.buffers);
713   device->map_neighbor_tiles(tile_device, neighbors);
714
715   /* The denoised result is written back to the original tile. */
716   neighbors.target = center_tile;
717 }
718
719 void Session::unmap_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
720 {
721   thread_scoped_lock tile_lock(tile_mutex);
722   device->unmap_neighbor_tiles(tile_device, neighbors);
723 }
724
725 void Session::run_cpu()
726 {
727   bool tiles_written = false;
728
729   last_update_time = time_dt();
730   last_display_time = last_update_time;
731
732   {
733     /* reset once to start */
734     thread_scoped_lock reset_lock(delayed_reset.mutex);
735     thread_scoped_lock buffers_lock(buffers_mutex);
736     thread_scoped_lock display_lock(display_mutex);
737
738     reset_(delayed_reset.params, delayed_reset.samples);
739     delayed_reset.do_reset = false;
740   }
741
742   while (!progress.get_cancel()) {
743     /* advance to next tile */
744     bool no_tiles = !tile_manager.next();
745     bool need_copy_to_display_buffer = false;
746
747     DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
748     if (no_tiles) {
749       kernel_state = device->get_active_kernel_switch_state();
750     }
751
752     if (params.background) {
753       /* if no work left and in background mode, we can stop immediately */
754       if (no_tiles) {
755         progress.set_status("Finished");
756         break;
757       }
758     }
759
760     else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
761       reset_cpu(tile_manager.params, params.samples);
762     }
763
764     else {
765       /* if in interactive mode, and we are either paused or done for now,
766        * wait for pause condition notify to wake up again */
767       thread_scoped_lock pause_lock(pause_mutex);
768
769       if (!pause && delayed_reset.do_reset) {
770         /* reset once to start */
771         thread_scoped_lock reset_lock(delayed_reset.mutex);
772         thread_scoped_lock buffers_lock(buffers_mutex);
773         thread_scoped_lock display_lock(display_mutex);
774
775         reset_(delayed_reset.params, delayed_reset.samples);
776         delayed_reset.do_reset = false;
777       }
778       else if (pause || no_tiles) {
779         update_status_time(pause, no_tiles);
780
781         while (1) {
782           scoped_timer pause_timer;
783           pause_cond.wait(pause_lock);
784           if (pause) {
785             progress.add_skip_time(pause_timer, params.background);
786           }
787
788           update_status_time(pause, no_tiles);
789           progress.set_update();
790
791           if (!pause)
792             break;
793         }
794       }
795
796       if (progress.get_cancel())
797         break;
798     }
799
800     if (!no_tiles) {
801       /* update scene */
802       scoped_timer update_timer;
803       if (update_scene()) {
804         profiler.reset(scene->shaders.size(), scene->objects.size());
805       }
806       progress.add_skip_time(update_timer, params.background);
807
808       if (!device->error_message().empty())
809         progress.set_error(device->error_message());
810
811       if (progress.get_cancel())
812         break;
813
814       /* buffers mutex is locked entirely while rendering each
815        * sample, and released/reacquired on each iteration to allow
816        * reset and draw in between */
817       thread_scoped_lock buffers_lock(buffers_mutex);
818
819       /* update status and timing */
820       update_status_time();
821
822       /* render */
823       bool delayed_denoise = false;
824       const bool need_denoise = render_need_denoise(delayed_denoise);
825       render(need_denoise);
826
827       /* update status and timing */
828       update_status_time();
829
830       if (!params.background)
831         need_copy_to_display_buffer = !delayed_denoise;
832
833       if (!device->error_message().empty())
834         progress.set_error(device->error_message());
835     }
836
837     device->task_wait();
838
839     {
840       thread_scoped_lock reset_lock(delayed_reset.mutex);
841       thread_scoped_lock buffers_lock(buffers_mutex);
842       thread_scoped_lock display_lock(display_mutex);
843
844       if (delayed_reset.do_reset) {
845         /* reset rendering if request from main thread */
846         delayed_reset.do_reset = false;
847         reset_(delayed_reset.params, delayed_reset.samples);
848       }
849       else if (need_copy_to_display_buffer) {
850         /* Only copy to display_buffer if we do not reset, we don't
851          * want to show the result of an incomplete sample */
852         copy_to_display_buffer(tile_manager.state.sample);
853       }
854
855       if (!device->error_message().empty())
856         progress.set_error(device->error_message());
857
858       tiles_written = update_progressive_refine(progress.get_cancel());
859     }
860
861     progress.set_update();
862   }
863
864   if (!tiles_written)
865     update_progressive_refine(true);
866 }
867
868 void Session::run()
869 {
870   if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
871     profiler.start();
872   }
873
874   /* session thread loop */
875   progress.set_status("Waiting for render to start");
876
877   /* run */
878   if (!progress.get_cancel()) {
879     /* reset number of rendered samples */
880     progress.reset_sample();
881
882     if (device_use_gl)
883       run_gpu();
884     else
885       run_cpu();
886   }
887
888   profiler.stop();
889
890   /* progress update */
891   if (progress.get_cancel())
892     progress.set_status(progress.get_cancel_message());
893   else
894     progress.set_update();
895 }
896
897 bool Session::draw(BufferParams &buffer_params, DeviceDrawParams &draw_params)
898 {
899   if (device_use_gl)
900     return draw_gpu(buffer_params, draw_params);
901   else
902     return draw_cpu(buffer_params, draw_params);
903 }
904
905 void Session::reset_(BufferParams &buffer_params, int samples)
906 {
907   if (buffers && buffer_params.modified(tile_manager.params)) {
908     gpu_draw_ready = false;
909     buffers->reset(buffer_params);
910     if (display) {
911       display->reset(buffer_params);
912     }
913   }
914
915   tile_manager.reset(buffer_params, samples);
916   stealable_tiles = 0;
917   tile_stealing_state = NOT_STEALING;
918   progress.reset_sample();
919
920   bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
921   progress.set_total_pixel_samples(show_progress ? tile_manager.state.total_pixel_samples : 0);
922
923   if (!params.background)
924     progress.set_start_time();
925   progress.set_render_start_time();
926 }
927
928 void Session::reset(BufferParams &buffer_params, int samples)
929 {
930   if (device_use_gl)
931     reset_gpu(buffer_params, samples);
932   else
933     reset_cpu(buffer_params, samples);
934 }
935
936 void Session::set_samples(int samples)
937 {
938   if (samples != params.samples) {
939     params.samples = samples;
940     tile_manager.set_samples(samples);
941
942     pause_cond.notify_all();
943   }
944 }
945
946 void Session::set_pause(bool pause_)
947 {
948   bool notify = false;
949
950   {
951     thread_scoped_lock pause_lock(pause_mutex);
952
953     if (pause != pause_) {
954       pause = pause_;
955       notify = true;
956     }
957   }
958
959   if (session_thread) {
960     if (notify) {
961       pause_cond.notify_all();
962     }
963   }
964   else if (pause_) {
965     update_status_time(pause_);
966   }
967 }
968
969 void Session::set_denoising(const DenoiseParams &denoising)
970 {
971   bool need_denoise = denoising.need_denoising_task();
972
973   /* Lock buffers so no denoising operation is triggered while the settings are changed here. */
974   thread_scoped_lock buffers_lock(buffers_mutex);
975   params.denoising = denoising;
976
977   if (!(params.device.denoisers & denoising.type)) {
978     if (need_denoise) {
979       progress.set_error("Denoiser type not supported by compute device");
980     }
981
982     params.denoising.use = false;
983     need_denoise = false;
984   }
985
986   // TODO(pmours): Query the required overlap value for denoising from the device?
987   tile_manager.slice_overlap = need_denoise && !params.background ? 64 : 0;
988
989   /* Schedule per tile denoising for final renders if we are either denoising or
990    * need prefiltered passes for the native denoiser. */
991   tile_manager.schedule_denoising = need_denoise && !buffers;
992 }
993
994 void Session::set_denoising_start_sample(int sample)
995 {
996   if (sample != params.denoising.start_sample) {
997     params.denoising.start_sample = sample;
998
999     pause_cond.notify_all();
1000   }
1001 }
1002
1003 void Session::wait()
1004 {
1005   if (session_thread) {
1006     session_thread->join();
1007     delete session_thread;
1008   }
1009
1010   session_thread = NULL;
1011 }
1012
1013 bool Session::update_scene()
1014 {
1015   thread_scoped_lock scene_lock(scene->mutex);
1016
1017   /* update camera if dimensions changed for progressive render. the camera
1018    * knows nothing about progressive or cropped rendering, it just gets the
1019    * image dimensions passed in */
1020   Camera *cam = scene->camera;
1021   int width = tile_manager.state.buffer.full_width;
1022   int height = tile_manager.state.buffer.full_height;
1023   int resolution = tile_manager.state.resolution_divider;
1024
1025   cam->set_screen_size_and_resolution(width, height, resolution);
1026
1027   /* number of samples is needed by multi jittered
1028    * sampling pattern and by baking */
1029   Integrator *integrator = scene->integrator;
1030   BakeManager *bake_manager = scene->bake_manager;
1031
1032   if (integrator->get_sampling_pattern() != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) {
1033     integrator->set_aa_samples(tile_manager.num_samples);
1034   }
1035
1036   bool kernel_switch_needed = false;
1037   if (scene->update(progress, kernel_switch_needed)) {
1038     if (kernel_switch_needed) {
1039       reset(tile_manager.params, params.samples);
1040     }
1041     return true;
1042   }
1043   return false;
1044 }
1045
1046 void Session::update_status_time(bool show_pause, bool show_done)
1047 {
1048   int progressive_sample = tile_manager.state.sample;
1049   int num_samples = tile_manager.get_num_effective_samples();
1050
1051   int tile = progress.get_rendered_tiles();
1052   int num_tiles = tile_manager.state.num_tiles;
1053
1054   /* update status */
1055   string status, substatus;
1056
1057   if (!params.progressive) {
1058     const bool is_cpu = params.device.type == DEVICE_CPU;
1059     const bool rendering_finished = (tile == num_tiles);
1060     const bool is_last_tile = (tile + 1) == num_tiles;
1061
1062     substatus = string_printf("Rendered %d/%d Tiles", tile, num_tiles);
1063
1064     if (!rendering_finished && (device->show_samples() || (is_cpu && is_last_tile))) {
1065       /* Some devices automatically support showing the sample number:
1066        * - CUDADevice
1067        * - OpenCLDevice when using the megakernel (the split kernel renders multiple
1068        *   samples at the same time, so the current sample isn't really defined)
1069        * - CPUDevice when using one thread
1070        * For these devices, the current sample is always shown.
1071        *
1072        * The other option is when the last tile is currently being rendered by the CPU.
1073        */
1074       substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
1075     }
1076     if (params.denoising.use && params.denoising.type != DENOISER_OPENIMAGEDENOISE) {
1077       substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles());
1078     }
1079     else if (params.denoising.store_passes && params.denoising.type == DENOISER_NLM) {
1080       substatus += string_printf(", Prefiltered %d tiles", progress.get_denoised_tiles());
1081     }
1082   }
1083   else if (tile_manager.num_samples == Integrator::MAX_SAMPLES)
1084     substatus = string_printf("Path Tracing Sample %d", progressive_sample + 1);
1085   else
1086     substatus = string_printf("Path Tracing Sample %d/%d", progressive_sample + 1, num_samples);
1087
1088   if (show_pause) {
1089     status = "Rendering Paused";
1090   }
1091   else if (show_done) {
1092     status = "Rendering Done";
1093     progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
1094   }
1095   else {
1096     status = substatus;
1097     substatus.clear();
1098   }
1099
1100   progress.set_status(status, substatus);
1101 }
1102
1103 bool Session::render_need_denoise(bool &delayed)
1104 {
1105   delayed = false;
1106
1107   /* Not supported yet for baking. */
1108   if (read_bake_tile_cb) {
1109     return false;
1110   }
1111
1112   /* Denoising enabled? */
1113   if (!params.denoising.need_denoising_task()) {
1114     return false;
1115   }
1116
1117   if (params.background) {
1118     /* Background render, only denoise when rendering the last sample. */
1119     return tile_manager.done();
1120   }
1121
1122   /* Viewport render. */
1123
1124   /* It can happen that denoising was already enabled, but the scene still needs an update. */
1125   if (scene->film->is_modified() || !scene->film->get_denoising_data_offset()) {
1126     return false;
1127   }
1128
1129   /* Immediately denoise when we reach the start sample or last sample. */
1130   const int num_samples_finished = tile_manager.state.sample + 1;
1131   if (num_samples_finished == params.denoising.start_sample ||
1132       num_samples_finished == params.samples) {
1133     return true;
1134   }
1135
1136   /* Do not denoise until the sample at which denoising should start is reached. */
1137   if (num_samples_finished < params.denoising.start_sample) {
1138     return false;
1139   }
1140
1141   /* Avoid excessive denoising in viewport after reaching a certain amount of samples. */
1142   delayed = (tile_manager.state.sample >= 20 &&
1143              (time_dt() - last_display_time) < params.progressive_update_timeout);
1144   return !delayed;
1145 }
1146
1147 void Session::render(bool need_denoise)
1148 {
1149   if (buffers && tile_manager.state.sample == tile_manager.range_start_sample) {
1150     /* Clear buffers. */
1151     buffers->zero();
1152   }
1153
1154   if (tile_manager.state.buffer.width == 0 || tile_manager.state.buffer.height == 0) {
1155     return; /* Avoid empty launches. */
1156   }
1157
1158   /* Add path trace task. */
1159   DeviceTask task(DeviceTask::RENDER);
1160
1161   task.acquire_tile = function_bind(&Session::acquire_tile, this, _2, _1, _3);
1162   task.release_tile = function_bind(&Session::release_tile, this, _1, need_denoise);
1163   task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2);
1164   task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2);
1165   task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
1166   task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
1167   task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
1168   task.get_tile_stolen = function_bind(&Session::get_tile_stolen, this);
1169   task.need_finish_queue = params.progressive_refine;
1170   task.integrator_branched = scene->integrator->get_method() == Integrator::BRANCHED_PATH;
1171
1172   task.adaptive_sampling.use = (scene->integrator->get_sampling_pattern() ==
1173                                 SAMPLING_PATTERN_PMJ) &&
1174                                scene->dscene.data.film.pass_adaptive_aux_buffer;
1175   task.adaptive_sampling.min_samples = scene->dscene.data.integrator.adaptive_min_samples;
1176   task.adaptive_sampling.adaptive_step = scene->dscene.data.integrator.adaptive_step;
1177
1178   /* Acquire render tiles by default. */
1179   task.tile_types = RenderTile::PATH_TRACE;
1180
1181   if (need_denoise) {
1182     task.denoising = params.denoising;
1183
1184     task.pass_stride = scene->film->get_pass_stride();
1185     task.target_pass_stride = task.pass_stride;
1186     task.pass_denoising_data = scene->film->get_denoising_data_offset();
1187     task.pass_denoising_clean = scene->film->get_denoising_clean_offset();
1188
1189     task.denoising_from_render = true;
1190
1191     if (tile_manager.schedule_denoising) {
1192       /* Acquire denoising tiles during rendering. */
1193       task.tile_types |= RenderTile::DENOISE;
1194     }
1195     else {
1196       assert(buffers);
1197
1198       /* Schedule rendering and wait for it to finish. */
1199       device->task_add(task);
1200       device->task_wait();
1201
1202       /* Then run denoising on the whole image at once. */
1203       task.type = DeviceTask::DENOISE_BUFFER;
1204       task.x = tile_manager.state.buffer.full_x;
1205       task.y = tile_manager.state.buffer.full_y;
1206       task.w = tile_manager.state.buffer.width;
1207       task.h = tile_manager.state.buffer.height;
1208       task.buffer = buffers->buffer.device_pointer;
1209       task.sample = tile_manager.state.sample;
1210       task.num_samples = tile_manager.state.num_samples;
1211       tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
1212       task.buffers = buffers;
1213     }
1214   }
1215
1216   device->task_add(task);
1217 }
1218
1219 void Session::copy_to_display_buffer(int sample)
1220 {
1221   /* add film conversion task */
1222   DeviceTask task(DeviceTask::FILM_CONVERT);
1223
1224   task.x = tile_manager.state.buffer.full_x;
1225   task.y = tile_manager.state.buffer.full_y;
1226   task.w = tile_manager.state.buffer.width;
1227   task.h = tile_manager.state.buffer.height;
1228   task.rgba_byte = display->rgba_byte.device_pointer;
1229   task.rgba_half = display->rgba_half.device_pointer;
1230   task.buffer = buffers->buffer.device_pointer;
1231   task.sample = sample;
1232   tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
1233
1234   if (task.w > 0 && task.h > 0) {
1235     device->task_add(task);
1236     device->task_wait();
1237
1238     /* set display to new size */
1239     display->draw_set(task.w, task.h);
1240
1241     last_display_time = time_dt();
1242   }
1243
1244   display_outdated = false;
1245 }
1246
1247 bool Session::update_progressive_refine(bool cancel)
1248 {
1249   int sample = tile_manager.state.sample + 1;
1250   bool write = sample == tile_manager.num_samples || cancel;
1251
1252   double current_time = time_dt();
1253
1254   if (current_time - last_update_time < params.progressive_update_timeout) {
1255     /* if last sample was processed, we need to write buffers anyway  */
1256     if (!write && sample != 1)
1257       return false;
1258   }
1259
1260   if (params.progressive_refine) {
1261     foreach (Tile &tile, tile_manager.state.tiles) {
1262       if (!tile.buffers) {
1263         continue;
1264       }
1265
1266       RenderTile rtile;
1267       rtile.x = tile_manager.state.buffer.full_x + tile.x;
1268       rtile.y = tile_manager.state.buffer.full_y + tile.y;
1269       rtile.w = tile.w;
1270       rtile.h = tile.h;
1271       rtile.sample = sample;
1272       rtile.buffers = tile.buffers;
1273
1274       if (write) {
1275         if (write_render_tile_cb)
1276           write_render_tile_cb(rtile);
1277       }
1278       else {
1279         if (update_render_tile_cb)
1280           update_render_tile_cb(rtile, true);
1281       }
1282     }
1283   }
1284
1285   last_update_time = current_time;
1286
1287   return write;
1288 }
1289
1290 void Session::device_free()
1291 {
1292   scene->device_free();
1293
1294   tile_manager.device_free();
1295
1296   /* used from background render only, so no need to
1297    * re-create render/display buffers here
1298    */
1299 }
1300
1301 void Session::collect_statistics(RenderStats *render_stats)
1302 {
1303   scene->collect_statistics(render_stats);
1304   if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
1305     render_stats->collect_profiling(scene, profiler);
1306   }
1307 }
1308
1309 CCL_NAMESPACE_END