Merge branch 'blender2.7'
authorLukas Stockner <lukas.stockner@freenet.de>
Fri, 18 Jan 2019 00:47:32 +0000 (01:47 +0100)
committerLukas Stockner <lukas.stockner@freenet.de>
Fri, 18 Jan 2019 00:47:32 +0000 (01:47 +0100)
1  2 
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/render/extern/include/RE_engine.h
source/blender/render/intern/include/render_result.h
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/render_result.c

@@@ -41,7 -41,6 +41,7 @@@
  #include "BKE_context.h"
  #include "BKE_global.h"
  #include "BKE_main.h"
 +#include "BKE_scene.h"
  
  /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
  
@@@ -52,14 -51,14 +52,14 @@@ static bNodeSocketTemplate cmp_node_rla
        {       SOCK_VECTOR, 0, N_(RE_PASSNAME_NORMAL),                                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VECTOR, 0, N_(RE_PASSNAME_UV),                                             1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VECTOR, 0, N_(RE_PASSNAME_VECTOR),                                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 -      {       SOCK_RGBA,   0, N_(RE_PASSNAME_RGBA),                                   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 -      {       SOCK_RGBA,   0, N_(RE_PASSNAME_DIFFUSE),                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 -      {       SOCK_RGBA,   0, N_(RE_PASSNAME_SPEC),                                   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 +      {       SOCK_RGBA,   0, N_(RE_PASSNAME_DEPRECATED),                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 +      {       SOCK_RGBA,   0, N_(RE_PASSNAME_DEPRECATED),                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 +      {       SOCK_RGBA,   0, N_(RE_PASSNAME_DEPRECATED),                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_RGBA,   0, N_(RE_PASSNAME_SHADOW),                                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_RGBA,   0, N_(RE_PASSNAME_AO),                                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 -      {       SOCK_RGBA,   0, N_(RE_PASSNAME_REFLECT),                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 -      {       SOCK_RGBA,   0, N_(RE_PASSNAME_REFRACT),                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 -      {       SOCK_RGBA,   0, N_(RE_PASSNAME_INDIRECT),                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 +      {       SOCK_RGBA,   0, N_(RE_PASSNAME_DEPRECATED),                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 +      {       SOCK_RGBA,   0, N_(RE_PASSNAME_DEPRECATED),                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
 +      {       SOCK_RGBA,   0, N_(RE_PASSNAME_DEPRECATED),                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_FLOAT,  0, N_(RE_PASSNAME_INDEXOB),                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_FLOAT,  0, N_(RE_PASSNAME_INDEXMA),                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_FLOAT,  0, N_(RE_PASSNAME_MIST),                                   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
@@@ -191,16 -190,16 +191,16 @@@ typedef struct RLayerUpdateData 
        int prev_index;
  } RLayerUpdateData;
  
 -void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
 +void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, ViewLayer *view_layer, const char *name, int type)
  {
        RLayerUpdateData *data = node->storage;
  
 -      if (scene == NULL || srl == NULL || data == NULL || node->id != (ID *)scene) {
 +      if (scene == NULL || view_layer == NULL || data == NULL || node->id != (ID *)scene) {
                return;
        }
  
 -      SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1);
 -      if (node_srl != srl) {
 +      ViewLayer *node_view_layer = BLI_findlink(&scene->view_layers, node->custom1);
 +      if (node_view_layer != view_layer) {
                return;
        }
  
        }
  }
  
 -static void cmp_node_rlayer_create_outputs_cb(RenderEngine *UNUSED(engine), Scene *scene, SceneRenderLayer *srl,
++static void cmp_node_rlayer_create_outputs_cb(RenderEngine *UNUSED(engine), Scene *scene, ViewLayer *view_layer,
+                                               const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type)
+ {
+       /* Register the pass in all scenes that have a render layer node for this layer.
+        * Since multiple scenes can be used in the compositor, the code must loop over all scenes
+        * and check whether their nodetree has a node that needs to be updated. */
+       /* NOTE: using G_MAIN seems valid here,
+        * unless we want to register that for every other temp Main we could generate??? */
++      ntreeCompositRegisterPass(scene->nodetree, scene, view_layer, name, type);
++
+       for (Scene *sce = G_MAIN->scene.first; sce; sce = sce->id.next) {
 -              if (sce->nodetree) {
 -                      ntreeCompositRegisterPass(sce->nodetree, scene, srl, name, type);
++              if (sce->nodetree && sce != scene) {
++                      ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type);
+               }
+       }
+ }
  static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets)
  {
        Scene *scene = (Scene *)node->id;
        if (scene) {
                RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
                if (engine_type && engine_type->update_render_passes) {
 -                      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1);
 -                      if (srl) {
 +                      ViewLayer *view_layer = BLI_findlink(&scene->view_layers, node->custom1);
 +                      if (view_layer) {
                                RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data");
                                data->available_sockets = available_sockets;
                                data->prev_index = -1;
                                node->storage = data;
  
                                RenderEngine *engine = RE_engine_create(engine_type);
-                               engine_type->update_render_passes(engine, scene, view_layer);
 -                              RE_engine_update_render_passes(engine, scene, srl, cmp_node_rlayer_create_outputs_cb);
++                              RE_engine_update_render_passes(engine, scene, view_layer, cmp_node_rlayer_create_outputs_cb);
                                RE_engine_free(engine);
  
                                MEM_freeN(data);
@@@ -306,8 -320,8 +323,8 @@@ static void node_composit_init_image(bN
        node->storage = iuser;
        iuser->frames = 1;
        iuser->sfra = 1;
 -      iuser->fie_ima = 2;
        iuser->ok = 1;
 +      iuser->flag |= IMA_ANIM_ALWAYS;
  
        /* setup initial outputs */
        cmp_node_image_verify_outputs(ntree, node, false);
@@@ -360,9 -374,9 +377,9 @@@ const char *node_cmp_rlayers_sock_to_pa
  {
        const char *sock_to_passname[] = {
                RE_PASSNAME_COMBINED, RE_PASSNAME_COMBINED,
 -              RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_RGBA,
 -              RE_PASSNAME_DIFFUSE, RE_PASSNAME_SPEC, RE_PASSNAME_SHADOW, RE_PASSNAME_AO,
 -              RE_PASSNAME_REFLECT, RE_PASSNAME_REFRACT, RE_PASSNAME_INDIRECT,
 +              RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_DEPRECATED,
 +              RE_PASSNAME_DEPRECATED, RE_PASSNAME_DEPRECATED, RE_PASSNAME_SHADOW, RE_PASSNAME_AO,
 +              RE_PASSNAME_DEPRECATED, RE_PASSNAME_DEPRECATED, RE_PASSNAME_DEPRECATED,
                RE_PASSNAME_INDEXOB, RE_PASSNAME_INDEXMA, RE_PASSNAME_MIST, RE_PASSNAME_EMIT, RE_PASSNAME_ENVIRONMENT,
                RE_PASSNAME_DIFFUSE_DIRECT, RE_PASSNAME_DIFFUSE_INDIRECT, RE_PASSNAME_DIFFUSE_COLOR,
                RE_PASSNAME_GLOSSY_DIRECT, RE_PASSNAME_GLOSSY_INDIRECT, RE_PASSNAME_GLOSSY_COLOR,
@@@ -414,11 -428,8 +431,11 @@@ static void node_composit_free_rlayers(
        bNodeSocket *sock;
  
        /* free extra socket info */
 -      for (sock = node->outputs.first; sock; sock = sock->next)
 -              MEM_freeN(sock->storage);
 +      for (sock = node->outputs.first; sock; sock = sock->next) {
 +              if (sock->storage) {
 +                      MEM_freeN(sock->storage);
 +              }
 +      }
  }
  
  static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), bNode *UNUSED(dest_node), bNode *src_node)
        bNodeSocket *sock;
  
        /* copy extra socket info */
 -      for (sock = src_node->outputs.first; sock; sock = sock->next)
 -              sock->new_sock->storage = MEM_dupallocN(sock->storage);
 +      for (sock = src_node->outputs.first; sock; sock = sock->next) {
 +              if (sock->storage) {
 +                      sock->new_sock->storage = MEM_dupallocN(sock->storage);
 +              }
 +      }
  }
  
  static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node)
@@@ -451,7 -459,6 +468,7 @@@ void register_node_type_cmp_rlayers(voi
        node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers);
        node_type_update(&ntype, cmp_node_rlayers_update, NULL);
        node_type_init(&ntype, node_cmp_rlayers_outputs);
 +      node_type_size_preset(&ntype, NODE_SIZE_LARGE);
  
        nodeRegisterType(&ntype);
  }
  #include "RNA_types.h"
  #include "RE_bake.h"
  
+ #include "BLI_threads.h"
  struct bNode;
  struct bNodeTree;
 +struct BakePixel;
 +struct Depsgraph;
 +struct IDProperty;
 +struct Main;
  struct Object;
  struct Render;
  struct RenderData;
@@@ -52,13 -50,13 +54,13 @@@ struct RenderLayer
  struct RenderResult;
  struct ReportList;
  struct Scene;
 -struct BakePixel;
 +struct ViewLayer;
  
  /* External Engine */
  
  /* RenderEngineType.flag */
  #define RE_INTERNAL                           1
 -#define RE_GAME                                       2
 +/* #define RE_FLAG_DEPRECATED 2 */
  #define RE_USE_PREVIEW                        4
  #define RE_USE_POSTPROCESS            8
  #define RE_USE_SHADING_NODES  16
@@@ -92,25 -90,23 +94,28 @@@ typedef struct RenderEngineType 
        char name[64];
        int flag;
  
 -      void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene);
 -      void (*render)(struct RenderEngine *engine, struct Scene *scene);
 -      void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result);
 +      void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph);
 +      void (*render)(struct RenderEngine *engine, struct Depsgraph *depsgraph);
 +      void (*bake)(struct RenderEngine *engine, struct Depsgraph *depsgraph,
 +                   struct Object *object, const int pass_type,
 +                   const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels,
 +                   const int depth, void *result);
  
        void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
        void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
  
        void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
 -      void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl);
 +      void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer);
 +
 +      struct DrawEngineType *draw_engine;
  
        /* RNA integration */
        ExtensionRNA ext;
  } RenderEngineType;
  
 -typedef void (*update_render_passes_cb_t)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
++typedef void (*update_render_passes_cb_t)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
+                                           const char *name, int channels, const char *chanid, int type);
  typedef struct RenderEngine {
        RenderEngineType *type;
        void *py_instance;
  
        struct ReportList *reports;
  
 +      /* Depsgraph */
 +      struct Depsgraph *depsgraph;
 +
        /* for blender internal only */
        int update_flag;
        int job_update_flag;
  
+       /* callback for render pass query */
+       ThreadMutex update_render_passes_mutex;
+       update_render_passes_cb_t update_render_passes_cb;
        rctf last_viewplane;
        rcti last_disprect;
        float last_viewmat[4][4];
@@@ -175,24 -172,20 +184,26 @@@ bool RE_engine_is_external(struct Rende
  
  void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe);
  
 -void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
++void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
+                                     update_render_passes_cb_t callback);
 -void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
 +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
                               const char *name, int channels, const char *chanid, int type);
  
  /* Engine Types */
  
  void RE_engines_init(void);
  void RE_engines_exit(void);
 +void RE_engines_register(RenderEngineType *render_type);
 +
 +bool RE_engine_is_opengl(RenderEngineType *render_type);
  
  RenderEngineType *RE_engines_find(const char *idname);
  
  rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free);
  struct RenderData *RE_engine_get_render_data(struct Render *re);
 -void RE_bake_engine_set_engine_parameters(struct Render *re, struct Main *bmain, struct Scene *scene);
 +void RE_bake_engine_set_engine_parameters(
 +        struct Render *re, struct Main *bmain, struct Scene *scene);
 +
 +void RE_engine_free_blender_memory(struct RenderEngine *engine);
  
  #endif /* __RE_ENGINE_H__ */
@@@ -44,6 -44,7 +44,7 @@@ struct ImBuf
  struct ListBase;
  struct Render;
  struct RenderData;
+ struct RenderEngine;
  struct RenderLayer;
  struct RenderResult;
  struct Scene;
@@@ -55,6 -56,8 +56,6 @@@ struct ColorManagedViewSettings
  
  struct RenderResult *render_result_new(struct Render *re,
        struct rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname);
 -struct RenderResult *render_result_new_full_sample(struct Render *re,
 -      struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers, const char *viewname);
  
  struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
  
@@@ -83,8 -86,8 +84,8 @@@ void render_result_single_layer_end(str
  /* EXR Tile File Render */
  
  void render_result_save_empty_result_tiles(struct Render *re);
- void render_result_exr_file_begin(struct Render *re);
- void render_result_exr_file_end(struct Render *re);
+ void render_result_exr_file_begin(struct Render *re, struct RenderEngine *engine);
+ void render_result_exr_file_end(struct Render *re, struct RenderEngine *engine);
  
  /* render pass wrapper for gpencil */
  struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, const char *name, const char *viewname);
@@@ -92,7 -95,7 +93,7 @@@
  void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname);
  
  void render_result_exr_file_path(struct Scene *scene, const char *layname, int sample, char *filepath);
- int render_result_exr_file_read_sample(struct Render *re, int sample);
+ int render_result_exr_file_read_sample(struct Render *re, int sample, struct RenderEngine *engine);
  int render_result_exr_file_read_path(struct RenderResult *rr, struct RenderLayer *rl_single, const char *filepath);
  
  /* EXR cache */
@@@ -115,27 -118,4 +116,27 @@@ void render_result_views_shallowcopy(st
  void render_result_views_shallowdelete(struct RenderResult *rr);
  bool render_result_has_views(struct RenderResult *rr);
  
 +#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_)    \
 +{                                                         \
 +      int nr_;                                              \
 +      ViewLayer *iter_;                                     \
 +      for (nr_ = 0, iter_ = (re_)->view_layers.first;       \
 +           iter_ != NULL;                                   \
 +          iter_ = iter_->next, nr_++)                       \
 +      {                                                     \
 +              if (!G.background &&  (re_)->r.scemode & R_SINGLE_LAYER) {  \
 +                      if (nr_ != re->active_view_layer) {           \
 +                              continue;                                 \
 +                      }                                             \
 +              }                                                 \
 +              else {                                            \
 +                      if ((iter_->flag & VIEW_LAYER_RENDER) == 0) { \
 +                              continue;                                 \
 +                      }                                             \
 +              }
 +
 +#define FOREACH_VIEW_LAYER_TO_RENDER_END                  \
 +      }                                                     \
 +} ((void)0)
 +
  #endif /* __RENDER_RESULT_H__ */
  #include "BLI_string.h"
  #include "BLI_utildefines.h"
  
 +#include "DNA_object_types.h"
 +
  #include "BKE_camera.h"
  #include "BKE_global.h"
  #include "BKE_colortools.h"
 +#include "BKE_layer.h"
 +#include "BKE_node.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
  
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_debug.h"
 +#include "DEG_depsgraph_query.h"
 +
  #include "RNA_access.h"
  
  #ifdef WITH_PYTHON
  #include "RE_pipeline.h"
  #include "RE_bake.h"
  
 +#include "DRW_engine.h"
 +
  #include "initrender.h"
  #include "renderpipeline.h"
  #include "render_types.h"
  #include "render_result.h"
 -#include "rendercore.h"
  
  /* Render Engine Types */
  
 -static RenderEngineType internal_render_type = {
 -      NULL, NULL,
 -      "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
 -      NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes,
 -      {NULL, NULL, NULL}
 -};
 -
 -#ifdef WITH_GAMEENGINE
 -
 -static RenderEngineType internal_game_type = {
 -      NULL, NULL,
 -      "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
 -      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 -      {NULL, NULL, NULL}
 -};
 -
 -#endif
 -
  ListBase R_engines = {NULL, NULL};
  
  void RE_engines_init(void)
  {
 -      BLI_addtail(&R_engines, &internal_render_type);
 -#ifdef WITH_GAMEENGINE
 -      BLI_addtail(&R_engines, &internal_game_type);
 -#endif
 +      DRW_engines_register();
  }
  
  void RE_engines_exit(void)
  {
        RenderEngineType *type, *next;
  
 +      DRW_engines_free();
 +
        for (type = R_engines.first; type; type = next) {
                next = type->next;
  
        }
  }
  
 +void RE_engines_register(RenderEngineType *render_type)
 +{
 +      if (render_type->draw_engine) {
 +              DRW_engine_register(render_type->draw_engine);
 +      }
 +      BLI_addtail(&R_engines, render_type);
 +}
 +
  RenderEngineType *RE_engines_find(const char *idname)
  {
        RenderEngineType *type;
  
        type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
        if (!type)
 -              type = &internal_render_type;
 +              type = BLI_findstring(&R_engines, "BLENDER_EEVEE", offsetof(RenderEngineType, idname));
  
        return type;
  }
  
  bool RE_engine_is_external(Render *re)
  {
 -      RenderEngineType *type = RE_engines_find(re->r.engine);
 -      return (type && type->render);
 +      return (re->engine && re->engine->type && re->engine->type->render);
 +}
 +
 +bool RE_engine_is_opengl(RenderEngineType *render_type)
 +{
 +      /* TODO refine? Can we have ogl render engine without ogl render pipeline? */
 +      return (render_type->draw_engine != NULL) &&
 +             DRW_engine_render_support(render_type->draw_engine);
  }
  
  /* Create, Free */
@@@ -150,6 -146,8 +150,8 @@@ RenderEngine *RE_engine_create_ex(Rende
                BLI_threaded_malloc_begin();
        }
  
+       BLI_mutex_init(&engine->update_render_passes_mutex);
        return engine;
  }
  
@@@ -165,6 -163,8 +167,8 @@@ void RE_engine_free(RenderEngine *engin
                BLI_threaded_malloc_end();
        }
  
+       BLI_mutex_end(&engine->update_render_passes_mutex);
        MEM_freeN(engine);
  }
  
@@@ -187,8 -187,7 +191,8 @@@ static RenderPart *get_part_from_result
        return NULL;
  }
  
 -RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
 +RenderResult *RE_engine_begin_result(
 +        RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
  {
        Render *re = engine->re;
        RenderResult *result;
@@@ -418,8 -417,7 +422,8 @@@ float RE_engine_get_camera_shift_x(Rend
        return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
  }
  
 -void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, bool use_spherical_stereo, float *r_modelmat)
 +void RE_engine_get_camera_model_matrix(
 +        RenderEngine *engine, Object *camera, bool use_spherical_stereo, float *r_modelmat)
  {
        Render *re = engine->re;
  
@@@ -475,6 -473,13 +479,6 @@@ rcti* RE_engine_get_current_tiles(Rende
                        }
                        tiles[total_tiles] = pa->disprect;
  
 -                      if (pa->crop) {
 -                              tiles[total_tiles].xmin += pa->crop;
 -                              tiles[total_tiles].ymin += pa->crop;
 -                              tiles[total_tiles].xmax -= pa->crop;
 -                              tiles[total_tiles].ymax -= pa->crop;
 -                      }
 -
                        total_tiles++;
                }
        }
@@@ -488,49 -493,6 +492,49 @@@ RenderData *RE_engine_get_render_data(R
        return &re->r;
  }
  
 +/* Depsgraph */
 +static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
 +{
 +      Main *bmain = engine->re->main;
 +      Scene *scene = engine->re->scene;
 +
 +      engine->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
 +      DEG_debug_name_set(engine->depsgraph, "RENDER");
 +
 +      BKE_scene_graph_update_for_newframe(engine->depsgraph, bmain);
 +}
 +
 +static void engine_depsgraph_free(RenderEngine *engine)
 +{
 +      DEG_graph_free(engine->depsgraph);
 +
 +      engine->depsgraph = NULL;
 +}
 +
 +void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
 +{
 +      if(!engine->depsgraph) {
 +              return;
 +      }
 +
 +#ifdef WITH_PYTHON
 +      BPy_BEGIN_ALLOW_THREADS;
 +#endif
 +
 +      Render *re = engine->re;
 +      double cfra = (double)frame + (double)subframe;
 +
 +      CLAMP(cfra, MINAFRAME, MAXFRAME);
 +      BKE_scene_frame_set(re->scene, cfra);
 +      BKE_scene_graph_update_for_newframe(engine->depsgraph, re->main);
 +
 +      BKE_scene_camera_switch_update(re->scene);
 +
 +#ifdef WITH_PYTHON
 +      BPy_END_ALLOW_THREADS;
 +#endif
 +}
 +
  /* Bake */
  void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
  {
@@@ -546,7 -508,7 +550,7 @@@ bool RE_bake_has_engine(Render *re
  }
  
  bool RE_bake_engine(
 -        Render *re, Object *object,
 +        Render *re, Depsgraph *depsgraph, Object *object,
          const int object_id, const BakePixel pixel_array[],
          const size_t num_pixels, const int depth,
          const eScenePassType pass_type, const int pass_filter,
        engine->resolution_x = re->winx;
        engine->resolution_y = re->winy;
  
 -      RE_parts_init(re, false);
 +      RE_parts_init(re);
        engine->tile_x = re->r.tilex;
        engine->tile_y = re->r.tiley;
  
 -      /* update is only called so we create the engine.session */
 -      if (type->update)
 -              type->update(engine, re->main, re->scene);
 -
 -      if (type->bake)
 -              type->bake(engine, re->scene, object, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result);
 +      if (type->bake) {
 +              engine->depsgraph = depsgraph;
 +
 +              /* update is only called so we create the engine.session */
 +              if (type->update)
 +                      type->update(engine, re->main, engine->depsgraph);
 +
 +              type->bake(engine,
 +                         engine->depsgraph,
 +                         object,
 +                         pass_type,
 +                         pass_filter,
 +                         object_id,
 +                         pixel_array,
 +                         num_pixels,
 +                         depth,
 +                         result);
 +
 +              engine->depsgraph = NULL;
 +      }
  
        engine->tile_x = 0;
        engine->tile_y = 0;
        return true;
  }
  
 -void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
 -{
 -      Render *re = engine->re;
 -      Scene *scene = re->scene;
 -      double cfra = (double)frame + (double)subframe;
 -
 -      CLAMP(cfra, MINAFRAME, MAXFRAME);
 -      BKE_scene_frame_set(scene, cfra);
 -
 -#ifdef WITH_PYTHON
 -      BPy_BEGIN_ALLOW_THREADS;
 -#endif
 -
 -      /* It's possible that here we're including layers which were never visible before. */
 -      BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, scene, (1 << 20) - 1, true);
 -
 -#ifdef WITH_PYTHON
 -      BPy_END_ALLOW_THREADS;
 -#endif
 -
 -      BKE_scene_camera_switch_update(scene);
 -}
 -
  /* Render */
  
 -static bool render_layer_exclude_animated(Scene *scene, SceneRenderLayer *srl)
 -{
 -      PointerRNA ptr;
 -      PropertyRNA *prop;
 -
 -      RNA_pointer_create(&scene->id, &RNA_SceneRenderLayer, srl, &ptr);
 -      prop = RNA_struct_find_property(&ptr, "layers_exclude");
 -
 -      return RNA_property_animated(&ptr, prop);
 -}
 -
  int RE_engine_render(Render *re, int do_all)
  {
        RenderEngineType *type = RE_engines_find(re->r.engine);
        /* update animation here so any render layer animation is applied before
         * creating the render result */
        if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
 -              unsigned int lay = re->lay;
 -
 -              /* don't update layers excluded on all render layers */
 -              if (type->flag & RE_USE_EXCLUDE_LAYERS) {
 -                      SceneRenderLayer *srl;
 -                      unsigned int non_excluded_lay = 0;
 -
 -                      if (re->r.scemode & R_SINGLE_LAYER) {
 -                              srl = BLI_findlink(&re->r.layers, re->r.actlay);
 -                              if (srl) {
 -                                      non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask);
 -
 -                                      /* in this case we must update all because animation for
 -                                       * the scene has not been updated yet, and so may not be
 -                                       * up to date until after BKE_scene_update_for_newframe */
 -                                      if (render_layer_exclude_animated(re->scene, srl))
 -                                              non_excluded_lay |= ~0;
 -                              }
 -                      }
 -                      else {
 -                              for (srl = re->r.layers.first; srl; srl = srl->next) {
 -                                      if (!(srl->layflag & SCE_LAY_DISABLE)) {
 -                                              non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask);
 -
 -                                              if (render_layer_exclude_animated(re->scene, srl))
 -                                                      non_excluded_lay |= ~0;
 -                                      }
 -                              }
 -                      }
 -
 -                      lay &= non_excluded_lay;
 -              }
 -
 -              BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, re->scene, lay, true);
 -              render_update_anim_renderdata(re, &re->scene->r);
 +              render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
        }
  
        /* create render result */
        if (re->r.scemode & R_BUTS_PREVIEW)
                engine->flag |= RE_ENGINE_PREVIEW;
        engine->camera_override = re->camera_override;
 -      engine->layer_override = re->layer_override;
  
        engine->resolution_x = re->winx;
        engine->resolution_y = re->winy;
  
 -      RE_parts_init(re, false);
 +      RE_parts_init(re);
        engine->tile_x = re->partx;
        engine->tile_y = re->party;
  
        if (re->result->do_exr_tile)
-               render_result_exr_file_begin(re);
+               render_result_exr_file_begin(re, engine);
  
 -      if (type->update)
 -              type->update(engine, re->main, re->scene);
 -
        /* Clear UI drawing locks. */
        if (re->draw_lock) {
                re->draw_lock(re->dlh, 0);
        }
  
 -      if (type->render)
 -              type->render(engine, re->scene);
 +      if (type->render) {
 +              FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer_iter)
 +              {
 +                      if (re->draw_lock) {
 +                              re->draw_lock(re->dlh, 1);
 +                      }
 +
 +                      ViewLayer *view_layer = BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name));
 +                      engine_depsgraph_init(engine, view_layer);
 +
 +                      if (type->update) {
 +                              type->update(engine, re->main, engine->depsgraph);
 +                      }
 +
 +                      if (re->draw_lock) {
 +                              re->draw_lock(re->dlh, 0);
 +                      }
 +
 +                      type->render(engine, engine->depsgraph);
 +
 +                      /* Grease pencil render over previous render result.
 +                       *
 +                       * NOTE: External engine might have been requested to free its
 +                       * dependency graph, which is only allowed if there is no grease
 +                       * pencil (pipeline is taking care of that).
 +                       */
 +                      if (!RE_engine_test_break(engine) && engine->depsgraph != NULL) {
 +                              DRW_render_gpencil(engine, engine->depsgraph);
 +                      }
 +
 +                      engine_depsgraph_free(engine);
 +
 +                      if (RE_engine_test_break(engine)) {
 +                              break;
 +                      }
 +              }
 +              FOREACH_VIEW_LAYER_TO_RENDER_END;
 +      }
  
        engine->tile_x = 0;
        engine->tile_y = 0;
  
        BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
  
-       /* re->engine becomes zero if user changed active render engine during render */
-       if (!persistent_data || !re->engine) {
-               RE_engine_free(engine);
-               re->engine = NULL;
-       }
        if (re->result->do_exr_tile) {
                BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                render_result_save_empty_result_tiles(re);
-               render_result_exr_file_end(re);
+               render_result_exr_file_end(re, engine);
                BLI_rw_mutex_unlock(&re->resultmutex);
        }
  
+       /* re->engine becomes zero if user changed active render engine during render */
+       if (!persistent_data || !re->engine) {
+               RE_engine_free(engine);
+               re->engine = NULL;
+       }
        if (re->r.scemode & R_EXR_CACHE_FILE) {
                BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                render_result_exr_file_cache_write(re);
        return 1;
  }
  
- void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
-                              const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type)
 -void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
++void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
+                                     update_render_passes_cb_t callback)
  {
-       /* The channel information is currently not used, but is part of the API in case it's needed in the future. */
-       if (!(scene && view_layer && engine)) {
 -      if (!(scene && srl && engine && callback && engine->type->update_render_passes)) {
++      if (!(scene && view_layer && engine && callback && engine->type->update_render_passes)) {
                return;
        }
  
-       /* Register the pass in all scenes that have a render layer node for this layer.
-        * Since multiple scenes can be used in the compositor, the code must loop over all scenes
-        * and check whether their nodetree has a node that needs to be updated. */
-       /* NOTE: using G_MAIN seems valid here,
-        * unless we want to register that for every other temp Main we could generate??? */
-       ntreeCompositRegisterPass(scene->nodetree, scene, view_layer, name, type);
+       BLI_mutex_lock(&engine->update_render_passes_mutex);
  
-       for (Scene *sce = G_MAIN->scene.first; sce; sce = sce->id.next) {
-               if (sce->nodetree && sce != scene) {
-                       ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type);
-               }
+       engine->update_render_passes_cb = callback;
 -      engine->type->update_render_passes(engine, scene, srl);
++      engine->type->update_render_passes(engine, scene, view_layer);
+       BLI_mutex_unlock(&engine->update_render_passes_mutex);
+ }
 -void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
++void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
+                              const char *name, int channels, const char *chanid, int type)
+ {
 -      if (!(scene && srl && engine && engine->update_render_passes_cb)) {
++      if (!(scene && view_layer && engine && engine->update_render_passes_cb)) {
+               return;
        }
 -      engine->update_render_passes_cb(engine, scene, srl, name, channels, chanid, type);
++      engine->update_render_passes_cb(engine, scene, view_layer, name, channels, chanid, type);
 +}
 +
 +void RE_engine_free_blender_memory(RenderEngine *engine)
 +{
 +      /* Weak way to save memory, but not crash grease pencil.
 +       *
 +       * TODO(sergey): Find better solution for this.
 +       * TODO(sergey): Try to find solution which does not involve looping over
 +       * all the objects.
 +       */
 +      if (DRW_render_check_grease_pencil(engine->depsgraph)) {
 +              return;
 +      }
 +      DEG_graph_free(engine->depsgraph);
 +      engine->depsgraph = NULL;
  }
  #include "BLI_threads.h"
  
  #include "BKE_appdir.h"
 -#include "BKE_image.h"
 +#include "BKE_camera.h"
  #include "BKE_global.h"
 -#include "BKE_main.h"
 +#include "BKE_image.h"
  #include "BKE_report.h"
 -#include "BKE_camera.h"
  #include "BKE_scene.h"
  
  #include "IMB_imbuf.h"
@@@ -57,6 -58,8 +57,8 @@@
  
  #include "intern/openexr/openexr_multi.h"
  
+ #include "RE_engine.h"
  #include "render_result.h"
  #include "render_types.h"
  
@@@ -265,7 -268,9 +267,7 @@@ RenderResult *render_result_new(Render 
        RenderResult *rr;
        RenderLayer *rl;
        RenderView *rv;
 -      SceneRenderLayer *srl;
        int rectx, recty;
 -      int nr;
  
        rectx = BLI_rcti_size_x(partrct);
        recty = BLI_rcti_size_y(partrct);
        render_result_views_new(rr, &re->r);
  
        /* check renderdata for amount of layers */
 -      for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
 -
 -              if (layername && layername[0])
 -                      if (!STREQ(srl->name, layername))
 -                              continue;
 -
 -              if (re->r.scemode & R_SINGLE_LAYER) {
 -                      if (nr != re->r.actlay)
 -                              continue;
 -              }
 -              else {
 -                      if (srl->layflag & SCE_LAY_DISABLE)
 +      FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer)
 +      {
 +              if (layername && layername[0]) {
 +                      if (!STREQ(view_layer->name, layername)) {
                                continue;
 +                      }
                }
  
                rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
                BLI_addtail(&rr->layers, rl);
  
 -              BLI_strncpy(rl->name, srl->name, sizeof(rl->name));
 -              rl->lay = srl->lay;
 -              rl->lay_zmask = srl->lay_zmask;
 -              rl->lay_exclude = srl->lay_exclude;
 -              rl->layflag = srl->layflag;
 -              rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */
 -              rl->pass_xor = srl->pass_xor;
 -              rl->light_override = srl->light_override;
 -              rl->mat_override = srl->mat_override;
 +              BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name));
 +              rl->layflag = view_layer->layflag;
 +              rl->passflag = view_layer->passflag; /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
                rl->rectx = rectx;
                rl->recty = recty;
  
                        /* a renderlayer should always have a Combined pass*/
                        render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA");
  
 -                      if (srl->passflag  & SCE_PASS_Z)
 +                      if (view_layer->passflag  & SCE_PASS_Z)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
 -                      if (srl->passflag  & SCE_PASS_VECTOR)
 +                      if (view_layer->passflag  & SCE_PASS_VECTOR)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
 -                      if (srl->passflag  & SCE_PASS_NORMAL)
 +                      if (view_layer->passflag  & SCE_PASS_NORMAL)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
 -                      if (srl->passflag  & SCE_PASS_UV)
 +                      if (view_layer->passflag  & SCE_PASS_UV)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
 -                      if (srl->passflag  & SCE_PASS_RGBA)
 -                              RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RGBA, view, "RGBA");
 -                      if (srl->passflag  & SCE_PASS_EMIT)
 +                      if (view_layer->passflag  & SCE_PASS_EMIT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_DIFFUSE)
 -                              RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_SPEC)
 -                              RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SPEC, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_AO)
 +                      if (view_layer->passflag  & SCE_PASS_AO)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_ENVIRONMENT)
 +                      if (view_layer->passflag  & SCE_PASS_ENVIRONMENT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_INDIRECT)
 -                              RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_INDIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_SHADOW)
 +                      if (view_layer->passflag  & SCE_PASS_SHADOW)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_REFLECT)
 -                              RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFLECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_REFRACT)
 -                              RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFRACT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_INDEXOB)
 +                      if (view_layer->passflag  & SCE_PASS_INDEXOB)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
 -                      if (srl->passflag  & SCE_PASS_INDEXMA)
 +                      if (view_layer->passflag  & SCE_PASS_INDEXMA)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
 -                      if (srl->passflag  & SCE_PASS_MIST)
 +                      if (view_layer->passflag  & SCE_PASS_MIST)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z");
                        if (rl->passflag & SCE_PASS_RAYHITS)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_DIFFUSE_DIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_DIFFUSE_DIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_DIFFUSE_INDIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_DIFFUSE_INDIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_DIFFUSE_COLOR)
 +                      if (view_layer->passflag  & SCE_PASS_DIFFUSE_COLOR)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_GLOSSY_DIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_GLOSSY_DIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_GLOSSY_INDIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_GLOSSY_INDIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_GLOSSY_COLOR)
 +                      if (view_layer->passflag  & SCE_PASS_GLOSSY_COLOR)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_TRANSM_DIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_TRANSM_DIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_TRANSM_INDIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_TRANSM_INDIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_TRANSM_COLOR)
 +                      if (view_layer->passflag  & SCE_PASS_TRANSM_COLOR)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_SUBSURFACE_DIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_SUBSURFACE_DIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_SUBSURFACE_INDIRECT)
 +                      if (view_layer->passflag  & SCE_PASS_SUBSURFACE_INDIRECT)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
 -                      if (srl->passflag  & SCE_PASS_SUBSURFACE_COLOR)
 +                      if (view_layer->passflag  & SCE_PASS_SUBSURFACE_COLOR)
                                RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
  #undef RENDER_LAYER_ADD_PASS_SAFE
                }
        }
 -      /* sss, previewrender and envmap don't do layers, so we make a default one */
 +      FOREACH_VIEW_LAYER_TO_RENDER_END;
 +
 +      /* previewrender doesn't do layers, so we make a default one */
        if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
                rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
                BLI_addtail(&rr->layers, rl);
                }
  
                /* note, this has to be in sync with scene.c */
 -              rl->lay = (1 << 20) - 1;
                rl->layflag = 0x7FFF;    /* solid ztra halo strand */
                rl->passflag = SCE_PASS_COMBINED;
  
 -              re->r.actlay = 0;
 +              re->active_view_layer = 0;
        }
  
        /* border render; calculate offset for use in compositor. compo is centralized coords */
@@@ -482,6 -511,7 +484,7 @@@ void render_result_add_pass(RenderResul
                        for (rp = rl->passes.first; rp; rp = rp->next) {
                                if (!STREQ(rp->name, name)) continue;
                                if (!STREQ(rp->view, view)) continue;
+                               break;
                        }
  
                        if (!rp) {
        }
  }
  
 -/* allocate osa new results for samples */
 -RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers, const char *viewname)
 -{
 -      int a;
 -
 -      if (re->osa == 0)
 -              return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname);
 -
 -      for (a = 0; a < re->osa; a++) {
 -              RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname);
 -              BLI_addtail(lb, rr);
 -              rr->sample_nr = a;
 -      }
 -
 -      return lb->first;
 -}
 -
  static int passtype_from_name(const char *name)
  {
        const char delim[] = {'.', '\0'};
        CHECK_PASS(VECTOR);
        CHECK_PASS(NORMAL);
        CHECK_PASS(UV);
 -      CHECK_PASS(RGBA);
        CHECK_PASS(EMIT);
 -      CHECK_PASS(DIFFUSE);
 -      CHECK_PASS(SPEC);
        CHECK_PASS(SHADOW);
        CHECK_PASS(AO);
        CHECK_PASS(ENVIRONMENT);
 -      CHECK_PASS(INDIRECT);
 -      CHECK_PASS(REFLECT);
 -      CHECK_PASS(REFRACT);
        CHECK_PASS(INDEXOB);
        CHECK_PASS(INDEXMA);
        CHECK_PASS(MIST);
@@@ -945,7 -998,7 +948,7 @@@ void render_result_single_layer_begin(R
  /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
  void render_result_single_layer_end(Render *re)
  {
 -      SceneRenderLayer *srl;
 +      ViewLayer *view_layer;
        RenderLayer *rlpush;
        RenderLayer *rl;
        int nr;
                BLI_remlink(&re->result->layers, rl);
  
                /* reconstruct render result layers */
 -              for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
 -                      if (nr == re->r.actlay) {
 +              for (nr = 0, view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next, nr++) {
 +                      if (nr == re->active_view_layer) {
                                BLI_addtail(&re->result->layers, rl);
                        }
                        else {
 -                              rlpush = RE_GetRenderLayer(re->pushedresult, srl->name);
 +                              rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name);
                                if (rlpush) {
                                        BLI_remlink(&re->pushedresult->layers, rlpush);
                                        BLI_addtail(&re->result->layers, rlpush);
@@@ -1054,8 -1107,8 +1057,8 @@@ void render_result_save_empty_result_ti
                for (rl = rr->layers.first; rl; rl = rl->next) {
                        for (pa = re->parts.first; pa; pa = pa->next) {
                                if (pa->status != PART_STATUS_MERGED) {
 -                                      int party = pa->disprect.ymin - re->disprect.ymin + pa->crop;
 -                                      int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop;
 +                                      int party = pa->disprect.ymin - re->disprect.ymin;
 +                                      int partx = pa->disprect.xmin - re->disprect.xmin;
                                        IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname, true);
                                }
                        }
        }
  }
  
 -static void render_result_register_pass_cb(RenderEngine *engine, Scene *UNUSED(scene), SceneRenderLayer *srl,
++static void render_result_register_pass_cb(RenderEngine *engine, Scene *UNUSED(scene), ViewLayer *view_layer,
+                                            const char *name, int channels, const char *chanid, int UNUSED(type))
+ {
 -      RE_engine_add_pass(engine, name, channels, chanid, srl->name);
++      RE_engine_add_pass(engine, name, channels, chanid, view_layer->name);
+ }
+ static void render_result_create_all_passes(RenderEngine *engine, Render *re, RenderLayer *rl)
+ {
+       if (engine && engine->type->update_render_passes) {
 -              SceneRenderLayer *srl;
 -              srl = BLI_findstring(&re->r.layers, rl->name, offsetof(SceneRenderLayer, name));
 -              if (srl) {
 -                      RE_engine_update_render_passes(engine, re->scene, srl, render_result_register_pass_cb);
++              ViewLayer *view_layer;
++              view_layer = BLI_findstring(&re->view_layers, rl->name, offsetof(ViewLayer, name));
++              if (view_layer) {
++                      RE_engine_update_render_passes(engine, re->scene, view_layer, render_result_register_pass_cb);
+               }
+       }
+ }
  /* begin write of exr tile file */
- void render_result_exr_file_begin(Render *re)
+ void render_result_exr_file_begin(Render *re, RenderEngine *engine)
  {
        RenderResult *rr;
        RenderLayer *rl;
  
        for (rr = re->result; rr; rr = rr->next) {
                for (rl = rr->layers.first; rl; rl = rl->next) {
+                       render_result_create_all_passes(engine, re, rl);
                        render_result_exr_file_path(re->scene, rl->name, rr->sample_nr, str);
                        printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
                        IMB_exrtile_begin_write(rl->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
  }
  
  /* end write of exr tile file, read back first sample */
- void render_result_exr_file_end(Render *re)
+ void render_result_exr_file_end(Render *re, RenderEngine *engine)
  {
        RenderResult *rr;
        RenderLayer *rl;
        render_result_free_list(&re->fullresult, re->result);
        re->result = NULL;
  
-       render_result_exr_file_read_sample(re, 0);
+       render_result_exr_file_read_sample(re, 0, engine);
  }
  
  /* save part into exr file */
@@@ -1127,7 -1199,7 +1149,7 @@@ void render_result_exr_file_path(Scene 
  }
  
  /* only for temp buffer, makes exact copy of render result */
- int render_result_exr_file_read_sample(Render *re, int sample)
+ int render_result_exr_file_read_sample(Render *re, int sample, RenderEngine *engine)
  {
        RenderLayer *rl;
        char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
        re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
  
        for (rl = re->result->layers.first; rl; rl = rl->next) {
+               render_result_create_all_passes(engine, re, rl);
                render_result_exr_file_path(re->scene, rl->name, sample, str);
                printf("read exr tmp file: %s\n", str);