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