Fix Cycles to mostly work with render layer / depsgraph changes.
[blender.git] / source / blender / render / intern / source / external_engine.c
1 /*
2
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. 
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2006 Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/render/intern/source/external_engine.c
30  *  \ingroup render
31  */
32
33 #include <stddef.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLT_translation.h"
40
41 #include "BLI_listbase.h"
42 #include "BLI_string.h"
43 #include "BLI_utildefines.h"
44
45 #include "DNA_object_types.h"
46
47 #include "BKE_camera.h"
48 #include "BKE_global.h"
49 #include "BKE_colortools.h"
50 #include "BKE_layer.h"
51 #include "BKE_report.h"
52 #include "BKE_scene.h"
53
54 #include "DEG_depsgraph.h"
55 #include "DEG_depsgraph_query.h"
56
57 #include "RNA_access.h"
58
59 #ifdef WITH_PYTHON
60 #include "BPY_extern.h"
61 #endif
62
63 #include "RE_engine.h"
64 #include "RE_pipeline.h"
65 #include "RE_bake.h"
66
67 #include "DRW_engine.h"
68
69 #include "initrender.h"
70 #include "renderpipeline.h"
71 #include "render_types.h"
72 #include "render_result.h"
73 #include "rendercore.h"
74
75 /* Render Engine Types */
76
77 static RenderEngineType internal_render_type = {
78         NULL, NULL,
79         "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL | RE_USE_LEGACY_PIPELINE,
80         NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes, NULL, NULL, NULL,
81         {NULL, NULL, NULL}
82 };
83
84 #ifdef WITH_GAMEENGINE
85
86 static RenderEngineType internal_game_type = {
87         NULL, NULL,
88         "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME | RE_USE_LEGACY_PIPELINE,
89         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
90         {NULL, NULL, NULL}
91 };
92
93 #endif
94
95 ListBase R_engines = {NULL, NULL};
96
97 void RE_engines_init(void)
98 {
99         RE_engines_register(NULL, &internal_render_type);
100 #ifdef WITH_GAMEENGINE
101         RE_engines_register(NULL, &internal_game_type);
102 #endif
103         DRW_engines_register();
104 }
105
106 void RE_engines_exit(void)
107 {
108         RenderEngineType *type, *next;
109
110         DRW_engines_free();
111
112         BKE_layer_collection_engine_settings_callback_free();
113         BKE_view_layer_engine_settings_callback_free();
114
115         for (type = R_engines.first; type; type = next) {
116                 next = type->next;
117
118                 BLI_remlink(&R_engines, type);
119
120                 if (!(type->flag & RE_INTERNAL)) {
121                         if (type->ext.free)
122                                 type->ext.free(type->ext.data);
123
124                         MEM_freeN(type);
125                 }
126         }
127 }
128
129 void RE_engines_register(Main *bmain, RenderEngineType *render_type)
130 {
131         if (render_type->draw_engine) {
132                 DRW_engine_register(render_type->draw_engine);
133         }
134         if (render_type->collection_settings_create) {
135                 BKE_layer_collection_engine_settings_callback_register(
136                             bmain, render_type->idname, render_type->collection_settings_create);
137         }
138         if (render_type->render_settings_create) {
139                 BKE_view_layer_engine_settings_callback_register(
140                             bmain, render_type->idname, render_type->render_settings_create);
141         }
142         BLI_addtail(&R_engines, render_type);
143 }
144
145 RenderEngineType *RE_engines_find(const char *idname)
146 {
147         RenderEngineType *type;
148         
149         type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
150         if (!type)
151                 type = &internal_render_type;
152         
153         return type;
154 }
155
156 bool RE_engine_is_external(Render *re)
157 {
158         return (re->engine && re->engine->type && re->engine->type->render_to_image);
159 }
160
161 bool RE_engine_is_opengl(RenderEngineType *render_type)
162 {
163         /* TODO refine? Can we have ogl render engine without ogl render pipeline? */
164         return (render_type->draw_engine != NULL) &&
165                DRW_engine_render_support(render_type->draw_engine);
166 }
167
168 /* Create, Free */
169
170 RenderEngine *RE_engine_create(RenderEngineType *type)
171 {
172         return RE_engine_create_ex(type, false);
173 }
174
175 RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport)
176 {
177         RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
178         engine->type = type;
179
180         if (use_for_viewport) {
181                 engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
182
183                 BLI_threaded_malloc_begin();
184         }
185
186         return engine;
187 }
188
189 void RE_engine_free(RenderEngine *engine)
190 {
191 #ifdef WITH_PYTHON
192         if (engine->py_instance) {
193                 BPY_DECREF_RNA_INVALIDATE(engine->py_instance);
194         }
195 #endif
196
197         if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
198                 BLI_threaded_malloc_end();
199         }
200
201         MEM_freeN(engine);
202 }
203
204 /* Render Results */
205
206 static RenderPart *get_part_from_result(Render *re, RenderResult *result)
207 {
208         RenderPart *pa;
209
210         for (pa = re->parts.first; pa; pa = pa->next) {
211                 if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
212                     result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
213                     result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
214                     result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin)
215                 {
216                         return pa;
217                 }
218         }
219
220         return NULL;
221 }
222
223 RenderResult *RE_engine_begin_result(
224         RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
225 {
226         Render *re = engine->re;
227         RenderResult *result;
228         rcti disprect;
229
230         /* ensure the coordinates are within the right limits */
231         CLAMP(x, 0, re->result->rectx);
232         CLAMP(y, 0, re->result->recty);
233         CLAMP(w, 0, re->result->rectx);
234         CLAMP(h, 0, re->result->recty);
235
236         if (x + w > re->result->rectx)
237                 w = re->result->rectx - x;
238         if (y + h > re->result->recty)
239                 h = re->result->recty - y;
240
241         /* allocate a render result */
242         disprect.xmin = x;
243         disprect.xmax = x + w;
244         disprect.ymin = y;
245         disprect.ymax = y + h;
246
247         result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname);
248
249         /* todo: make this thread safe */
250
251         /* can be NULL if we CLAMP the width or height to 0 */
252         if (result) {
253                 render_result_clone_passes(re, result, viewname);
254
255                 RenderPart *pa;
256
257                 /* Copy EXR tile settings, so pipeline knows whether this is a result
258                  * for Save Buffers enabled rendering.
259                  */
260                 result->do_exr_tile = re->result->do_exr_tile;
261
262                 BLI_addtail(&engine->fullresult, result);
263
264                 result->tilerect.xmin += re->disprect.xmin;
265                 result->tilerect.xmax += re->disprect.xmin;
266                 result->tilerect.ymin += re->disprect.ymin;
267                 result->tilerect.ymax += re->disprect.ymin;
268
269                 pa = get_part_from_result(re, result);
270
271                 if (pa)
272                         pa->status = PART_STATUS_IN_PROGRESS;
273         }
274
275         return result;
276 }
277
278 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
279 {
280         Render *re = engine->re;
281
282         if (result) {
283                 result->renlay = result->layers.first; /* weak, draws first layer always */
284                 re->display_update(re->duh, result, NULL);
285         }
286 }
287
288 void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername)
289 {
290         Render *re = engine->re;
291
292         if (!re || !re->result) {
293                 return;
294         }
295
296         render_result_add_pass(re->result, name, channels, chan_id, layername, NULL);
297 }
298
299 void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int highlight, int merge_results)
300 {
301         Render *re = engine->re;
302
303         if (!result) {
304                 return;
305         }
306
307         /* merge. on break, don't merge in result for preview renders, looks nicer */
308         if (!highlight) {
309                 /* for exr tile render, detect tiles that are done */
310                 RenderPart *pa = get_part_from_result(re, result);
311
312                 if (pa) {
313                         pa->status = (!cancel && merge_results)? PART_STATUS_MERGED: PART_STATUS_RENDERED;
314                 }
315                 else if (re->result->do_exr_tile) {
316                         /* if written result does not match any tile and we are using save
317                          * buffers, we are going to get openexr save errors */
318                         fprintf(stderr, "RenderEngine.end_result: dimensions do not match any OpenEXR tile.\n");
319                 }
320         }
321
322         if (!cancel || merge_results) {
323                 if (re->result->do_exr_tile) {
324                         if (!cancel && merge_results) {
325                                 render_result_exr_file_merge(re->result, result, re->viewname);
326                         }
327                 }
328                 else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
329                         render_result_merge(re->result, result);
330
331                 /* draw */
332                 if (!re->test_break(re->tbh)) {
333                         result->renlay = result->layers.first; /* weak, draws first layer always */
334                         re->display_update(re->duh, result, NULL);
335                 }
336         }
337
338         /* free */
339         BLI_remlink(&engine->fullresult, result);
340         render_result_free(result);
341 }
342
343 RenderResult *RE_engine_get_result(RenderEngine *engine)
344 {
345         return engine->re->result;
346 }
347
348 /* Cancel */
349
350 int RE_engine_test_break(RenderEngine *engine)
351 {
352         Render *re = engine->re;
353
354         if (re)
355                 return re->test_break(re->tbh);
356         
357         return 0;
358 }
359
360 /* Statistics */
361
362 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
363 {
364         Render *re = engine->re;
365
366         /* stats draw callback */
367         if (re) {
368                 re->i.statstr = stats;
369                 re->i.infostr = info;
370                 re->stats_draw(re->sdh, &re->i);
371                 re->i.infostr = NULL;
372                 re->i.statstr = NULL;
373         }
374
375         /* set engine text */
376         engine->text[0] = '\0';
377
378         if (stats && stats[0] && info && info[0])
379                 BLI_snprintf(engine->text, sizeof(engine->text), "%s | %s", stats, info);
380         else if (info && info[0])
381                 BLI_strncpy(engine->text, info, sizeof(engine->text));
382         else if (stats && stats[0])
383                 BLI_strncpy(engine->text, stats, sizeof(engine->text));
384 }
385
386 void RE_engine_update_progress(RenderEngine *engine, float progress)
387 {
388         Render *re = engine->re;
389
390         if (re) {
391                 CLAMP(progress, 0.0f, 1.0f);
392                 re->progress(re->prh, progress);
393         }
394 }
395
396 void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
397 {
398         Render *re = engine->re;
399
400         if (re) {
401                 re->i.mem_used = mem_used;
402                 re->i.mem_peak = mem_peak;
403         }
404 }
405
406 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
407 {
408         Render *re = engine->re;
409
410         if (re)
411                 BKE_report(engine->re->reports, type, msg);
412         else if (engine->reports)
413                 BKE_report(engine->reports, type, msg);
414 }
415
416 void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
417 {
418         Render *re = engine->re;
419         if (re != NULL) {
420                 RenderResult *rr = RE_AcquireResultRead(re);
421                 if (rr) {
422                         if (rr->error != NULL) {
423                                 MEM_freeN(rr->error);
424                         }
425                         rr->error = BLI_strdup(msg);
426                 }
427                 RE_ReleaseResult(re);
428         }
429 }
430
431 const char *RE_engine_active_view_get(RenderEngine *engine)
432 {
433         Render *re = engine->re;
434         return RE_GetActiveRenderView(re);
435 }
436
437 void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
438 {
439         Render *re = engine->re;
440         RE_SetActiveRenderView(re, viewname);
441 }
442
443 float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, int use_spherical_stereo)
444 {
445         Render *re = engine->re;
446
447         /* when using spherical stereo, get camera shift without multiview, leaving stereo to be handled by the engine */
448         if (use_spherical_stereo)
449                 re = NULL;
450
451         return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
452 }
453
454 void RE_engine_get_camera_model_matrix(
455         RenderEngine *engine, Object *camera, int use_spherical_stereo, float *r_modelmat)
456 {
457         Render *re = engine->re;
458
459         /* when using spherical stereo, get model matrix without multiview, leaving stereo to be handled by the engine */
460         if (use_spherical_stereo)
461                 re = NULL;
462
463         BKE_camera_multiview_model_matrix(re ? &re->r : NULL, camera, re->viewname, (float (*)[4])r_modelmat);
464 }
465
466 int RE_engine_get_spherical_stereo(RenderEngine *engine, Object *camera)
467 {
468         Render *re = engine->re;
469         return BKE_camera_multiview_spherical_stereo(re ? &re->r : NULL, camera) ? 1 : 0;
470 }
471
472 rcti* RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free)
473 {
474         static rcti tiles_static[BLENDER_MAX_THREADS];
475         const int allocation_step = BLENDER_MAX_THREADS;
476         RenderPart *pa;
477         int total_tiles = 0;
478         rcti *tiles = tiles_static;
479         int allocation_size = BLENDER_MAX_THREADS;
480
481         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ);
482
483         *r_needs_free = false;
484
485         if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
486                 *r_total_tiles = 0;
487                 BLI_rw_mutex_unlock(&re->partsmutex);
488                 return NULL;
489         }
490
491         for (pa = re->parts.first; pa; pa = pa->next) {
492                 if (pa->status == PART_STATUS_IN_PROGRESS) {
493                         if (total_tiles >= allocation_size) {
494                                 /* Just in case we're using crazy network rendering with more
495                                  * slaves as BLENDER_MAX_THREADS.
496                                  */
497                                 allocation_size += allocation_step;
498                                 if (tiles == tiles_static) {
499                                         /* Can not realloc yet, tiles are pointing to a
500                                          * stack memory.
501                                          */
502                                         tiles = MEM_mallocN(allocation_size * sizeof(rcti), "current engine tiles");
503                                 }
504                                 else {
505                                         tiles = MEM_reallocN(tiles, allocation_size * sizeof(rcti));
506                                 }
507                                 *r_needs_free = true;
508                         }
509                         tiles[total_tiles] = pa->disprect;
510
511                         if (pa->crop) {
512                                 tiles[total_tiles].xmin += pa->crop;
513                                 tiles[total_tiles].ymin += pa->crop;
514                                 tiles[total_tiles].xmax -= pa->crop;
515                                 tiles[total_tiles].ymax -= pa->crop;
516                         }
517
518                         total_tiles++;
519                 }
520         }
521         BLI_rw_mutex_unlock(&re->partsmutex);
522         *r_total_tiles = total_tiles;
523         return tiles;
524 }
525
526 RenderData *RE_engine_get_render_data(Render *re)
527 {
528         return &re->r;
529 }
530
531 /* Bake */
532 void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
533 {
534         re->scene = scene;
535         re->main = bmain;
536         render_copy_renderdata(&re->r, &scene->r);
537         render_copy_viewrender(&re->view_render, &scene->view_render);
538 }
539
540 bool RE_bake_has_engine(Render *re)
541 {
542         RenderEngineType *type = RE_engines_find(re->view_render.engine_id);
543         return (type->bake != NULL);
544 }
545
546 bool RE_bake_engine(
547         Render *re, Object *object,
548         const int object_id, const BakePixel pixel_array[],
549         const size_t num_pixels, const int depth,
550         const eScenePassType pass_type, const int pass_filter,
551         float result[])
552 {
553         RenderEngineType *type = RE_engines_find(re->view_render.engine_id);
554         RenderEngine *engine;
555         bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
556
557         /* set render info */
558         re->i.cfra = re->scene->r.cfra;
559         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
560         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
561
562         /* render */
563         engine = re->engine;
564
565         if (!engine) {
566                 engine = RE_engine_create(type);
567                 re->engine = engine;
568         }
569
570         engine->flag |= RE_ENGINE_RENDERING;
571
572         /* TODO: actually link to a parent which shouldn't happen */
573         engine->re = re;
574
575         engine->resolution_x = re->winx;
576         engine->resolution_y = re->winy;
577
578         RE_parts_init(re, false);
579         engine->tile_x = re->r.tilex;
580         engine->tile_y = re->r.tiley;
581
582         /* update is only called so we create the engine.session */
583         if (type->update)
584                 type->update(engine, re->main, re->scene);
585
586         if (type->bake) {
587                 EvaluationContext *eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
588                 Depsgraph *depsgraph = DEG_graph_new();
589                 ViewLayer *view_layer = BLI_findlink(&re->scene->view_layers, re->scene->active_view_layer);
590
591                 DEG_evaluation_context_init_from_view_layer_for_render(
592                                         eval_ctx,
593                                         depsgraph,
594                                         re->scene,
595                                         view_layer);
596
597                 BKE_scene_graph_update_tagged(eval_ctx, depsgraph, re->main, re->scene, view_layer);
598
599                 type->bake(engine,
600                            depsgraph,
601                            re->scene,
602                            object,
603                            pass_type,
604                            pass_filter,
605                            object_id,
606                            pixel_array,
607                            num_pixels,
608                            depth,
609                            result);
610
611                 DEG_graph_free(depsgraph);
612                 DEG_evaluation_context_free(eval_ctx);
613         }
614
615         engine->tile_x = 0;
616         engine->tile_y = 0;
617         engine->flag &= ~RE_ENGINE_RENDERING;
618
619         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
620
621         /* re->engine becomes zero if user changed active render engine during render */
622         if (!persistent_data || !re->engine) {
623                 RE_engine_free(engine);
624                 re->engine = NULL;
625         }
626
627         RE_parts_free(re);
628         BLI_rw_mutex_unlock(&re->partsmutex);
629
630         if (BKE_reports_contain(re->reports, RPT_ERROR))
631                 G.is_break = true;
632
633         return true;
634 }
635
636 void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
637 {
638         Render *re = engine->re;
639         Scene *scene = re->scene;
640         double cfra = (double)frame + (double)subframe;
641
642         CLAMP(cfra, MINAFRAME, MAXFRAME);
643         BKE_scene_frame_set(scene, cfra);
644
645 #ifdef WITH_PYTHON
646         BPy_BEGIN_ALLOW_THREADS;
647 #endif
648
649 #ifdef WITH_PYTHON
650         BPy_END_ALLOW_THREADS;
651 #endif
652
653         BKE_scene_camera_switch_update(scene);
654 }
655
656 /* Render */
657
658 int RE_engine_render(Render *re, int do_all)
659 {
660         RenderEngineType *type = RE_engines_find(re->view_render.engine_id);
661         RenderEngine *engine;
662         bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
663
664         /* verify if we can render */
665         if (!type->render_to_image)
666                 return 0;
667         if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
668                 return 0;
669         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
670                 return 0;
671         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
672                 return 0;
673
674         /* Lock drawing in UI during data phase. */
675         if (re->draw_lock) {
676                 re->draw_lock(re->dlh, 1);
677         }
678
679         /* update animation here so any render layer animation is applied before
680          * creating the render result */
681         if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
682                 render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
683         }
684
685         /* create render result */
686         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
687         if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
688                 int savebuffers = RR_USE_MEM;
689
690                 if (re->result)
691                         render_result_free(re->result);
692
693                 if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
694                         savebuffers = RR_USE_EXR;
695                 re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS);
696         }
697         BLI_rw_mutex_unlock(&re->resultmutex);
698
699         if (re->result == NULL) {
700                 /* Clear UI drawing locks. */
701                 if (re->draw_lock) {
702                         re->draw_lock(re->dlh, 0);
703                 }
704                 /* Too small image is handled earlier, here it could only happen if
705                  * there was no sufficient memory to allocate all passes.
706                  */
707                 BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
708                 G.is_break = true;
709                 return 1;
710         }
711
712         /* set render info */
713         re->i.cfra = re->scene->r.cfra;
714         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
715         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
716
717         /* render */
718         engine = re->engine;
719
720         if (!engine) {
721                 engine = RE_engine_create(type);
722                 re->engine = engine;
723         }
724
725         engine->flag |= RE_ENGINE_RENDERING;
726
727         /* TODO: actually link to a parent which shouldn't happen */
728         engine->re = re;
729
730         if (re->flag & R_ANIMATION)
731                 engine->flag |= RE_ENGINE_ANIMATION;
732         if (re->r.scemode & R_BUTS_PREVIEW)
733                 engine->flag |= RE_ENGINE_PREVIEW;
734         engine->camera_override = re->camera_override;
735         engine->layer_override = re->layer_override;
736
737         engine->resolution_x = re->winx;
738         engine->resolution_y = re->winy;
739
740         RE_parts_init(re, false);
741         engine->tile_x = re->partx;
742         engine->tile_y = re->party;
743
744         if (re->result->do_exr_tile)
745                 render_result_exr_file_begin(re);
746
747         if (type->update) {
748                 type->update(engine, re->main, re->scene);
749         }
750
751         /* Clear UI drawing locks. */
752         if (re->draw_lock) {
753                 re->draw_lock(re->dlh, 0);
754         }
755
756         if (type->render_to_image) {
757                 FOREACH_VIEW_LAYER_TO_RENDER(re, view_layer_iter)
758                 {
759                         EvaluationContext *eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
760                         Depsgraph *depsgraph = DEG_graph_new();
761                         ViewLayer *view_layer = BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name));
762
763                         DEG_evaluation_context_init_from_view_layer_for_render(
764                                                 eval_ctx,
765                                                 depsgraph,
766                                                 re->scene,
767                                                 view_layer);
768
769                         BKE_scene_graph_update_tagged(eval_ctx, depsgraph, re->main, re->scene, view_layer);
770                         type->render_to_image(engine, depsgraph);
771
772                         DEG_graph_free(depsgraph);
773                         DEG_evaluation_context_free(eval_ctx);
774                 }
775                 FOREACH_VIEW_LAYER_TO_RENDER_END
776         }
777
778         engine->tile_x = 0;
779         engine->tile_y = 0;
780         engine->flag &= ~RE_ENGINE_RENDERING;
781
782         render_result_free_list(&engine->fullresult, engine->fullresult.first);
783
784         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
785
786         /* re->engine becomes zero if user changed active render engine during render */
787         if (!persistent_data || !re->engine) {
788                 RE_engine_free(engine);
789                 re->engine = NULL;
790         }
791
792         if (re->result->do_exr_tile) {
793                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
794                 render_result_save_empty_result_tiles(re);
795                 render_result_exr_file_end(re);
796                 BLI_rw_mutex_unlock(&re->resultmutex);
797         }
798
799         if (re->r.scemode & R_EXR_CACHE_FILE) {
800                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
801                 render_result_exr_file_cache_write(re);
802                 BLI_rw_mutex_unlock(&re->resultmutex);
803         }
804
805         RE_parts_free(re);
806         BLI_rw_mutex_unlock(&re->partsmutex);
807
808         if (BKE_reports_contain(re->reports, RPT_ERROR))
809                 G.is_break = true;
810         
811 #ifdef WITH_FREESTYLE
812         if (re->r.mode & R_EDGE_FRS)
813                 RE_RenderFreestyleExternal(re);
814 #endif
815
816         return 1;
817 }
818
819 void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
820                              const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type)
821 {
822         /* The channel information is currently not used, but is part of the API in case it's needed in the future. */
823
824         if (!(scene && view_layer && engine)) {
825                 return;
826         }
827
828         /* Register the pass in all scenes that have a render layer node for this layer.
829          * Since multiple scenes can be used in the compositor, the code must loop over all scenes
830          * and check whether their nodetree has a node that needs to be updated. */
831         Scene *sce;
832         for (sce = G.main->scene.first; sce; sce = sce->id.next) {
833                 if (sce->nodetree) {
834                         ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type);
835                 }
836         }
837 }