Merge branch 'blender2.7'
[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 <string.h>
18 #include <limits.h>
19
20 #include "render/buffers.h"
21 #include "render/camera.h"
22 #include "device/device.h"
23 #include "render/graph.h"
24 #include "render/integrator.h"
25 #include "render/light.h"
26 #include "render/mesh.h"
27 #include "render/object.h"
28 #include "render/scene.h"
29 #include "render/session.h"
30 #include "render/bake.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, params.samples, params.tile_size, params.start_resolution,
49        params.background == false || params.progressive_refine, params.background, params.tile_order,
50        max(params.device.multi_devices.size(), 1), params.pixel_size),
51   stats(),
52   profiler()
53 {
54         device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
55
56         TaskScheduler::init(params.threads);
57
58         device = Device::create(params.device, stats, profiler, params.background);
59
60         if(params.background && !params.write_render_cb) {
61                 buffers = NULL;
62                 display = NULL;
63         }
64         else {
65                 buffers = new RenderBuffers(device);
66                 display = new DisplayBuffer(device, params.display_buffer_linear);
67         }
68
69         session_thread = NULL;
70         scene = NULL;
71
72         reset_time = 0.0;
73         last_update_time = 0.0;
74
75         delayed_reset.do_reset = false;
76         delayed_reset.samples = 0;
77
78         display_outdated = false;
79         gpu_draw_ready = false;
80         gpu_need_tonemap = false;
81         pause = false;
82         kernels_loaded = false;
83
84         /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
85         max_closure_global = 1;
86 }
87
88 Session::~Session()
89 {
90         if(session_thread) {
91                 /* wait for session thread to end */
92                 progress.set_cancel("Exiting");
93
94                 gpu_need_tonemap = false;
95                 gpu_need_tonemap_cond.notify_all();
96
97                 {
98                         thread_scoped_lock pause_lock(pause_mutex);
99                         pause = false;
100                 }
101                 pause_cond.notify_all();
102
103                 wait();
104         }
105
106         if(params.write_render_cb) {
107                 /* tonemap and write out image if requested */
108                 delete display;
109
110                 display = new DisplayBuffer(device, false);
111                 display->reset(buffers->params);
112                 tonemap(params.samples);
113
114                 int w = display->draw_width;
115                 int h = display->draw_height;
116                 uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h);
117                 params.write_render_cb((uchar*)pixels, w, h, 4);
118         }
119
120         /* clean up */
121         tile_manager.device_free();
122
123         delete buffers;
124         delete display;
125         delete scene;
126         delete device;
127
128         TaskScheduler::exit();
129 }
130
131 void Session::start()
132 {
133         if (!session_thread) {
134                 session_thread = new thread(function_bind(&Session::run, this));
135         }
136 }
137
138 bool Session::ready_to_reset()
139 {
140         double dt = time_dt() - reset_time;
141
142         if(!display_outdated)
143                 return (dt > params.reset_timeout);
144         else
145                 return (dt > params.cancel_timeout);
146 }
147
148 /* GPU Session */
149
150 void Session::reset_gpu(BufferParams& buffer_params, int samples)
151 {
152         thread_scoped_lock pause_lock(pause_mutex);
153
154         /* block for buffer access and reset immediately. we can't do this
155          * in the thread, because we need to allocate an OpenGL buffer, and
156          * that only works in the main thread */
157         thread_scoped_lock display_lock(display_mutex);
158         thread_scoped_lock buffers_lock(buffers_mutex);
159
160         display_outdated = true;
161         reset_time = time_dt();
162
163         reset_(buffer_params, samples);
164
165         gpu_need_tonemap = false;
166         gpu_need_tonemap_cond.notify_all();
167
168         pause_cond.notify_all();
169 }
170
171 bool Session::draw_gpu(BufferParams& buffer_params, DeviceDrawParams& draw_params)
172 {
173         /* block for buffer access */
174         thread_scoped_lock display_lock(display_mutex);
175
176         /* first check we already rendered something */
177         if(gpu_draw_ready) {
178                 /* then verify the buffers have the expected size, so we don't
179                  * draw previous results in a resized window */
180                 if(!buffer_params.modified(display->params)) {
181                         /* for CUDA we need to do tonemapping still, since we can
182                          * only access GL buffers from the main thread */
183                         if(gpu_need_tonemap) {
184                                 thread_scoped_lock buffers_lock(buffers_mutex);
185                                 tonemap(tile_manager.state.sample);
186                                 gpu_need_tonemap = false;
187                                 gpu_need_tonemap_cond.notify_all();
188                         }
189
190                         display->draw(device, draw_params);
191
192                         if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
193                                 return false;
194
195                         return true;
196                 }
197         }
198
199         return false;
200 }
201
202 void Session::run_gpu()
203 {
204         bool tiles_written = false;
205
206         reset_time = time_dt();
207         last_update_time = time_dt();
208
209         progress.set_render_start_time();
210
211         while(!progress.get_cancel()) {
212                 /* advance to next tile */
213                 bool no_tiles = !tile_manager.next();
214
215                 DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
216                 if (no_tiles) {
217                         kernel_state = device->get_active_kernel_switch_state();
218                 }
219
220                 if(params.background) {
221                         /* if no work left and in background mode, we can stop immediately */
222                         if(no_tiles) {
223                                 progress.set_status("Finished");
224                                 break;
225                         }
226                 }
227
228                 /* Don't go in pause mode when image was rendered with preview kernels
229                  * When feature kernels become available the session will be resetted. */
230                 else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
231                         time_sleep(0.1);
232                 }
233                 else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
234                         reset_gpu(tile_manager.params, params.samples);
235                 }
236
237                 else {
238                         /* if in interactive mode, and we are either paused or done for now,
239                          * wait for pause condition notify to wake up again */
240                         thread_scoped_lock pause_lock(pause_mutex);
241
242                         if(!pause && !tile_manager.done()) {
243                                 /* reset could have happened after no_tiles was set, before this lock.
244                                  * in this case we shall not wait for pause condition
245                                  */
246                         }
247                         else if(pause || no_tiles) {
248                                 update_status_time(pause, no_tiles);
249
250                                 while(1) {
251                                         scoped_timer pause_timer;
252                                         pause_cond.wait(pause_lock);
253                                         if(pause) {
254                                                 progress.add_skip_time(pause_timer, params.background);
255                                         }
256
257                                         update_status_time(pause, no_tiles);
258                                         progress.set_update();
259
260                                         if(!pause)
261                                                 break;
262                                 }
263                         }
264
265                         if(progress.get_cancel())
266                                 break;
267                 }
268
269                 if(!no_tiles) {
270                         /* update scene */
271                         scoped_timer update_timer;
272                         if(update_scene()) {
273                                 profiler.reset(scene->shaders.size(), scene->objects.size());
274                         }
275                         progress.add_skip_time(update_timer, params.background);
276
277                         if(!device->error_message().empty())
278                                 progress.set_error(device->error_message());
279
280                         if(progress.get_cancel())
281                                 break;
282                 }
283
284                 if(!no_tiles) {
285                         /* buffers mutex is locked entirely while rendering each
286                          * sample, and released/reacquired on each iteration to allow
287                          * reset and draw in between */
288                         thread_scoped_lock buffers_lock(buffers_mutex);
289
290                         /* update status and timing */
291                         update_status_time();
292
293                         /* render */
294                         render();
295
296                         device->task_wait();
297
298                         if(!device->error_message().empty())
299                                 progress.set_cancel(device->error_message());
300
301                         /* update status and timing */
302                         update_status_time();
303
304                         gpu_need_tonemap = true;
305                         gpu_draw_ready = true;
306                         progress.set_update();
307
308                         /* wait for tonemap */
309                         if(!params.background) {
310                                 while(gpu_need_tonemap) {
311                                         if(progress.get_cancel())
312                                                 break;
313
314                                         gpu_need_tonemap_cond.wait(buffers_lock);
315                                 }
316                         }
317
318                         if(!device->error_message().empty())
319                                 progress.set_error(device->error_message());
320
321                         tiles_written = update_progressive_refine(progress.get_cancel());
322
323                         if(progress.get_cancel())
324                                 break;
325                 }
326         }
327
328         if(!tiles_written)
329                 update_progressive_refine(true);
330 }
331
332 /* CPU Session */
333
334 void Session::reset_cpu(BufferParams& buffer_params, int samples)
335 {
336         thread_scoped_lock reset_lock(delayed_reset.mutex);
337         thread_scoped_lock pause_lock(pause_mutex);
338
339         display_outdated = true;
340         reset_time = time_dt();
341
342         delayed_reset.params = buffer_params;
343         delayed_reset.samples = samples;
344         delayed_reset.do_reset = true;
345         device->task_cancel();
346
347         pause_cond.notify_all();
348 }
349
350 bool Session::draw_cpu(BufferParams& buffer_params, DeviceDrawParams& draw_params)
351 {
352         thread_scoped_lock display_lock(display_mutex);
353
354         /* first check we already rendered something */
355         if(display->draw_ready()) {
356                 /* then verify the buffers have the expected size, so we don't
357                  * draw previous results in a resized window */
358                 if(!buffer_params.modified(display->params)) {
359                         display->draw(device, draw_params);
360
361                         if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
362                                 return false;
363
364                         return true;
365                 }
366         }
367
368         return false;
369 }
370
371 bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
372 {
373         if(progress.get_cancel()) {
374                 if(params.progressive_refine == false) {
375                         /* for progressive refine current sample should be finished for all tiles */
376                         return false;
377                 }
378         }
379
380         thread_scoped_lock tile_lock(tile_mutex);
381
382         /* get next tile from manager */
383         Tile *tile;
384         int device_num = device->device_number(tile_device);
385
386         if(!tile_manager.next_tile(tile, device_num))
387                 return false;
388
389         /* fill render tile */
390         rtile.x = tile_manager.state.buffer.full_x + tile->x;
391         rtile.y = tile_manager.state.buffer.full_y + tile->y;
392         rtile.w = tile->w;
393         rtile.h = tile->h;
394         rtile.start_sample = tile_manager.state.sample;
395         rtile.num_samples = tile_manager.state.num_samples;
396         rtile.resolution = tile_manager.state.resolution_divider;
397         rtile.tile_index = tile->index;
398         rtile.task = (tile->state == Tile::DENOISE)? RenderTile::DENOISE: RenderTile::PATH_TRACE;
399
400         tile_lock.unlock();
401
402         /* in case of a permanent buffer, return it, otherwise we will allocate
403          * a new temporary buffer */
404         if(buffers) {
405                 tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
406
407                 rtile.buffer = buffers->buffer.device_pointer;
408                 rtile.buffers = buffers;
409
410                 device->map_tile(tile_device, rtile);
411
412                 return true;
413         }
414
415         if(tile->buffers == NULL) {
416                 /* fill buffer parameters */
417                 BufferParams buffer_params = tile_manager.params;
418                 buffer_params.full_x = rtile.x;
419                 buffer_params.full_y = rtile.y;
420                 buffer_params.width = rtile.w;
421                 buffer_params.height = rtile.h;
422
423                 /* allocate buffers */
424                 tile->buffers = new RenderBuffers(tile_device);
425                 tile->buffers->reset(buffer_params);
426         }
427
428         tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
429
430         rtile.buffer = tile->buffers->buffer.device_pointer;
431         rtile.buffers = tile->buffers;
432         rtile.sample = tile_manager.state.sample;
433
434         /* this will tag tile as IN PROGRESS in blender-side render pipeline,
435          * which is needed to highlight currently rendering tile before first
436          * sample was processed for it
437          */
438         update_tile_sample(rtile);
439
440         return true;
441 }
442
443 void Session::update_tile_sample(RenderTile& rtile)
444 {
445         thread_scoped_lock tile_lock(tile_mutex);
446
447         if(update_render_tile_cb) {
448                 if(params.progressive_refine == false) {
449                         /* todo: optimize this by making it thread safe and removing lock */
450
451                         update_render_tile_cb(rtile, true);
452                 }
453         }
454
455         update_status_time();
456 }
457
458 void Session::release_tile(RenderTile& rtile)
459 {
460         thread_scoped_lock tile_lock(tile_mutex);
461
462         progress.add_finished_tile(rtile.task == RenderTile::DENOISE);
463
464         bool delete_tile;
465
466         if(tile_manager.finish_tile(rtile.tile_index, delete_tile)) {
467                 if(write_render_tile_cb && params.progressive_refine == false) {
468                         write_render_tile_cb(rtile);
469                 }
470
471                 if(delete_tile) {
472                         delete rtile.buffers;
473                         tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
474                 }
475         }
476         else {
477                 if(update_render_tile_cb && params.progressive_refine == false) {
478                         update_render_tile_cb(rtile, false);
479                 }
480         }
481
482         update_status_time();
483 }
484
485 void Session::map_neighbor_tiles(RenderTile *tiles, Device *tile_device)
486 {
487         thread_scoped_lock tile_lock(tile_mutex);
488
489         int center_idx = tiles[4].tile_index;
490         assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE);
491         BufferParams buffer_params = tile_manager.params;
492         int4 image_region = make_int4(buffer_params.full_x, buffer_params.full_y,
493                                       buffer_params.full_x + buffer_params.width, buffer_params.full_y + buffer_params.height);
494
495         for(int dy = -1, i = 0; dy <= 1; dy++) {
496                 for(int dx = -1; dx <= 1; dx++, i++) {
497                         int px = tiles[4].x + dx*params.tile_size.x;
498                         int py = tiles[4].y + dy*params.tile_size.y;
499                         if(px >= image_region.x && py >= image_region.y &&
500                            px <  image_region.z && py <  image_region.w) {
501                                 int tile_index = center_idx + dy*tile_manager.state.tile_stride + dx;
502                                 Tile *tile = &tile_manager.state.tiles[tile_index];
503                                 assert(tile->buffers);
504
505                                 tiles[i].buffer = tile->buffers->buffer.device_pointer;
506                                 tiles[i].x = tile_manager.state.buffer.full_x + tile->x;
507                                 tiles[i].y = tile_manager.state.buffer.full_y + tile->y;
508                                 tiles[i].w = tile->w;
509                                 tiles[i].h = tile->h;
510                                 tiles[i].buffers = tile->buffers;
511
512                                 tile->buffers->params.get_offset_stride(tiles[i].offset, tiles[i].stride);
513                         }
514                         else {
515                                 tiles[i].buffer = (device_ptr)NULL;
516                                 tiles[i].buffers = NULL;
517                                 tiles[i].x = clamp(px, image_region.x, image_region.z);
518                                 tiles[i].y = clamp(py, image_region.y, image_region.w);
519                                 tiles[i].w = tiles[i].h = 0;
520                         }
521                 }
522         }
523
524         assert(tiles[4].buffers);
525         device->map_neighbor_tiles(tile_device, tiles);
526
527         /* The denoised result is written back to the original tile. */
528         tiles[9] = tiles[4];
529 }
530
531 void Session::unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device)
532 {
533         thread_scoped_lock tile_lock(tile_mutex);
534         device->unmap_neighbor_tiles(tile_device, tiles);
535 }
536
537 void Session::run_cpu()
538 {
539         bool tiles_written = false;
540
541         last_update_time = time_dt();
542
543         {
544                 /* reset once to start */
545                 thread_scoped_lock reset_lock(delayed_reset.mutex);
546                 thread_scoped_lock buffers_lock(buffers_mutex);
547                 thread_scoped_lock display_lock(display_mutex);
548
549                 reset_(delayed_reset.params, delayed_reset.samples);
550                 delayed_reset.do_reset = false;
551         }
552
553         while(!progress.get_cancel()) {
554                 /* advance to next tile */
555                 bool no_tiles = !tile_manager.next();
556                 bool need_tonemap = false;
557
558                 DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
559                 if (no_tiles) {
560                         kernel_state = device->get_active_kernel_switch_state();
561                 }
562
563                 if(params.background) {
564                         /* if no work left and in background mode, we can stop immediately */
565                         if(no_tiles) {
566                                 progress.set_status("Finished");
567                                 break;
568                         }
569                 }
570
571                 /* Don't go in pause mode when preview kernels are used
572                  * When feature kernels become available the session will be resetted. */
573                 else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
574                         time_sleep(0.1);
575                 }
576                 else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
577                         reset_cpu(tile_manager.params, params.samples);
578                 }
579
580                 else {
581                         /* if in interactive mode, and we are either paused or done for now,
582                          * wait for pause condition notify to wake up again */
583                         thread_scoped_lock pause_lock(pause_mutex);
584
585                         if(!pause && delayed_reset.do_reset) {
586                                 /* reset once to start */
587                                 thread_scoped_lock reset_lock(delayed_reset.mutex);
588                                 thread_scoped_lock buffers_lock(buffers_mutex);
589                                 thread_scoped_lock display_lock(display_mutex);
590
591                                 reset_(delayed_reset.params, delayed_reset.samples);
592                                 delayed_reset.do_reset = false;
593                         }
594                         else if(pause || no_tiles) {
595                                 update_status_time(pause, no_tiles);
596
597                                 while(1) {
598                                         scoped_timer pause_timer;
599                                         pause_cond.wait(pause_lock);
600                                         if(pause) {
601                                                 progress.add_skip_time(pause_timer, params.background);
602                                         }
603
604                                         update_status_time(pause, no_tiles);
605                                         progress.set_update();
606
607                                         if(!pause)
608                                                 break;
609                                 }
610                         }
611
612                         if(progress.get_cancel())
613                                 break;
614                 }
615
616                 if(!no_tiles) {
617                         /* buffers mutex is locked entirely while rendering each
618                          * sample, and released/reacquired on each iteration to allow
619                          * reset and draw in between */
620                         thread_scoped_lock buffers_lock(buffers_mutex);
621
622                         /* update scene */
623                         scoped_timer update_timer;
624                         if(update_scene()) {
625                                 profiler.reset(scene->shaders.size(), scene->objects.size());
626                         }
627                         progress.add_skip_time(update_timer, params.background);
628
629                         if(!device->error_message().empty())
630                                 progress.set_error(device->error_message());
631
632                         if(progress.get_cancel())
633                                 break;
634
635                         /* update status and timing */
636                         update_status_time();
637
638                         /* render */
639                         render();
640
641                         /* update status and timing */
642                         update_status_time();
643
644                         if(!params.background)
645                                 need_tonemap = true;
646
647                         if(!device->error_message().empty())
648                                 progress.set_error(device->error_message());
649                 }
650
651                 device->task_wait();
652
653                 {
654                         thread_scoped_lock reset_lock(delayed_reset.mutex);
655                         thread_scoped_lock buffers_lock(buffers_mutex);
656                         thread_scoped_lock display_lock(display_mutex);
657
658                         if(delayed_reset.do_reset) {
659                                 /* reset rendering if request from main thread */
660                                 delayed_reset.do_reset = false;
661                                 reset_(delayed_reset.params, delayed_reset.samples);
662                         }
663                         else if(need_tonemap) {
664                                 /* tonemap only if we do not reset, we don't we don't
665                                  * want to show the result of an incomplete sample */
666                                 tonemap(tile_manager.state.sample);
667                         }
668
669                         if(!device->error_message().empty())
670                                 progress.set_error(device->error_message());
671
672                         tiles_written = update_progressive_refine(progress.get_cancel());
673                 }
674
675                 progress.set_update();
676         }
677
678         if(!tiles_written)
679                 update_progressive_refine(true);
680 }
681
682 DeviceRequestedFeatures Session::get_requested_device_features()
683 {
684         /* TODO(sergey): Consider moving this to the Scene level. */
685         DeviceRequestedFeatures requested_features;
686         requested_features.experimental = params.experimental;
687
688         scene->shader_manager->get_requested_features(
689                 scene,
690                 &requested_features);
691
692         /* This features are not being tweaked as often as shaders,
693          * so could be done selective magic for the viewport as well.
694          */
695         bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR;
696         requested_features.use_hair = false;
697         requested_features.use_object_motion = false;
698         requested_features.use_camera_motion = use_motion && scene->camera->use_motion();
699         foreach(Object *object, scene->objects) {
700                 Mesh *mesh = object->mesh;
701                 if(mesh->num_curves()) {
702                         requested_features.use_hair = true;
703                 }
704                 if (use_motion) {
705                         requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur;
706                         requested_features.use_camera_motion |= mesh->use_motion_blur;
707                 }
708 #ifdef WITH_OPENSUBDIV
709                 if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
710                         requested_features.use_patch_evaluation = true;
711                 }
712 #endif
713                 if(object->is_shadow_catcher) {
714                         requested_features.use_shadow_tricks = true;
715                 }
716                 requested_features.use_true_displacement |= mesh->has_true_displacement();
717         }
718
719         requested_features.use_background_light = scene->light_manager->has_background_light(scene);
720
721         BakeManager *bake_manager = scene->bake_manager;
722         requested_features.use_baking = bake_manager->get_baking();
723         requested_features.use_integrator_branched = (scene->integrator->method == Integrator::BRANCHED_PATH);
724         if(params.run_denoising) {
725                 requested_features.use_denoising = true;
726                 requested_features.use_shadow_tricks = true;
727         }
728
729         return requested_features;
730 }
731
732 bool Session::load_kernels(bool lock_scene)
733 {
734         thread_scoped_lock scene_lock;
735         if(lock_scene) {
736                 scene_lock = thread_scoped_lock(scene->mutex);
737         }
738
739         DeviceRequestedFeatures requested_features = get_requested_device_features();
740
741         if(!kernels_loaded || loaded_kernel_features.modified(requested_features)) {
742                 progress.set_status("Loading render kernels (may take a few minutes the first time)");
743
744                 scoped_timer timer;
745
746                 VLOG(2) << "Requested features:\n" << requested_features;
747                 if(!device->load_kernels(requested_features)) {
748                         string message = device->error_message();
749                         if(message.empty())
750                                 message = "Failed loading render kernel, see console for errors";
751
752                         progress.set_error(message);
753                         progress.set_status("Error", message);
754                         progress.set_update();
755                         return false;
756                 }
757
758                 progress.add_skip_time(timer, false);
759                 VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
760
761                 kernels_loaded = true;
762                 loaded_kernel_features = requested_features;
763                 return true;
764         }
765         return false;
766 }
767
768 void Session::run()
769 {
770         if(params.use_profiling && (params.device.type == DEVICE_CPU)) {
771                 profiler.start();
772         }
773
774         /* session thread loop */
775         progress.set_status("Waiting for render to start");
776
777         /* run */
778         if(!progress.get_cancel()) {
779                 /* reset number of rendered samples */
780                 progress.reset_sample();
781
782                 if(device_use_gl)
783                         run_gpu();
784                 else
785                         run_cpu();
786         }
787
788         profiler.stop();
789
790         /* progress update */
791         if(progress.get_cancel())
792                 progress.set_status("Cancel", progress.get_cancel_message());
793         else
794                 progress.set_update();
795 }
796
797 bool Session::draw(BufferParams& buffer_params, DeviceDrawParams &draw_params)
798 {
799         if(device_use_gl)
800                 return draw_gpu(buffer_params, draw_params);
801         else
802                 return draw_cpu(buffer_params, draw_params);
803 }
804
805 void Session::reset_(BufferParams& buffer_params, int samples)
806 {
807         if(buffers && buffer_params.modified(tile_manager.params)) {
808                 gpu_draw_ready = false;
809                 buffers->reset(buffer_params);
810                 if(display) {
811                         display->reset(buffer_params);
812                 }
813         }
814
815         tile_manager.reset(buffer_params, samples);
816         progress.reset_sample();
817
818         bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
819         progress.set_total_pixel_samples(show_progress? tile_manager.state.total_pixel_samples : 0);
820
821         if(!params.background)
822                 progress.set_start_time();
823         progress.set_render_start_time();
824 }
825
826 void Session::reset(BufferParams& buffer_params, int samples)
827 {
828         if(device_use_gl)
829                 reset_gpu(buffer_params, samples);
830         else
831                 reset_cpu(buffer_params, samples);
832 }
833
834 void Session::set_samples(int samples)
835 {
836         if(samples != params.samples) {
837                 params.samples = samples;
838                 tile_manager.set_samples(samples);
839
840                 {
841                         thread_scoped_lock pause_lock(pause_mutex);
842                 }
843                 pause_cond.notify_all();
844         }
845 }
846
847 void Session::set_pause(bool pause_)
848 {
849         bool notify = false;
850
851         {
852                 thread_scoped_lock pause_lock(pause_mutex);
853
854                 if(pause != pause_) {
855                         pause = pause_;
856                         notify = true;
857                 }
858         }
859
860         if(notify)
861                 pause_cond.notify_all();
862 }
863
864 void Session::wait()
865 {
866         if (session_thread) {
867                 session_thread->join();
868                 delete session_thread;
869         }
870
871         session_thread = NULL;
872 }
873
874 bool Session::update_scene()
875 {
876         thread_scoped_lock scene_lock(scene->mutex);
877
878         /* update camera if dimensions changed for progressive render. the camera
879          * knows nothing about progressive or cropped rendering, it just gets the
880          * image dimensions passed in */
881         Camera *cam = scene->camera;
882         int width = tile_manager.state.buffer.full_width;
883         int height = tile_manager.state.buffer.full_height;
884         int resolution = tile_manager.state.resolution_divider;
885
886         if(width != cam->width || height != cam->height) {
887                 cam->width = width;
888                 cam->height = height;
889                 cam->resolution = resolution;
890                 cam->tag_update();
891         }
892
893         /* number of samples is needed by multi jittered
894          * sampling pattern and by baking */
895         Integrator *integrator = scene->integrator;
896         BakeManager *bake_manager = scene->bake_manager;
897
898         if(integrator->sampling_pattern == SAMPLING_PATTERN_CMJ ||
899            bake_manager->get_baking())
900         {
901                 int aa_samples = tile_manager.num_samples;
902
903                 if(aa_samples != integrator->aa_samples) {
904                         integrator->aa_samples = aa_samples;
905                         integrator->tag_update(scene);
906                 }
907         }
908
909         /* update scene */
910         if(scene->need_update()) {
911                 bool new_kernels_needed = load_kernels(false);
912
913                 /* Update max_closures. */
914                 KernelIntegrator *kintegrator = &scene->dscene.data.integrator;
915                 if(params.background) {
916                         kintegrator->max_closures = get_max_closure_count();
917                 }
918                 else {
919                         /* Currently viewport render is faster with higher max_closures, needs investigating. */
920                         kintegrator->max_closures = MAX_CLOSURE;
921                 }
922
923                 progress.set_status("Updating Scene");
924                 MEM_GUARDED_CALL(&progress, scene->device_update, device, progress);
925
926                 DeviceKernelStatus kernel_switch_status = device->get_active_kernel_switch_state();
927                 bool kernel_switch_needed = kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE ||
928                                             kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
929                 if (kernel_switch_status == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
930                         progress.set_kernel_status("Compiling render kernels");
931                 }
932                 if (new_kernels_needed || kernel_switch_needed) {
933                         progress.set_kernel_status("Compiling render kernels");
934                         device->wait_for_availability(loaded_kernel_features);
935                         progress.set_kernel_status("");
936                 }
937
938                 if (kernel_switch_needed) {
939                         reset(tile_manager.params, params.samples);
940                 }
941                 return true;
942         }
943         return false;
944 }
945
946 void Session::update_status_time(bool show_pause, bool show_done)
947 {
948         int progressive_sample = tile_manager.state.sample;
949         int num_samples = tile_manager.get_num_effective_samples();
950
951         int tile = progress.get_rendered_tiles();
952         int num_tiles = tile_manager.state.num_tiles;
953
954         /* update status */
955         string status, substatus;
956
957         if(!params.progressive) {
958                 const bool is_cpu = params.device.type == DEVICE_CPU;
959                 const bool rendering_finished = (tile == num_tiles);
960                 const bool is_last_tile = (tile + 1) == num_tiles;
961
962                 substatus = string_printf("Rendered %d/%d Tiles", tile, num_tiles);
963
964                 if(!rendering_finished && (device->show_samples() || (is_cpu && is_last_tile))) {
965                         /* Some devices automatically support showing the sample number:
966                          * - CUDADevice
967                          * - OpenCLDevice when using the megakernel (the split kernel renders multiple
968                          *   samples at the same time, so the current sample isn't really defined)
969                          * - CPUDevice when using one thread
970                          * For these devices, the current sample is always shown.
971                          *
972                          * The other option is when the last tile is currently being rendered by the CPU.
973                          */
974                         substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
975                 }
976                 if(params.full_denoising) {
977                         substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles());
978                 }
979                 else if(params.run_denoising) {
980                         substatus += string_printf(", Prefiltered %d tiles", progress.get_denoised_tiles());
981                 }
982         }
983         else if(tile_manager.num_samples == INT_MAX)
984                 substatus = string_printf("Path Tracing Sample %d", progressive_sample+1);
985         else
986                 substatus = string_printf("Path Tracing Sample %d/%d",
987                                           progressive_sample+1,
988                                           num_samples);
989
990         if(show_pause) {
991                 status = "Rendering Paused";
992         }
993         else if(show_done) {
994                 status = "Rendering Done";
995                 progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
996         }
997         else {
998                 status = substatus;
999                 substatus.clear();
1000         }
1001
1002         progress.set_status(status, substatus);
1003 }
1004
1005 void Session::render()
1006 {
1007         /* Clear buffers. */
1008         if(buffers && tile_manager.state.sample == tile_manager.range_start_sample) {
1009                 buffers->zero();
1010         }
1011
1012         /* Add path trace task. */
1013         DeviceTask task(DeviceTask::RENDER);
1014
1015         task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
1016         task.release_tile = function_bind(&Session::release_tile, this, _1);
1017         task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2);
1018         task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2);
1019         task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
1020         task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
1021         task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
1022         task.need_finish_queue = params.progressive_refine;
1023         task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
1024         task.requested_tile_size = params.tile_size;
1025         task.passes_size = tile_manager.params.get_passes_size();
1026
1027         if(params.run_denoising) {
1028                 task.denoising = params.denoising;
1029
1030                 assert(!scene->film->need_update);
1031                 task.pass_stride = scene->film->pass_stride;
1032                 task.target_pass_stride = task.pass_stride;
1033                 task.pass_denoising_data = scene->film->denoising_data_offset;
1034                 task.pass_denoising_clean = scene->film->denoising_clean_offset;
1035
1036                 task.denoising_from_render = true;
1037                 task.denoising_do_filter = params.full_denoising;
1038                 task.denoising_write_passes = params.write_denoising_passes;
1039         }
1040
1041         device->task_add(task);
1042 }
1043
1044 void Session::tonemap(int sample)
1045 {
1046         /* add tonemap task */
1047         DeviceTask task(DeviceTask::FILM_CONVERT);
1048
1049         task.x = tile_manager.state.buffer.full_x;
1050         task.y = tile_manager.state.buffer.full_y;
1051         task.w = tile_manager.state.buffer.width;
1052         task.h = tile_manager.state.buffer.height;
1053         task.rgba_byte = display->rgba_byte.device_pointer;
1054         task.rgba_half = display->rgba_half.device_pointer;
1055         task.buffer = buffers->buffer.device_pointer;
1056         task.sample = sample;
1057         tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
1058
1059         if(task.w > 0 && task.h > 0) {
1060                 device->task_add(task);
1061                 device->task_wait();
1062
1063                 /* set display to new size */
1064                 display->draw_set(task.w, task.h);
1065         }
1066
1067         display_outdated = false;
1068 }
1069
1070 bool Session::update_progressive_refine(bool cancel)
1071 {
1072         int sample = tile_manager.state.sample + 1;
1073         bool write = sample == tile_manager.num_samples || cancel;
1074
1075         double current_time = time_dt();
1076
1077         if(current_time - last_update_time < params.progressive_update_timeout) {
1078                 /* if last sample was processed, we need to write buffers anyway  */
1079                 if(!write && sample != 1)
1080                         return false;
1081         }
1082
1083         if(params.progressive_refine) {
1084                 foreach(Tile& tile, tile_manager.state.tiles) {
1085                         if(!tile.buffers) {
1086                                 continue;
1087                         }
1088
1089                         RenderTile rtile;
1090                         rtile.x = tile_manager.state.buffer.full_x + tile.x;
1091                         rtile.y = tile_manager.state.buffer.full_y + tile.y;
1092                         rtile.w = tile.w;
1093                         rtile.h = tile.h;
1094                         rtile.sample = sample;
1095                         rtile.buffers = tile.buffers;
1096
1097                         if(write) {
1098                                 if(write_render_tile_cb)
1099                                         write_render_tile_cb(rtile);
1100                         }
1101                         else {
1102                                 if(update_render_tile_cb)
1103                                         update_render_tile_cb(rtile, true);
1104                         }
1105                 }
1106         }
1107
1108         last_update_time = current_time;
1109
1110         return write;
1111 }
1112
1113 void Session::device_free()
1114 {
1115         scene->device_free();
1116
1117         tile_manager.device_free();
1118
1119         /* used from background render only, so no need to
1120          * re-create render/display buffers here
1121          */
1122 }
1123
1124 void Session::collect_statistics(RenderStats *render_stats)
1125 {
1126         scene->collect_statistics(render_stats);
1127         if(params.use_profiling && (params.device.type == DEVICE_CPU)) {
1128                 render_stats->collect_profiling(scene, profiler);
1129         }
1130 }
1131
1132 int Session::get_max_closure_count()
1133 {
1134         int max_closures = 0;
1135         for(int i = 0; i < scene->shaders.size(); i++) {
1136                 int num_closures = scene->shaders[i]->graph->get_num_closures();
1137                 max_closures = max(max_closures, num_closures);
1138         }
1139         max_closure_global = max(max_closure_global, max_closures);
1140
1141         if (max_closure_global > MAX_CLOSURE) {
1142                 /* This is usually harmless as more complex shader tend to get many
1143                  * closures discarded due to mixing or low weights. We need to limit
1144                  * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it
1145                  * avoids excessive memory usage for split kernels. */
1146                 VLOG(2) << "Maximum number of closures exceeded: "
1147                                 << max_closure_global
1148                                 << " > "
1149                                 << MAX_CLOSURE;
1150
1151                 max_closure_global = MAX_CLOSURE;
1152         }
1153
1154         return max_closure_global;
1155 }
1156
1157 CCL_NAMESPACE_END