Merge branch 'master' into blender2.8
authorLukas Stockner <lukas.stockner@freenet.de>
Wed, 3 May 2017 16:33:02 +0000 (18:33 +0200)
committerLukas Stockner <lukas.stockner@freenet.de>
Wed, 3 May 2017 16:33:02 +0000 (18:33 +0200)
32 files changed:
1  2 
intern/cycles/blender/addon/__init__.py
intern/cycles/blender/addon/engine.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_python.cpp
intern/cycles/blender/blender_session.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/blender/blender_sync.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/writefile.c
source/blender/draw/engines/basic/basic_engine.c
source/blender/draw/engines/clay/clay_engine.c
source/blender/draw/engines/eevee/eevee_engine.c
source/blender/draw/engines/external/external_engine.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_update.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_edit.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/rna_render.c
source/blender/makesrna/intern/rna_scene.c
source/blender/nodes/CMakeLists.txt
source/blender/render/CMakeLists.txt
source/blender/render/extern/include/RE_engine.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/pipeline.c
source/blenderplayer/bad_level_call_stubs/stubs.c

Simple merge
Simple merge
Simple merge
Simple merge
index 0b6be6ab08da03c430ac464047a1ce9499251001,c187766b5862718427a07491a89193129e831091..a097e0a9e48f56ca716f9436692fc064ce5eecb6
@@@ -1609,30 -1609,31 +1609,54 @@@ void blo_do_versions_270(FileData *fd, 
                                }
                        }
                }
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == CMP_NODE_R_LAYERS) {
+                                               int pass_index = 0;
+                                               const char *sockname;
+                                               for (bNodeSocket *sock = node->outputs.first; sock && pass_index < 31; sock = sock->next, pass_index++) {
+                                                       if (sock->storage == NULL) {
+                                                               NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+                                                               sock->storage = sockdata;
+                                                               BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(pass_index), sizeof(sockdata->pass_name));
+                                                               if (pass_index == 0) sockname = "Image";
+                                                               else if (pass_index == 1) sockname = "Alpha";
+                                                               else sockname = node_cmp_rlayers_sock_to_pass(pass_index);
+                                                               BLI_strncpy(sock->name, sockname, sizeof(sock->name));
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               } FOREACH_NODETREE_END
        }
 +
 +      {
 +              if (!DNA_struct_elem_find(fd->filesdna, "View3DDebug", "char", "background")) {
 +                      bScreen *screen;
 +
 +                      for (screen = main->screen.first; screen; screen = screen->id.next) {
 +                              ScrArea *sa;
 +                              for (sa = screen->areabase.first; sa; sa = sa->next) {
 +                                      SpaceLink *sl;
 +
 +                                      for (sl = sa->spacedata.first; sl; sl = sl->next) {
 +                                              switch (sl->spacetype) {
 +                                                      case SPACE_VIEW3D:
 +                                                      {
 +                                                              View3D *v3d = (View3D *)sl;
 +                                                              v3d->debug.background = V3D_DEBUG_BACKGROUND_NONE;
 +                                                      }
 +                                              }
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
  }
  
  void do_versions_after_linking_270(Main *main)
index bdcdefe414a1ef0d43d386906e47daf116f25877,0000000000000000000000000000000000000000..169c67f97029e1c14cf15ccdc2c3d8cafe63cdae
mode 100644,000000..100644
--- /dev/null
@@@ -1,257 -1,0 +1,257 @@@
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 +/*
 + * Copyright 2016, Blender Foundation.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + * Contributor(s): Blender Institute
 + *
 + */
 +
 +/** \file basic_engine.h
 + *  \ingroup draw_engine
 + *
 + * Simple engine for drawing color and/or depth.
 + * When we only need simple flat shaders.
 + */
 +
 +#include "DRW_render.h"
 +
 +#include "BKE_icons.h"
 +#include "BKE_idprop.h"
 +#include "BKE_main.h"
 +
 +#include "GPU_shader.h"
 +
 +#include "basic_engine.h"
 +/* Shaders */
 +
 +#define BASIC_ENGINE "BLENDER_BASIC"
 +
 +/* we may want this later? */
 +#define USE_DEPTH
 +
 +/* *********** LISTS *********** */
 +
 +/* GPUViewport.storage
 + * Is freed everytime the viewport engine changes */
 +typedef struct BASIC_Storage {
 +      int dummy;
 +} BASIC_Storage;
 +
 +typedef struct BASIC_StorageList {
 +      struct BASIC_Storage *storage;
 +      struct BASIC_PrivateData *g_data;
 +} BASIC_StorageList;
 +
 +typedef struct BASIC_FramebufferList {
 +      /* default */
 +      struct GPUFrameBuffer *default_fb;
 +      /* engine specific */
 +#ifdef USE_DEPTH
 +      struct GPUFrameBuffer *dupli_depth;
 +#endif
 +} BASIC_FramebufferList;
 +
 +typedef struct BASIC_TextureList {
 +      /* default */
 +      struct GPUTexture *color;
 +#ifdef USE_DEPTH
 +      struct GPUTexture *depth;
 +      /* engine specific */
 +      struct GPUTexture *depth_dup;
 +#endif
 +} BASIC_TextureList;
 +
 +typedef struct BASIC_PassList {
 +#ifdef USE_DEPTH
 +      struct DRWPass *depth_pass;
 +      struct DRWPass *depth_pass_cull;
 +#endif
 +      struct DRWPass *color_pass;
 +} BASIC_PassList;
 +
 +typedef struct BASIC_Data {
 +      void *engine_type;
 +      BASIC_FramebufferList *fbl;
 +      BASIC_TextureList *txl;
 +      BASIC_PassList *psl;
 +      BASIC_StorageList *stl;
 +} BASIC_Data;
 +
 +/* *********** STATIC *********** */
 +
 +static struct {
 +#ifdef USE_DEPTH
 +      /* Depth Pre Pass */
 +      struct GPUShader *depth_sh;
 +#endif
 +      /* Shading Pass */
 +      struct GPUShader *color_sh;
 +} e_data = {NULL}; /* Engine data */
 +
 +typedef struct BASIC_PrivateData {
 +#ifdef USE_DEPTH
 +      DRWShadingGroup *depth_shgrp;
 +      DRWShadingGroup *depth_shgrp_cull;
 +#endif
 +      DRWShadingGroup *color_shgrp;
 +} BASIC_PrivateData; /* Transient data */
 +
 +/* Functions */
 +
 +static void BASIC_engine_init(void *vedata)
 +{
 +      BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
 +      BASIC_TextureList *txl = ((BASIC_Data *)vedata)->txl;
 +      BASIC_FramebufferList *fbl = ((BASIC_Data *)vedata)->fbl;
 +
 +#ifdef USE_DEPTH
 +      /* Depth prepass */
 +      if (!e_data.depth_sh) {
 +              e_data.depth_sh = DRW_shader_create_3D_depth_only();
 +      }
 +#endif
 +
 +      /* Shading pass */
 +      if (!e_data.color_sh) {
 +              e_data.color_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
 +      }
 +
 +      if (!stl->storage) {
 +              stl->storage = MEM_callocN(sizeof(BASIC_Storage), "BASIC_Storage");
 +      }
 +
 +#ifdef USE_DEPTH
 +      if (DRW_state_is_fbo()) {
 +              const float *viewport_size = DRW_viewport_size_get();
 +              DRWFboTexture tex = {&txl->depth_dup, DRW_BUF_DEPTH_24, 0};
 +              DRW_framebuffer_init(&fbl->dupli_depth,
 +                                   (int)viewport_size[0], (int)viewport_size[1],
 +                                   &tex, 1);
 +      }
 +#endif
 +}
 +
 +static void BASIC_cache_init(void *vedata)
 +{
 +      BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
 +      BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
 +
 +      if (!stl->g_data) {
 +              /* Alloc transient pointers */
 +              stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
 +      }
 +
 +#ifdef USE_DEPTH
 +      /* Depth Pass */
 +      {
 +              psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 +              stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
 +
 +              psl->depth_pass_cull = DRW_pass_create(
 +                      "Depth Pass Cull",
 +                      DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
 +              stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
 +      }
 +#endif
 +
 +      /* Color Pass */
 +      {
 +              psl->color_pass = DRW_pass_create("Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
 +              stl->g_data->color_shgrp = DRW_shgroup_create(e_data.color_sh, psl->color_pass);
 +      }
 +}
 +
 +static void BASIC_cache_populate(void *vedata, Object *ob)
 +{
 +      BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
 +
 +      if (!DRW_is_object_renderable(ob))
 +              return;
 +
 +      struct Batch *geom = DRW_cache_object_surface_get(ob);
 +      if (geom) {
 +              bool do_cull = false;  /* TODO (we probably wan't to take this from the viewport?) */
 +#ifdef USE_DEPTH
 +              /* Depth Prepass */
 +              DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
 +#endif
 +              /* Shading */
 +              DRW_shgroup_call_add(stl->g_data->color_shgrp, geom, ob->obmat);
 +      }
 +}
 +
 +static void BASIC_cache_finish(void *vedata)
 +{
 +      BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
 +
 +      UNUSED_VARS(stl);
 +}
 +
 +static void BASIC_draw_scene(void *vedata)
 +{
 +
 +      BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
 +      BASIC_FramebufferList *fbl = ((BASIC_Data *)vedata)->fbl;
 +      DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
 +
 +#ifdef USE_DEPTH
 +      /* Pass 1 : Depth pre-pass */
 +      DRW_draw_pass(psl->depth_pass);
 +      DRW_draw_pass(psl->depth_pass_cull);
 +
 +      /* Pass 2 : Duplicate depth */
 +      /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
 +      if (DRW_state_is_fbo()) {
 +              DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true);
 +      }
 +#endif
 +
 +      /* Pass 3 : Shading */
 +      DRW_draw_pass(psl->color_pass);
 +}
 +
 +static void BASIC_engine_free(void)
 +{
 +      /* all shaders are builtin */
 +}
 +
 +static const DrawEngineDataSize BASIC_data_size = DRW_VIEWPORT_DATA_SIZE(BASIC_Data);
 +
 +DrawEngineType draw_engine_basic_type = {
 +      NULL, NULL,
 +      N_("Basic"),
 +      &BASIC_data_size,
 +      &BASIC_engine_init,
 +      &BASIC_engine_free,
 +      &BASIC_cache_init,
 +      &BASIC_cache_populate,
 +      &BASIC_cache_finish,
 +      NULL,
 +      &BASIC_draw_scene
 +};
 +
 +/* Note: currently unused, we may want to register so we can see this when debugging the view. */
 +
 +RenderEngineType DRW_engine_viewport_basic_type = {
 +      NULL, NULL,
 +      BASIC_ENGINE, N_("Basic"), RE_INTERNAL,
++      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 +      &draw_engine_basic_type,
 +      {NULL, NULL, NULL}
 +};
 +
 +
 +#undef BASIC_ENGINE
index 6f3e0c4e8b95d55e716328800caf47889cb150b8,0000000000000000000000000000000000000000..8ac8ed50cdc4ae91360b4d4b79ee08b48d02c183
mode 100644,000000..100644
--- /dev/null
@@@ -1,669 -1,0 +1,669 @@@
-       NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create,
 +/*
 + * Copyright 2016, Blender Foundation.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + * Contributor(s): Blender Institute
 + *
 + */
 +
 +#include "DRW_render.h"
 +
 +#include "BKE_icons.h"
 +#include "BKE_idprop.h"
 +#include "BKE_main.h"
 +
 +#include "BLI_dynstr.h"
 +#include "BLI_rand.h"
 +
 +#include "IMB_imbuf.h"
 +#include "IMB_imbuf_types.h"
 +
 +#include "UI_resources.h"
 +#include "UI_interface_icons.h"
 +
 +#include "clay_engine.h"
 +#ifdef WITH_CLAY_ENGINE
 +/* Shaders */
 +
 +#define CLAY_ENGINE "BLENDER_CLAY"
 +
 +extern char datatoc_clay_frag_glsl[];
 +extern char datatoc_clay_vert_glsl[];
 +extern char datatoc_ssao_alchemy_glsl[];
 +
 +/* *********** LISTS *********** */
 +
 +/* UBOs data needs to be 16 byte aligned (size of vec4) */
 +/* Reminder : float, int, bool are 4 bytes */
 +typedef struct CLAY_UBO_Material {
 +      float ssao_params_var[4];
 +      /* - 16 -*/
 +      float matcap_hsv[3];
 +      float matcap_id; /* even float encoding have enough precision */
 +      /* - 16 -*/
 +      float matcap_rot[2];
 +      float pad[2]; /* ensure 16 bytes alignement */
 +} CLAY_UBO_Material; /* 48 bytes */
 +
 +#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */
 +
 +typedef struct CLAY_UBO_Storage {
 +      CLAY_UBO_Material materials[MAX_CLAY_MAT];
 +} CLAY_UBO_Storage;
 +
 +/* GPUViewport.storage
 + * Is freed everytime the viewport engine changes */
 +typedef struct CLAY_Storage {
 +      /* Materials Parameter UBO */
 +      CLAY_UBO_Storage mat_storage;
 +      int ubo_current_id;
 +      DRWShadingGroup *shgrps[MAX_CLAY_MAT];
 +} CLAY_Storage;
 +
 +typedef struct CLAY_StorageList {
 +      struct CLAY_Storage *storage;
 +      struct GPUUniformBuffer *mat_ubo;
 +      struct CLAY_PrivateData *g_data;
 +} CLAY_StorageList;
 +
 +typedef struct CLAY_FramebufferList {
 +      /* default */
 +      struct GPUFrameBuffer *default_fb;
 +      /* engine specific */
 +      struct GPUFrameBuffer *dupli_depth;
 +} CLAY_FramebufferList;
 +
 +typedef struct CLAY_TextureList {
 +      /* default */
 +      struct GPUTexture *color;
 +      struct GPUTexture *depth;
 +      /* engine specific */
 +      struct GPUTexture *depth_dup;
 +} CLAY_TextureList;
 +
 +typedef struct CLAY_PassList {
 +      struct DRWPass *depth_pass;
 +      struct DRWPass *depth_pass_cull;
 +      struct DRWPass *clay_pass;
 +} CLAY_PassList;
 +
 +typedef struct CLAY_Data {
 +      void *engine_type;
 +      CLAY_FramebufferList *fbl;
 +      CLAY_TextureList *txl;
 +      CLAY_PassList *psl;
 +      CLAY_StorageList *stl;
 +} CLAY_Data;
 +
 +/* *********** STATIC *********** */
 +
 +static struct {
 +      /* Depth Pre Pass */
 +      struct GPUShader *depth_sh;
 +      /* Shading Pass */
 +      struct GPUShader *clay_sh;
 +
 +      /* Matcap textures */
 +      struct GPUTexture *matcap_array;
 +      float matcap_colors[24][3];
 +
 +      /* Ssao */
 +      float winmat[4][4];
 +      float viewvecs[3][4];
 +      float ssao_params[4];
 +      int cached_sample_num;
 +      struct GPUTexture *jitter_tx;
 +      struct GPUTexture *sampling_tx;
 +
 +      /* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
 +      int ubo_mat_idxs[MAX_CLAY_MAT];
 +} e_data = {NULL}; /* Engine data */
 +
 +typedef struct CLAY_PrivateData {
 +      DRWShadingGroup *depth_shgrp;
 +      DRWShadingGroup *depth_shgrp_select;
 +      DRWShadingGroup *depth_shgrp_active;
 +      DRWShadingGroup *depth_shgrp_cull;
 +      DRWShadingGroup *depth_shgrp_cull_select;
 +      DRWShadingGroup *depth_shgrp_cull_active;
 +} CLAY_PrivateData; /* Transient data */
 +
 +/* Functions */
 +
 +static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer)
 +{
 +      int image_size = prv->w[0] * prv->h[0];
 +      float *new_rect = &final_rect[image_size * 4 * layer];
 +
 +      IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB,
 +                                 false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]);
 +
 +      /* Find overall color */
 +      for (int y = 0; y < 4; ++y)     {
 +              for (int x = 0; x < 4; ++x) {
 +                      e_data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
 +                      e_data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
 +                      e_data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
 +              }
 +      }
 +
 +      e_data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
 +      e_data.matcap_colors[layer][1] /= 16.0f * 2.0f;
 +      e_data.matcap_colors[layer][2] /= 16.0f * 2.0f;
 +}
 +
 +static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr)
 +{
 +      struct GPUTexture *tex;
 +      int w = prv[0]->w[0];
 +      int h = prv[0]->h[0];
 +      float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect");
 +
 +      for (int i = 0; i < nbr; ++i) {
 +              add_icon_to_rect(prv[i], final_rect, i);
 +              BKE_previewimg_free(&prv[i]);
 +      }
 +
 +      tex = DRW_texture_create_2D_array(w, h, nbr, DRW_TEX_RGBA_8, DRW_TEX_FILTER, final_rect);
 +      MEM_freeN(final_rect);
 +
 +      return tex;
 +}
 +
 +static int matcap_to_index(int matcap)
 +{
 +      if (matcap == ICON_MATCAP_02) return 1;
 +      else if (matcap == ICON_MATCAP_03) return 2;
 +      else if (matcap == ICON_MATCAP_04) return 3;
 +      else if (matcap == ICON_MATCAP_05) return 4;
 +      else if (matcap == ICON_MATCAP_06) return 5;
 +      else if (matcap == ICON_MATCAP_07) return 6;
 +      else if (matcap == ICON_MATCAP_08) return 7;
 +      else if (matcap == ICON_MATCAP_09) return 8;
 +      else if (matcap == ICON_MATCAP_10) return 9;
 +      else if (matcap == ICON_MATCAP_11) return 10;
 +      else if (matcap == ICON_MATCAP_12) return 11;
 +      else if (matcap == ICON_MATCAP_13) return 12;
 +      else if (matcap == ICON_MATCAP_14) return 13;
 +      else if (matcap == ICON_MATCAP_15) return 14;
 +      else if (matcap == ICON_MATCAP_16) return 15;
 +      else if (matcap == ICON_MATCAP_17) return 16;
 +      else if (matcap == ICON_MATCAP_18) return 17;
 +      else if (matcap == ICON_MATCAP_19) return 18;
 +      else if (matcap == ICON_MATCAP_20) return 19;
 +      else if (matcap == ICON_MATCAP_21) return 20;
 +      else if (matcap == ICON_MATCAP_22) return 21;
 +      else if (matcap == ICON_MATCAP_23) return 22;
 +      else if (matcap == ICON_MATCAP_24) return 23;
 +      return 0;
 +}
 +
 +static struct GPUTexture *create_spiral_sample_texture(int numsaples)
 +{
 +      struct GPUTexture *tex;
 +      float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
 +      const float numsaples_inv = 1.0f / numsaples;
 +      int i;
 +      /* arbitrary number to ensure we don't get conciding samples every circle */
 +      const float spirals = 7.357;
 +
 +      for (i = 0; i < numsaples; i++) {
 +              float r = (i + 0.5f) * numsaples_inv;
 +              float phi = r * spirals * (float)(2.0 * M_PI);
 +              texels[i][0] = r * cosf(phi);
 +              texels[i][1] = r * sinf(phi);
 +      }
 +
 +      tex = DRW_texture_create_1D(numsaples, DRW_TEX_RG_16, 0, (float *)texels);
 +
 +      MEM_freeN(texels);
 +      return tex;
 +}
 +
 +static struct GPUTexture *create_jitter_texture(void)
 +{
 +      float jitter[64 * 64][2];
 +      int i;
 +
 +      /* TODO replace by something more evenly distributed like blue noise */
 +      for (i = 0; i < 64 * 64; i++) {
 +              jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
 +              jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
 +              normalize_v2(jitter[i]);
 +      }
 +
 +      return DRW_texture_create_2D(64, 64, DRW_TEX_RG_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
 +}
 +
 +static void CLAY_engine_init(void *vedata)
 +{
 +      CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
 +      CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl;
 +      CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
 +
 +      /* Create Texture Array */
 +      if (!e_data.matcap_array) {
 +              PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */
 +
 +              /* TODO only load used matcaps */
 +              prv[0]  = UI_icon_to_preview(ICON_MATCAP_01);
 +              prv[1]  = UI_icon_to_preview(ICON_MATCAP_02);
 +              prv[2]  = UI_icon_to_preview(ICON_MATCAP_03);
 +              prv[3]  = UI_icon_to_preview(ICON_MATCAP_04);
 +              prv[4]  = UI_icon_to_preview(ICON_MATCAP_05);
 +              prv[5]  = UI_icon_to_preview(ICON_MATCAP_06);
 +              prv[6]  = UI_icon_to_preview(ICON_MATCAP_07);
 +              prv[7]  = UI_icon_to_preview(ICON_MATCAP_08);
 +              prv[8]  = UI_icon_to_preview(ICON_MATCAP_09);
 +              prv[9]  = UI_icon_to_preview(ICON_MATCAP_10);
 +              prv[10] = UI_icon_to_preview(ICON_MATCAP_11);
 +              prv[11] = UI_icon_to_preview(ICON_MATCAP_12);
 +              prv[12] = UI_icon_to_preview(ICON_MATCAP_13);
 +              prv[13] = UI_icon_to_preview(ICON_MATCAP_14);
 +              prv[14] = UI_icon_to_preview(ICON_MATCAP_15);
 +              prv[15] = UI_icon_to_preview(ICON_MATCAP_16);
 +              prv[16] = UI_icon_to_preview(ICON_MATCAP_17);
 +              prv[17] = UI_icon_to_preview(ICON_MATCAP_18);
 +              prv[18] = UI_icon_to_preview(ICON_MATCAP_19);
 +              prv[19] = UI_icon_to_preview(ICON_MATCAP_20);
 +              prv[20] = UI_icon_to_preview(ICON_MATCAP_21);
 +              prv[21] = UI_icon_to_preview(ICON_MATCAP_22);
 +              prv[22] = UI_icon_to_preview(ICON_MATCAP_23);
 +              prv[23] = UI_icon_to_preview(ICON_MATCAP_24);
 +
 +              e_data.matcap_array = load_matcaps(prv, 24);
 +      }
 +
 +      /* AO Jitter */
 +      if (!e_data.jitter_tx) {
 +              e_data.jitter_tx = create_jitter_texture();
 +      }
 +
 +
 +      /* Depth prepass */
 +      if (!e_data.depth_sh) {
 +              e_data.depth_sh = DRW_shader_create_3D_depth_only();
 +      }
 +
 +      /* Shading pass */
 +      if (!e_data.clay_sh) {
 +              DynStr *ds = BLI_dynstr_new();
 +              const char *max_mat =
 +                      "#define MAX_MATERIAL 512\n"
 +                      "#define USE_ROTATION\n"
 +                      "#define USE_AO\n"
 +                      "#define USE_HSV\n";
 +              char *matcap_with_ao;
 +
 +              BLI_dynstr_append(ds, datatoc_clay_frag_glsl);
 +              BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl);
 +
 +              matcap_with_ao = BLI_dynstr_get_cstring(ds);
 +
 +              e_data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat);
 +
 +              BLI_dynstr_free(ds);
 +              MEM_freeN(matcap_with_ao);
 +      }
 +
 +      if (!stl->storage) {
 +              stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage");
 +      }
 +
 +      if (!stl->mat_ubo) {
 +              stl->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
 +      }
 +
 +      if (e_data.ubo_mat_idxs[1] == 0) {
 +              /* Just int to have pointers to them */
 +              for (int i = 0; i < MAX_CLAY_MAT; ++i) {
 +                      e_data.ubo_mat_idxs[i] = i;
 +              }
 +      }
 +
 +      if (DRW_state_is_fbo()) {
 +              const float *viewport_size = DRW_viewport_size_get();
 +              DRWFboTexture tex = {&txl->depth_dup, DRW_BUF_DEPTH_24, 0};
 +              DRW_framebuffer_init(&fbl->dupli_depth,
 +                                   (int)viewport_size[0], (int)viewport_size[1],
 +                                   &tex, 1);
 +      }
 +
 +      /* SSAO setup */
 +      {
 +              int ssao_samples = 32; /* XXX get from render settings */
 +              float invproj[4][4];
 +              float dfdyfacs[2];
 +              const bool is_persp = DRW_viewport_is_persp_get();
 +              /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
 +              float viewvecs[3][4] = {
 +                  {-1.0f, -1.0f, -1.0f, 1.0f},
 +                  {1.0f, -1.0f, -1.0f, 1.0f},
 +                  {-1.0f, 1.0f, -1.0f, 1.0f}
 +              };
 +              int i;
 +              const float *size = DRW_viewport_size_get();
 +
 +              DRW_state_dfdy_factors_get(dfdyfacs);
 +
 +              e_data.ssao_params[0] = ssao_samples;
 +              e_data.ssao_params[1] = size[0] / 64.0;
 +              e_data.ssao_params[2] = size[1] / 64.0;
 +              e_data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
 +
 +              /* invert the view matrix */
 +              DRW_viewport_matrix_get(e_data.winmat, DRW_MAT_WIN);
 +              invert_m4_m4(invproj, e_data.winmat);
 +
 +              /* convert the view vectors to view space */
 +              for (i = 0; i < 3; i++) {
 +                      mul_m4_v4(invproj, viewvecs[i]);
 +                      /* normalized trick see:
 +                       * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
 +                      mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
 +                      if (is_persp)
 +                              mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
 +                      viewvecs[i][3] = 1.0;
 +
 +                      copy_v4_v4(e_data.viewvecs[i], viewvecs[i]);
 +              }
 +
 +              /* we need to store the differences */
 +              e_data.viewvecs[1][0] -= e_data.viewvecs[0][0];
 +              e_data.viewvecs[1][1] = e_data.viewvecs[2][1] - e_data.viewvecs[0][1];
 +
 +              /* calculate a depth offset as well */
 +              if (!is_persp) {
 +                      float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
 +                      mul_m4_v4(invproj, vec_far);
 +                      mul_v3_fl(vec_far, 1.0f / vec_far[3]);
 +                      e_data.viewvecs[1][2] = vec_far[2] - e_data.viewvecs[0][2];
 +              }
 +
 +              /* AO Samples Tex */
 +              if (e_data.sampling_tx && (e_data.cached_sample_num != ssao_samples)) {
 +                      DRW_texture_free(e_data.sampling_tx);
 +                      e_data.sampling_tx = NULL;
 +              }
 +
 +              if (!e_data.sampling_tx) {
 +                      e_data.sampling_tx = create_spiral_sample_texture(ssao_samples);
 +                      e_data.cached_sample_num = ssao_samples;
 +              }
 +      }
 +}
 +
 +static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id)
 +{
 +      CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl;
 +      const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3;
 +
 +      DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_sh, pass);
 +
 +      DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
 +      DRW_shgroup_uniform_buffer(grp, "depthtex", &txl->depth_dup, depthloc);
 +      DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array, matcaploc);
 +      DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)e_data.winmat);
 +      DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)e_data.viewvecs, 3);
 +      DRW_shgroup_uniform_vec4(grp, "ssao_params", e_data.ssao_params, 1);
 +      DRW_shgroup_uniform_vec3(grp, "matcaps_color[0]", (float *)e_data.matcap_colors, 24);
 +
 +      DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
 +
 +      DRW_shgroup_uniform_texture(grp, "ssao_jitter", e_data.jitter_tx, jitterloc);
 +      DRW_shgroup_uniform_texture(grp, "ssao_samples", e_data.sampling_tx, sampleloc);
 +
 +      return grp;
 +}
 +
 +static int search_mat_to_ubo(
 +        CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
 +        float matcap_val, float ssao_distance, float ssao_factor_cavity,
 +        float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
 +{
 +      /* For now just use a linear search and test all parameters */
 +      /* TODO make a hash table */
 +      for (int i = 0; i < storage->ubo_current_id; ++i) {
 +              CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i];
 +
 +              if ((ubo->matcap_rot[0] == cosf(matcap_rot * 3.14159f * 2.0f)) &&
 +                  (ubo->matcap_hsv[0] == matcap_hue + 0.5f) &&
 +                  (ubo->matcap_hsv[1] == matcap_sat * 2.0f) &&
 +                  (ubo->matcap_hsv[2] == matcap_val * 2.0f) &&
 +                  (ubo->ssao_params_var[0] == ssao_distance) &&
 +                  (ubo->ssao_params_var[1] == ssao_factor_cavity) &&
 +                  (ubo->ssao_params_var[2] == ssao_factor_edge) &&
 +                  (ubo->ssao_params_var[3] == ssao_attenuation) &&
 +                  (ubo->matcap_id == matcap_to_index(matcap_icon)))
 +              {
 +                      return i;
 +              }
 +      }
 +
 +      return -1;
 +}
 +
 +static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
 +                            float matcap_val, float ssao_distance, float ssao_factor_cavity,
 +                            float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
 +{
 +      int id = storage->ubo_current_id;
 +      CLAY_UBO_Material *ubo = &storage->mat_storage.materials[id];
 +
 +      ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
 +      ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
 +
 +      ubo->matcap_hsv[0] = matcap_hue + 0.5f;
 +      ubo->matcap_hsv[1] = matcap_sat * 2.0f;
 +      ubo->matcap_hsv[2] = matcap_val * 2.0f;
 +
 +      /* small optimisation : make samples not spread if we don't need ssao */
 +      ubo->ssao_params_var[0] = (ssao_factor_cavity + ssao_factor_edge > 0.0f) ? ssao_distance : 0.0f;
 +      ubo->ssao_params_var[1] = ssao_factor_cavity;
 +      ubo->ssao_params_var[2] = ssao_factor_edge;
 +      ubo->ssao_params_var[3] = ssao_attenuation;
 +
 +      ubo->matcap_id = matcap_to_index(matcap_icon);
 +
 +      storage->ubo_current_id++;
 +
 +      return id;
 +}
 +
 +static int mat_in_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
 +                      float matcap_val, float ssao_distance, float ssao_factor_cavity,
 +                      float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
 +{
 +      /* Search material in UBO */
 +      int id = search_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
 +                                 ssao_distance, ssao_factor_cavity, ssao_factor_edge,
 +                                 ssao_attenuation, matcap_icon);
 +
 +      /* if not found create it */
 +      if (id == -1) {
 +              id = push_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
 +                                   ssao_distance, ssao_factor_cavity, ssao_factor_edge,
 +                                   ssao_attenuation, matcap_icon);
 +      }
 +
 +      return id;
 +}
 +
 +static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
 +{
 +      DRWShadingGroup **shgrps = stl->storage->shgrps;
 +      IDProperty *props = BKE_object_collection_engine_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
 +
 +      /* Default Settings */
 +      float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
 +      float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
 +      float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
 +      float matcap_val = BKE_collection_engine_property_value_get_float(props, "matcap_value");
 +      float ssao_distance = BKE_collection_engine_property_value_get_float(props, "ssao_distance");
 +      float ssao_factor_cavity = BKE_collection_engine_property_value_get_float(props, "ssao_factor_cavity");
 +      float ssao_factor_edge = BKE_collection_engine_property_value_get_float(props, "ssao_factor_edge");
 +      float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation");
 +      int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
 +
 +      int id = mat_in_ubo(stl->storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
 +                          ssao_distance, ssao_factor_cavity, ssao_factor_edge,
 +                          ssao_attenuation, matcap_icon);
 +
 +      if (shgrps[id] == NULL) {
 +              shgrps[id] = CLAY_shgroup_create(vedata, psl->clay_pass, &e_data.ubo_mat_idxs[id]);
 +              /* if it's the first shgrp, pass bind the material UBO */
 +              if (stl->storage->ubo_current_id == 1) {
 +                      DRW_shgroup_uniform_block(shgrps[0], "material_block", stl->mat_ubo, 0);
 +              }
 +      }
 +
 +      return shgrps[id];
 +}
 +
 +static void CLAY_cache_init(void *vedata)
 +{
 +      CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
 +      CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
 +
 +      if (!stl->g_data) {
 +              /* Alloc transient pointers */
 +              stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
 +      }
 +
 +      /* Depth Pass */
 +      {
 +              psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 +              stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
 +
 +              psl->depth_pass_cull = DRW_pass_create(
 +                      "Depth Pass Cull",
 +                      DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
 +              stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
 +      }
 +
 +      /* Clay Pass */
 +      {
 +              psl->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
 +              stl->storage->ubo_current_id = 0;
 +              memset(stl->storage->shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
 +      }
 +}
 +
 +static void CLAY_cache_populate(void *vedata, Object *ob)
 +{
 +      CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
 +      CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
 +
 +      DRWShadingGroup *clay_shgrp;
 +
 +      if (!DRW_is_object_renderable(ob))
 +              return;
 +
 +      struct Batch *geom = DRW_cache_object_surface_get(ob);
 +      if (geom) {
 +              IDProperty *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
 +              bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
 +
 +              /* Depth Prepass */
 +              DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
 +
 +              /* Shading */
 +              clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl);
 +              DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
 +      }
 +}
 +
 +static void CLAY_cache_finish(void *vedata)
 +{
 +      CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
 +
 +      DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage);
 +}
 +
 +static void CLAY_draw_scene(void *vedata)
 +{
 +
 +      CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
 +      CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
 +      DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
 +
 +      /* Pass 1 : Depth pre-pass */
 +      DRW_draw_pass(psl->depth_pass);
 +      DRW_draw_pass(psl->depth_pass_cull);
 +
 +      /* Pass 2 : Duplicate depth */
 +      /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
 +      if (DRW_state_is_fbo()) {
 +              DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true);
 +      }
 +
 +      /* Pass 3 : Shading */
 +      DRW_draw_pass(psl->clay_pass);
 +}
 +
 +static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
 +{
 +      BLI_assert(props &&
 +                 props->type == IDP_GROUP &&
 +                 props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
 +
 +      BKE_collection_engine_property_add_int(props, "matcap_icon", ICON_MATCAP_01);
 +      BKE_collection_engine_property_add_int(props, "type", CLAY_MATCAP_NONE);
 +      BKE_collection_engine_property_add_float(props, "matcap_rotation", 0.0f);
 +      BKE_collection_engine_property_add_float(props, "matcap_hue", 0.5f);
 +      BKE_collection_engine_property_add_float(props, "matcap_saturation", 0.5f);
 +      BKE_collection_engine_property_add_float(props, "matcap_value", 0.5f);
 +      BKE_collection_engine_property_add_float(props, "ssao_distance", 0.2f);
 +      BKE_collection_engine_property_add_float(props, "ssao_attenuation", 1.0f);
 +      BKE_collection_engine_property_add_float(props, "ssao_factor_cavity", 1.0f);
 +      BKE_collection_engine_property_add_float(props, "ssao_factor_edge", 1.0f);
 +}
 +
 +static void CLAY_engine_free(void)
 +{
 +      DRW_SHADER_FREE_SAFE(e_data.clay_sh);
 +      DRW_TEXTURE_FREE_SAFE(e_data.matcap_array);
 +      DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx);
 +      DRW_TEXTURE_FREE_SAFE(e_data.sampling_tx);
 +}
 +
 +static const DrawEngineDataSize CLAY_data_size = DRW_VIEWPORT_DATA_SIZE(CLAY_Data);
 +
 +DrawEngineType draw_engine_clay_type = {
 +      NULL, NULL,
 +      N_("Clay"),
 +      &CLAY_data_size,
 +      &CLAY_engine_init,
 +      &CLAY_engine_free,
 +      &CLAY_cache_init,
 +      &CLAY_cache_populate,
 +      &CLAY_cache_finish,
 +      NULL,
 +      &CLAY_draw_scene
 +};
 +
 +RenderEngineType DRW_engine_viewport_clay_type = {
 +      NULL, NULL,
 +      CLAY_ENGINE, N_("Clay"), RE_INTERNAL,
++      NULL, NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create,
 +      &draw_engine_clay_type,
 +      {NULL, NULL, NULL}
 +};
 +
 +
 +#undef CLAY_ENGINE
 +
 +#endif
index 6572abde728c233581d33458059a8d1d61f75c93,0000000000000000000000000000000000000000..5fbf98e3003278d6cf3d65558ecdf492a531e9b7
mode 100644,000000..100644
--- /dev/null
@@@ -1,721 -1,0 +1,721 @@@
-       NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create,
 +/*
 + * Copyright 2016, Blender Foundation.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + * Contributor(s): Blender Institute
 + *
 + */
 +
 +/** \file eevee_engine.c
 + *  \ingroup draw_engine
 + */
 +
 +#include "DRW_render.h"
 +
 +#include "DNA_world_types.h"
 +
 +#include "BLI_dynstr.h"
 +#include "BLI_rand.h"
 +
 +#include "GPU_material.h"
 +#include "GPU_glew.h"
 +
 +#include "eevee_engine.h"
 +#include "eevee_private.h"
 +#include "eevee_lut.h"
 +
 +#define EEVEE_ENGINE "BLENDER_EEVEE"
 +
 +/* *********** STATIC *********** */
 +static struct {
 +      char *frag_shader_lib;
 +
 +      struct GPUShader *default_lit;
 +      struct GPUShader *default_world;
 +      struct GPUShader *depth_sh;
 +      struct GPUShader *tonemap;
 +      struct GPUShader *shadow_sh;
 +
 +      struct GPUShader *probe_filter_sh;
 +      struct GPUShader *probe_spherical_harmonic_sh;
 +
 +      struct GPUTexture *ltc_mat;
 +      struct GPUTexture *brdf_lut;
 +      struct GPUTexture *hammersley;
 +      struct GPUTexture *jitter;
 +
 +      float camera_pos[3];
 +} e_data = {NULL}; /* Engine data */
 +
 +extern char datatoc_default_frag_glsl[];
 +extern char datatoc_default_world_frag_glsl[];
 +extern char datatoc_ltc_lib_glsl[];
 +extern char datatoc_bsdf_lut_frag_glsl[];
 +extern char datatoc_bsdf_common_lib_glsl[];
 +extern char datatoc_bsdf_direct_lib_glsl[];
 +extern char datatoc_bsdf_sampling_lib_glsl[];
 +extern char datatoc_lit_surface_frag_glsl[];
 +extern char datatoc_lit_surface_vert_glsl[];
 +extern char datatoc_tonemap_frag_glsl[];
 +extern char datatoc_shadow_frag_glsl[];
 +extern char datatoc_shadow_geom_glsl[];
 +extern char datatoc_shadow_vert_glsl[];
 +extern char datatoc_probe_filter_frag_glsl[];
 +extern char datatoc_probe_sh_frag_glsl[];
 +extern char datatoc_probe_geom_glsl[];
 +extern char datatoc_probe_vert_glsl[];
 +
 +extern Material defmaterial;
 +extern GlobalsUboStorage ts;
 +
 +/* Van der Corput sequence */
 + /* From http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html */
 +static float radical_inverse(int i) {
 +      unsigned int bits = (unsigned int)i;
 +      bits = (bits << 16u) | (bits >> 16u);
 +      bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
 +      bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
 +      bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
 +      bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
 +      return (float)bits * 2.3283064365386963e-10f;
 +}
 +
 +static struct GPUTexture *create_hammersley_sample_texture(int samples)
 +{
 +      struct GPUTexture *tex;
 +      float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex");
 +      int i;
 +
 +      for (i = 0; i < samples; i++) {
 +              float phi = radical_inverse(i) * 2.0f * M_PI;
 +              texels[i][0] = cos(phi);
 +              texels[i][1] = sinf(phi);
 +      }
 +
 +      tex = DRW_texture_create_1D(samples, DRW_TEX_RG_16, DRW_TEX_WRAP, (float *)texels);
 +      MEM_freeN(texels);
 +      return tex;
 +}
 +
 +static struct GPUTexture *create_jitter_texture(int w, int h)
 +{
 +      struct GPUTexture *tex;
 +      float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * w * h, "jitter_tex");
 +      int i;
 +
 +      /* TODO replace by something more evenly distributed like blue noise */
 +      for (i = 0; i < w * h; i++) {
 +              texels[i][0] = 2.0f * BLI_frand() - 1.0f;
 +              texels[i][1] = 2.0f * BLI_frand() - 1.0f;
 +              normalize_v2(texels[i]);
 +      }
 +
 +      tex = DRW_texture_create_2D(w, h, DRW_TEX_RG_16, DRW_TEX_WRAP, (float *)texels);
 +      MEM_freeN(texels);
 +      return tex;
 +}
 +
 +static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
 +{
 +      struct GPUTexture *tex;
 +#if 0 /* Used only to generate the LUT values */
 +      struct GPUFrameBuffer *fb = NULL;
 +      static float samples_ct = 8192.0f;
 +      static float inv_samples_ct = 1.0f / 8192.0f;
 +
 +      char *lib_str = NULL;
 +
 +      DynStr *ds_vert = BLI_dynstr_new();
 +      BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
 +      BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl);
 +      lib_str = BLI_dynstr_get_cstring(ds_vert);
 +      BLI_dynstr_free(ds_vert);
 +
 +      struct GPUShader *sh = DRW_shader_create_with_lib(
 +              datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, datatoc_bsdf_lut_frag_glsl, lib_str,
 +              "#define HAMMERSLEY_SIZE 8192\n"
 +              "#define BRDF_LUT_SIZE 64\n"
 +              "#define NOISE_SIZE 64\n");
 +
 +      DRWPass *pass = DRW_pass_create("Probe Filtering", DRW_STATE_WRITE_COLOR);
 +      DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
 +      DRW_shgroup_uniform_float(grp, "sampleCount", &samples_ct, 1);
 +      DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_ct, 1);
 +      DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley, 0);
 +      DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter, 1);
 +
 +      struct Batch *geom = DRW_cache_fullscreen_quad_get();
 +      DRW_shgroup_call_add(grp, geom, NULL);
 +
 +      float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
 +
 +      tex = DRW_texture_create_2D(w, h, DRW_TEX_RG_16, DRW_TEX_FILTER, (float *)texels);
 +
 +      DRWFboTexture tex_filter = {&tex, DRW_BUF_RG_16, DRW_TEX_FILTER};
 +      DRW_framebuffer_init(&fb, w, h, &tex_filter, 1);
 +
 +      DRW_framebuffer_bind(fb);
 +      DRW_draw_pass(pass);
 +
 +      float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
 +      glReadBuffer(GL_COLOR_ATTACHMENT0);
 +      glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
 +
 +      printf("{");
 +      for (int i = 0; i < w*h * 3; i+=3) {
 +              printf("%ff, %ff, ", data[i],  data[i+1]); i+=3;
 +              printf("%ff, %ff, ", data[i],  data[i+1]); i+=3;
 +              printf("%ff, %ff, ", data[i],  data[i+1]); i+=3;
 +              printf("%ff, %ff, \n", data[i],  data[i+1]);
 +      }
 +      printf("}");
 +
 +      MEM_freeN(texels);
 +      MEM_freeN(data);
 +#else
 +      float (*texels)[3] = MEM_mallocN(sizeof(float[3]) * 64 * 64, "bsdf lut texels");
 +
 +      for (int i = 0; i < 64 * 64; i++) {
 +              texels[i][0] = bsdf_split_sum_ggx[i*2 + 0];
 +              texels[i][1] = bsdf_split_sum_ggx[i*2 + 1];
 +              texels[i][2] = ltc_mag_ggx[i];
 +      }
 +
 +      tex = DRW_texture_create_2D(64, 64, DRW_TEX_RGB_16, DRW_TEX_FILTER, (float *)texels);
 +      MEM_freeN(texels);
 +#endif
 +
 +      return tex;
 +}
 +
 +
 +/* *********** FUNCTIONS *********** */
 +
 +static void EEVEE_engine_init(void *ved)
 +{
 +      EEVEE_Data *vedata = (EEVEE_Data *)ved;
 +      EEVEE_TextureList *txl = vedata->txl;
 +      EEVEE_FramebufferList *fbl = vedata->fbl;
 +      EEVEE_StorageList *stl = vedata->stl;
 +
 +      DRWFboTexture tex = {&txl->color, DRW_BUF_RGBA_16, DRW_TEX_FILTER};
 +
 +      const float *viewport_size = DRW_viewport_size_get();
 +      DRW_framebuffer_init(&fbl->main,
 +                          (int)viewport_size[0], (int)viewport_size[1],
 +                          &tex, 1);
 +
 +      if (!e_data.frag_shader_lib) {
 +              DynStr *ds_frag = BLI_dynstr_new();
 +              BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
 +              BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
 +              BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
 +              BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
 +              e_data.frag_shader_lib = BLI_dynstr_get_cstring(ds_frag);
 +              BLI_dynstr_free(ds_frag);
 +      }
 +
 +      if (!e_data.depth_sh) {
 +              e_data.depth_sh = DRW_shader_create_3D_depth_only();
 +      }
 +
 +      if (!e_data.default_lit) {
 +              char *frag_str = NULL;
 +
 +              DynStr *ds_frag = BLI_dynstr_new();
 +              BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
 +              BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl);
 +              frag_str = BLI_dynstr_get_cstring(ds_frag);
 +              BLI_dynstr_free(ds_frag);
 +
 +              e_data.default_lit = DRW_shader_create(
 +                      datatoc_lit_surface_vert_glsl, NULL, frag_str,
 +                      "#define MAX_LIGHT 128\n"
 +                      "#define MAX_SHADOW_CUBE 42\n"
 +                      "#define MAX_SHADOW_MAP 64\n"
 +                      "#define MAX_SHADOW_CASCADE 8\n"
 +                      "#define MAX_CASCADE_NUM 4\n");
 +
 +              MEM_freeN(frag_str);
 +      }
 +
 +      if (!e_data.shadow_sh) {
 +              e_data.shadow_sh = DRW_shader_create(
 +                      datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL);
 +      }
 +
 +      if (!e_data.default_world) {
 +              e_data.default_world = DRW_shader_create(
 +                      datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, datatoc_default_world_frag_glsl, NULL);
 +      }
 +
 +      if (!e_data.probe_filter_sh) {
 +              char *shader_str = NULL;
 +
 +              DynStr *ds_frag = BLI_dynstr_new();
 +              BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
 +              BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
 +              BLI_dynstr_append(ds_frag, datatoc_probe_filter_frag_glsl);
 +              shader_str = BLI_dynstr_get_cstring(ds_frag);
 +              BLI_dynstr_free(ds_frag);
 +
 +              e_data.probe_filter_sh = DRW_shader_create(
 +                      datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, shader_str,
 +                      "#define HAMMERSLEY_SIZE 8192\n"
 +                      "#define NOISE_SIZE 64\n");
 +
 +              MEM_freeN(shader_str);
 +      }
 +
 +      if (!e_data.probe_spherical_harmonic_sh) {
 +              e_data.probe_spherical_harmonic_sh = DRW_shader_create_fullscreen(datatoc_probe_sh_frag_glsl, NULL);
 +      }
 +
 +      if (!e_data.tonemap) {
 +              e_data.tonemap = DRW_shader_create_fullscreen(datatoc_tonemap_frag_glsl, NULL);
 +      }
 +
 +      if (!e_data.ltc_mat) {
 +              e_data.ltc_mat = DRW_texture_create_2D(64, 64, DRW_TEX_RGBA_16, DRW_TEX_FILTER, ltc_mat_ggx);
 +      }
 +
 +      if (!e_data.hammersley) {
 +              e_data.hammersley = create_hammersley_sample_texture(8192);
 +      }
 +
 +      if (!e_data.jitter) {
 +              e_data.jitter = create_jitter_texture(64, 64);
 +      }
 +
 +      if (!e_data.brdf_lut) {
 +              e_data.brdf_lut = create_ggx_lut_texture(64, 64);
 +      }
 +
 +      {
 +              float viewinvmat[4][4];
 +              DRW_viewport_matrix_get(viewinvmat, DRW_MAT_VIEWINV);
 +
 +              copy_v3_v3(e_data.camera_pos, viewinvmat[3]);
 +      }
 +
 +      EEVEE_lights_init(stl);
 +
 +      EEVEE_probes_init(vedata);
 +
 +      // EEVEE_lights_update(stl);
 +}
 +
 +static DRWShadingGroup *eevee_cube_shgroup(struct GPUShader *sh, DRWPass *pass, struct Batch *geom)
 +{
 +      DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
 +
 +      for (int i = 0; i < 6; ++i)
 +              DRW_shgroup_call_dynamic_add_empty(grp);
 +
 +      return grp;
 +}
 +
 +static DRWShadingGroup *eevee_cube_shadow_shgroup(
 +        EEVEE_PassList *psl, EEVEE_StorageList *stl, struct Batch *geom, float (*obmat)[4])
 +{
 +      DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cube_pass, geom);
 +      DRW_shgroup_uniform_block(grp, "shadow_render_block", stl->shadow_render_ubo, 0);
 +      DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
 +
 +      for (int i = 0; i < 6; ++i)
 +              DRW_shgroup_call_dynamic_add_empty(grp);
 +
 +      return grp;
 +}
 +
 +static DRWShadingGroup *eevee_cascade_shadow_shgroup(
 +        EEVEE_PassList *psl, EEVEE_StorageList *stl, struct Batch *geom, float (*obmat)[4])
 +{
 +      DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cascade_pass, geom);
 +      DRW_shgroup_uniform_block(grp, "shadow_render_block", stl->shadow_render_ubo, 0);
 +      DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
 +
 +      for (int i = 0; i < MAX_CASCADE_NUM; ++i)
 +              DRW_shgroup_call_dynamic_add_empty(grp);
 +
 +      return grp;
 +}
 +
 +static void EEVEE_cache_init(void *vedata)
 +{
 +      static int zero = 0;
 +
 +      EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
 +      EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
 +      EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
 +
 +      if (!stl->g_data) {
 +              /* Alloc transient pointers */
 +              stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
 +      }
 +
 +      {
 +              psl->shadow_cube_pass = DRW_pass_create("Shadow Cube Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 +      }
 +
 +      {
 +              psl->shadow_cascade_pass = DRW_pass_create("Shadow Cascade Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 +      }
 +
 +      {
 +              // psl->shadow_pass = DRW_pass_create("Shadow Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 +              // stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
 +              // DRW_shgroup_uniform_mat4(stl->g_data->shadow_shgrp, "ShadowMatrix", (float *)stl->lamps->shadowmat);
 +              // DRW_shgroup_uniform_int(stl->g_data->shadow_shgrp, "Layer", &stl->lamps->layer, 1);
 +      }
 +
 +      {
 +              psl->probe_background = DRW_pass_create("Probe Background Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR);
 +
 +              struct Batch *geom = DRW_cache_fullscreen_quad_get();
 +              DRWShadingGroup *grp = NULL;
 +
 +              const DRWContextState *draw_ctx = DRW_context_state_get();
 +              Scene *scene = draw_ctx->scene;
 +              World *wo = scene->world;
 +
 +              float *col = ts.colorBackground;
 +              if (wo) {
 +                      col = &wo->horr;
 +              }
 +
 +              if (wo && wo->use_nodes && wo->nodetree) {
 +                      struct GPUMaterial *gpumat = GPU_material_from_nodetree(
 +                              scene, wo->nodetree, &wo->gpumaterial, &DRW_engine_viewport_eevee_type, 0,
 +                          datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, e_data.frag_shader_lib,
 +                          "#define PROBE_CAPTURE\n"
 +                          "#define MAX_LIGHT 128\n"
 +                          "#define MAX_SHADOW_CUBE 42\n"
 +                          "#define MAX_SHADOW_MAP 64\n"
 +                          "#define MAX_SHADOW_CASCADE 8\n"
 +                          "#define MAX_CASCADE_NUM 4\n");
 +
 +                      grp = DRW_shgroup_material_instance_create(gpumat, psl->probe_background, geom);
 +
 +                      if (grp) {
 +                              DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
 +
 +                              for (int i = 0; i < 6; ++i)
 +                                      DRW_shgroup_call_dynamic_add_empty(grp);
 +                      }
 +                      else {
 +                              /* Shader failed : pink background */
 +                              static float pink[3] = {1.0f, 0.0f, 1.0f};
 +                              col = pink;
 +                      }
 +              }
 +
 +              /* Fallback if shader fails or if not using nodetree. */
 +              if (grp == NULL) {
 +                      grp = eevee_cube_shgroup(e_data.default_world, psl->probe_background, geom);
 +                      DRW_shgroup_uniform_vec3(grp, "color", col, 1);
 +                      DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
 +              }
 +      }
 +
 +      {
 +              psl->probe_prefilter = DRW_pass_create("Probe Filtering", DRW_STATE_WRITE_COLOR);
 +
 +              struct Batch *geom = DRW_cache_fullscreen_quad_get();
 +              DRWShadingGroup *grp = eevee_cube_shgroup(e_data.probe_filter_sh, psl->probe_prefilter, geom);
 +              DRW_shgroup_uniform_float(grp, "sampleCount", &stl->probes->samples_ct, 1);
 +              DRW_shgroup_uniform_float(grp, "invSampleCount", &stl->probes->invsamples_ct, 1);
 +              DRW_shgroup_uniform_float(grp, "roughnessSquared", &stl->probes->roughness, 1);
 +              DRW_shgroup_uniform_float(grp, "lodFactor", &stl->probes->lodfactor, 1);
 +              DRW_shgroup_uniform_float(grp, "lodMax", &stl->probes->lodmax, 1);
 +              DRW_shgroup_uniform_int(grp, "Layer", &stl->probes->layer, 1);
 +              DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley, 0);
 +              // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter, 1);
 +              DRW_shgroup_uniform_texture(grp, "probeHdr", txl->probe_rt, 3);
 +      }
 +
 +      {
 +              psl->probe_sh_compute = DRW_pass_create("Probe SH Compute", DRW_STATE_WRITE_COLOR);
 +
 +              DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_spherical_harmonic_sh, psl->probe_sh_compute);
 +              DRW_shgroup_uniform_int(grp, "probeSize", &stl->probes->shres, 1);
 +              DRW_shgroup_uniform_float(grp, "lodBias", &stl->probes->lodfactor, 1);
 +              DRW_shgroup_uniform_texture(grp, "probeHdr", txl->probe_rt, 0);
 +
 +              struct Batch *geom = DRW_cache_fullscreen_quad_get();
 +              DRW_shgroup_call_add(grp, geom, NULL);
 +      }
 +
 +      {
 +              psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 +              stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
 +
 +              psl->depth_pass_cull = DRW_pass_create(
 +                      "Depth Pass Cull",
 +                      DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
 +              stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
 +      }
 +
 +      {
 +              DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
 +              psl->default_pass = DRW_pass_create("Default Shader Pass", state);
 +
 +              /* NOTE : this shading grp does not contain any geom, it's just here to setup uniforms & textures. */
 +              stl->g_data->default_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->default_pass);
 +              DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "light_block", stl->light_ubo, 0);
 +              DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "shadow_block", stl->shadow_ubo, 1);
 +              DRW_shgroup_uniform_int(stl->g_data->default_lit_grp, "light_count", &stl->lamps->num_light, 1);
 +              DRW_shgroup_uniform_float(stl->g_data->default_lit_grp, "lodMax", &stl->probes->lodmax, 1);
 +              DRW_shgroup_uniform_vec3(stl->g_data->default_lit_grp, "shCoefs[0]", (float *)stl->probes->shcoefs, 9);
 +              DRW_shgroup_uniform_vec3(stl->g_data->default_lit_grp, "cameraPos", e_data.camera_pos, 1);
 +              DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMat", e_data.ltc_mat, 0);
 +              DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "brdfLut", e_data.brdf_lut, 1);
 +              DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "probeFiltered", txl->probe_pool, 2);
 +              /* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */
 +      }
 +
 +      {
 +              DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
 +              psl->material_pass = DRW_pass_create("Material Shader Pass", state);
 +      }
 +
 +      {
 +              /* Final pass : Map HDR color to LDR color.
 +               * Write result to the default color buffer */
 +              psl->tonemap = DRW_pass_create("Tone Mapping", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
 +
 +              DRWShadingGroup *grp = DRW_shgroup_create(e_data.tonemap, psl->tonemap);
 +              DRW_shgroup_uniform_buffer(grp, "hdrColorBuf", &txl->color, 0);
 +
 +              struct Batch *geom = DRW_cache_fullscreen_quad_get();
 +              DRW_shgroup_call_add(grp, geom, NULL);
 +      }
 +
 +      EEVEE_lights_cache_init(stl);
 +}
 +
 +static void EEVEE_cache_populate(void *vedata, Object *ob)
 +{
 +      EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
 +      EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
 +      EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
 +
 +      struct Batch *geom = DRW_cache_object_surface_get(ob);
 +      if (geom) {
 +              IDProperty *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
 +              const bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
 +
 +              /* Depth Prepass */
 +              DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
 +
 +              /* Get per-material split surface */
 +              struct Batch **mat_geom = DRW_cache_object_surface_material_get(ob);
 +              if (mat_geom) {
 +                      for (int i = 0; i < MAX2(1, ob->totcol); ++i) {
 +                              Material *ma = give_current_material(ob, i + 1);
 +
 +                              if (ma == NULL)
 +                                      ma = &defmaterial;
 +
 +                              if (ma->use_nodes && ma->nodetree) {
 +                                      const DRWContextState *draw_ctx = DRW_context_state_get();
 +                                      Scene *scene = draw_ctx->scene;
 +                                      struct GPUMaterial *gpumat = GPU_material_from_nodetree(
 +                                          scene, ma->nodetree, &ma->gpumaterial, &DRW_engine_viewport_eevee_type, 0,
 +                                          datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
 +                                          "#define PROBE_CAPTURE\n"
 +                                          "#define MAX_LIGHT 128\n"
 +                                          "#define MAX_SHADOW_CUBE 42\n"
 +                                          "#define MAX_SHADOW_MAP 64\n"
 +                                          "#define MAX_SHADOW_CASCADE 8\n"
 +                                          "#define MAX_CASCADE_NUM 4\n");
 +
 +                                      DRWShadingGroup *shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass);
 +
 +                                      if (shgrp) {
 +                                              DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
 +
 +                                              DRW_shgroup_uniform_block(shgrp, "light_block", stl->light_ubo, 0);
 +                                              DRW_shgroup_uniform_block(shgrp, "shadow_block", stl->shadow_ubo, 1);
 +                                              DRW_shgroup_uniform_int(shgrp, "light_count", &stl->lamps->num_light, 1);
 +                                              DRW_shgroup_uniform_float(shgrp, "lodMax", &stl->probes->lodmax, 1);
 +                                              DRW_shgroup_uniform_vec3(shgrp, "shCoefs[0]", (float *)stl->probes->shcoefs, 9);
 +                                              DRW_shgroup_uniform_vec3(shgrp, "cameraPos", e_data.camera_pos, 1);
 +                                              DRW_shgroup_uniform_texture(shgrp, "ltcMat", e_data.ltc_mat, 0);
 +                                              DRW_shgroup_uniform_texture(shgrp, "brdfLut", e_data.brdf_lut, 1);
 +                                              DRW_shgroup_uniform_texture(shgrp, "probeFiltered", txl->probe_pool, 2);
 +                                      }
 +                                      else {
 +                                              /* Shader failed : pink color */
 +                                              static float col[3] = {1.0f, 0.0f, 1.0f};
 +                                              static float spec[3] = {1.0f, 0.0f, 1.0f};
 +                                              static short hardness = 1;
 +                                              shgrp = DRW_shgroup_create(e_data.default_lit, psl->default_pass);
 +                                              DRW_shgroup_uniform_vec3(shgrp, "diffuse_col", col, 1);
 +                                              DRW_shgroup_uniform_vec3(shgrp, "specular_col", spec, 1);
 +                                              DRW_shgroup_uniform_short(shgrp, "hardness", &hardness, 1);
 +                                              DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
 +                                      }
 +                              }
 +                              else {
 +                                      DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit, psl->default_pass);
 +                                      DRW_shgroup_uniform_vec3(shgrp, "diffuse_col", &ma->r, 1);
 +                                      DRW_shgroup_uniform_vec3(shgrp, "specular_col", &ma->specr, 1);
 +                                      DRW_shgroup_uniform_short(shgrp, "hardness", &ma->har, 1);
 +                                      DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
 +                              }
 +
 +                      }
 +              }
 +              else {
 +                      /* TODO, support for all geometry types (non mesh geometry) */
 +                      DRW_shgroup_call_add(stl->g_data->default_lit_grp, geom, ob->obmat);
 +                      // DRW_shgroup_call_add(stl->g_data->shadow_shgrp, geom, ob->obmat);
 +                      eevee_cascade_shadow_shgroup(psl, stl, geom, ob->obmat);
 +                      eevee_cube_shadow_shgroup(psl, stl, geom, ob->obmat);
 +              }
 +              // GPUMaterial *gpumat = GPU_material_from_nodetree(struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options)
 +
 +              // DRW_shgroup_call_add(stl->g_data->shadow_shgrp, geom, ob->obmat);
 +              eevee_cascade_shadow_shgroup(psl, stl, geom, ob->obmat);
 +              eevee_cube_shadow_shgroup(psl, stl, geom, ob->obmat);
 +      }
 +      else if (ob->type == OB_LAMP) {
 +              EEVEE_lights_cache_add(stl, ob);
 +      }
 +}
 +
 +typedef struct eevee_bind_shadow_data {
 +      struct GPUTexture *shadow_depth_map_pool;
 +      struct GPUTexture *shadow_depth_cube_pool;
 +      struct GPUTexture *shadow_depth_cascade_pool;
 +} eevee_bind_shadow_data;
 +
 +static void eevee_bind_shadow(void *data, DRWShadingGroup *shgrp)
 +{
 +      eevee_bind_shadow_data *shdw_data = data;
 +      DRW_shgroup_uniform_texture(shgrp, "shadowMaps", shdw_data->shadow_depth_map_pool, 3);
 +      DRW_shgroup_uniform_texture(shgrp, "shadowCubes", shdw_data->shadow_depth_cube_pool, 4);
 +      DRW_shgroup_uniform_texture(shgrp, "shadowCascades", shdw_data->shadow_depth_cascade_pool, 5);
 +}
 +
 +static void EEVEE_cache_finish(void *vedata)
 +{
 +      EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
 +      EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
 +      EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
 +      EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
 +
 +      EEVEE_lights_cache_finish(stl, txl, fbl);
 +
 +      /* Shadows binding */
 +      eevee_bind_shadow_data data;
 +
 +      data.shadow_depth_map_pool = txl->shadow_depth_map_pool;
 +      data.shadow_depth_cube_pool = txl->shadow_depth_cube_pool;
 +      data.shadow_depth_cascade_pool = txl->shadow_depth_cascade_pool;
 +
 +      DRW_pass_foreach_shgroup(psl->default_pass, eevee_bind_shadow, &data);
 +      DRW_pass_foreach_shgroup(psl->material_pass, eevee_bind_shadow, &data);
 +}
 +
 +static void EEVEE_draw_scene(void *vedata)
 +{
 +      EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
 +      EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
 +
 +      /* Default framebuffer and texture */
 +      DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
 +      DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
 +
 +      /* Refresh Probes */
 +      EEVEE_refresh_probe((EEVEE_Data *)vedata);
 +
 +      /* Refresh shadows */
 +      EEVEE_draw_shadows((EEVEE_Data *)vedata);
 +
 +      /* Attach depth to the hdr buffer and bind it */        
 +      DRW_framebuffer_texture_detach(dtxl->depth);
 +      DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
 +      DRW_framebuffer_bind(fbl->main);
 +
 +      /* Clear Depth */
 +      /* TODO do background */
 +      // float clearcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
 +      // DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
 +      DRW_draw_background();
 +
 +      DRW_draw_pass(psl->depth_pass);
 +      DRW_draw_pass(psl->depth_pass_cull);
 +      DRW_draw_pass(psl->default_pass);
 +      DRW_draw_pass(psl->material_pass);
 +
 +      /* Restore default framebuffer */
 +      DRW_framebuffer_texture_detach(dtxl->depth);
 +      DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
 +      DRW_framebuffer_bind(dfbl->default_fb);
 +
 +      DRW_draw_pass(psl->tonemap);
 +}
 +
 +static void EEVEE_engine_free(void)
 +{
 +      MEM_SAFE_FREE(e_data.frag_shader_lib);
 +      DRW_SHADER_FREE_SAFE(e_data.default_lit);
 +      DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
 +      DRW_SHADER_FREE_SAFE(e_data.default_world);
 +      DRW_SHADER_FREE_SAFE(e_data.probe_filter_sh);
 +      DRW_SHADER_FREE_SAFE(e_data.probe_spherical_harmonic_sh);
 +      DRW_SHADER_FREE_SAFE(e_data.tonemap);
 +      DRW_TEXTURE_FREE_SAFE(e_data.ltc_mat);
 +      DRW_TEXTURE_FREE_SAFE(e_data.brdf_lut);
 +      DRW_TEXTURE_FREE_SAFE(e_data.hammersley);
 +      DRW_TEXTURE_FREE_SAFE(e_data.jitter);
 +}
 +
 +static void EEVEE_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
 +{
 +      BLI_assert(props &&
 +                 props->type == IDP_GROUP &&
 +                 props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
 +      // BKE_collection_engine_property_add_int(props, "high_quality_sphere_lamps", false);
 +}
 +
 +static const DrawEngineDataSize EEVEE_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data);
 +
 +DrawEngineType draw_engine_eevee_type = {
 +      NULL, NULL,
 +      N_("Eevee"),
 +      &EEVEE_data_size,
 +      &EEVEE_engine_init,
 +      &EEVEE_engine_free,
 +      &EEVEE_cache_init,
 +      &EEVEE_cache_populate,
 +      &EEVEE_cache_finish,
 +      &EEVEE_draw_scene,
 +      NULL//&EEVEE_draw_scene
 +};
 +
 +RenderEngineType DRW_engine_viewport_eevee_type = {
 +      NULL, NULL,
 +      EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES,
++      NULL, NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create,
 +      &draw_engine_eevee_type,
 +      {NULL, NULL, NULL}
 +};
 +
 +
 +#undef EEVEE_ENGINE
index 5c7f507b34b91822bd4ef6b8d5b505e9cbd297a6,0000000000000000000000000000000000000000..7b6b4e5114700268bd09ab8a6781f5d6d65a3d86
mode 100644,000000..100644
--- /dev/null
@@@ -1,222 -1,0 +1,222 @@@
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 +/*
 + * Copyright 2017, Blender Foundation.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + * Contributor(s): Blender Institute
 + *
 + */
 +
 +/** \file external_engine.h
 + *  \ingroup draw_engine
 + *
 + * Base engine for external render engines.
 + * We use it for depth and non-mesh objects.
 + */
 +
 +#include "DRW_render.h"
 +
 +#include "DNA_screen_types.h"
 +#include "DNA_view3d_types.h"
 +
 +#include "BKE_icons.h"
 +#include "BKE_idprop.h"
 +#include "BKE_main.h"
 +
 +#include "ED_view3d.h"
 +#include "ED_screen.h"
 +
 +#include "GPU_glew.h"
 +#include "GPU_matrix.h"
 +#include "GPU_shader.h"
 +#include "GPU_viewport.h"
 +
 +#include "external_engine.h"
 +/* Shaders */
 +
 +#define EXTERNAL_ENGINE "BLENDER_EXTERNAL"
 +
 +/* *********** LISTS *********** */
 +
 +/* GPUViewport.storage
 + * Is freed everytime the viewport engine changes */
 +typedef struct EXTERNAL_Storage {
 +      int dummy;
 +} EXTERNAL_Storage;
 +
 +typedef struct EXTERNAL_StorageList {
 +      struct EXTERNAL_Storage *storage;
 +      struct EXTERNAL_PrivateData *g_data;
 +} EXTERNAL_StorageList;
 +
 +typedef struct EXTERNAL_FramebufferList {
 +      struct GPUFrameBuffer *default_fb;
 +} EXTERNAL_FramebufferList;
 +
 +typedef struct EXTERNAL_TextureList {
 +      /* default */
 +      struct GPUTexture *depth;
 +} EXTERNAL_TextureList;
 +
 +typedef struct EXTERNAL_PassList {
 +      struct DRWPass *depth_pass;
 +} EXTERNAL_PassList;
 +
 +typedef struct EXTERNAL_Data {
 +      void *engine_type;
 +      EXTERNAL_FramebufferList *fbl;
 +      EXTERNAL_TextureList *txl;
 +      EXTERNAL_PassList *psl;
 +      EXTERNAL_StorageList *stl;
 +} EXTERNAL_Data;
 +
 +/* *********** STATIC *********** */
 +
 +static struct {
 +      /* Depth Pre Pass */
 +      struct GPUShader *depth_sh;
 +} e_data = {NULL}; /* Engine data */
 +
 +typedef struct EXTERNAL_PrivateData {
 +      DRWShadingGroup *depth_shgrp;
 +} EXTERNAL_PrivateData; /* Transient data */
 +
 +/* Functions */
 +
 +static void EXTERNAL_engine_init(void *UNUSED(vedata))
 +{
 +      /* Depth prepass */
 +      if (!e_data.depth_sh) {
 +              e_data.depth_sh = DRW_shader_create_3D_depth_only();
 +      }
 +}
 +
 +static void EXTERNAL_cache_init(void *vedata)
 +{
 +      EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl;
 +      EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl;
 +
 +      if (!stl->g_data) {
 +              /* Alloc transient pointers */
 +              stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
 +      }
 +
 +      /* Depth Pass */
 +      {
 +              psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
 +              stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
 +      }
 +}
 +
 +static void EXTERNAL_cache_populate(void *vedata, Object *ob)
 +{
 +      EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl;
 +
 +      if (!DRW_is_object_renderable(ob))
 +              return;
 +
 +      struct Batch *geom = DRW_cache_object_surface_get(ob);
 +      if (geom) {
 +              /* Depth Prepass */
 +              DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat);
 +      }
 +}
 +
 +static void EXTERNAL_cache_finish(void *UNUSED(vedata))
 +{
 +}
 +
 +static void external_draw_scene(void *UNUSED(vedata))
 +{
 +      const DRWContextState *draw_ctx = DRW_context_state_get();
 +      Scene *scene = draw_ctx->scene;
 +      RegionView3D *rv3d = draw_ctx->rv3d;
 +      ARegion *ar = draw_ctx->ar;
 +      RenderEngineType *type;
 +
 +      DRW_state_reset_ex(DRW_STATE_DEFAULT & ~DRW_STATE_DEPTH_LESS);
 +
 +      /* Create render engine. */
 +      if (!rv3d->render_engine) {
 +              RenderEngine *engine;
 +              type = RE_engines_find(scene->r.engine);
 +
 +              if (!(type->view_update && type->render_to_view)) {
 +                      return;
 +              }
 +
 +              engine = RE_engine_create_ex(type, true);
 +              engine->tile_x = scene->r.tilex;
 +              engine->tile_y = scene->r.tiley;
 +              type->view_update(engine, draw_ctx->evil_C);
 +              rv3d->render_engine = engine;
 +      }
 +
 +      /* Rendered draw. */
 +      gpuPushProjectionMatrix();
 +      ED_region_pixelspace(ar);
 +
 +      /* Render result draw. */
 +      type = rv3d->render_engine->type;
 +      type->render_to_view(rv3d->render_engine, draw_ctx->evil_C);
 +
 +      gpuPopProjectionMatrix();
 +}
 +
 +static void EXTERNAL_draw_scene(void *vedata)
 +{
 +      const DRWContextState *draw_ctx = DRW_context_state_get();
 +      EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl;
 +
 +      /* Will be NULL during OpenGL render.
 +       * OpenGL render is used for quick preview (thumbnails or sequencer preview)
 +       * where using the rendering engine to preview doesn't make so much sense. */
 +      if (draw_ctx->evil_C) {
 +              external_draw_scene(vedata);
 +      }
 +      DRW_draw_pass(psl->depth_pass);
 +}
 +
 +static void EXTERNAL_engine_free(void)
 +{
 +      /* All shaders are builtin. */
 +}
 +
 +static const DrawEngineDataSize EXTERNAL_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data);
 +
 +DrawEngineType draw_engine_external_type = {
 +      NULL, NULL,
 +      N_("External"),
 +      &EXTERNAL_data_size,
 +      &EXTERNAL_engine_init,
 +      &EXTERNAL_engine_free,
 +      &EXTERNAL_cache_init,
 +      &EXTERNAL_cache_populate,
 +      &EXTERNAL_cache_finish,
 +      NULL,
 +      &EXTERNAL_draw_scene
 +};
 +
 +/* Note: currently unused, we should not register unless we want to see this when debugging the view. */
 +
 +RenderEngineType DRW_engine_viewport_external_type = {
 +      NULL, NULL,
 +      EXTERNAL_ENGINE, N_("External"), RE_INTERNAL,
++      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 +      &draw_engine_external_type,
 +      {NULL, NULL, NULL}
 +};
 +
 +#undef EXTERNAL_ENGINE
index 69dea2a46c203d272c427d56ec8c4987b8e01723,129cc591d9f0de41b4ae6434cb462f0ac656c55e..1819f11d292571de5b4548120bbaae7bd78caac0
@@@ -264,23 -251,24 +254,41 @@@ static void engine_update_script_node(R
        RNA_parameter_list_free(&list);
  }
  
 +static void engine_collection_settings_create(RenderEngine *engine, struct IDProperty *props)
 +{
 +      extern FunctionRNA rna_RenderEngine_collection_settings_create_func;
 +      PointerRNA ptr;
 +      ParameterList list;
 +      FunctionRNA *func;
 +
 +      RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
 +      func = &rna_RenderEngine_collection_settings_create_func;
 +
 +      RNA_parameter_list_create(&list, &ptr, func);
 +      RNA_parameter_set_lookup(&list, "props", &props);
 +      engine->type->ext.call(NULL, &ptr, func, &list);
 +
 +      RNA_parameter_list_free(&list);
 +}
 +
+ static void engine_update_render_passes(RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl)
+ {
+       extern FunctionRNA rna_RenderEngine_update_render_passes_func;
+       PointerRNA ptr;
+       ParameterList list;
+       FunctionRNA *func;
+       RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
+       func = &rna_RenderEngine_update_render_passes_func;
+       RNA_parameter_list_create(&list, &ptr, func);
+       RNA_parameter_set_lookup(&list, "scene", &scene);
+       RNA_parameter_set_lookup(&list, "renderlayer", &srl);
+       engine->type->ext.call(NULL, &ptr, func, &list);
+       RNA_parameter_list_free(&list);
+ }
  /* RenderEngine registration */
  
  static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
@@@ -301,7 -289,7 +309,7 @@@ static StructRNA *rna_RenderEngine_regi
        RenderEngineType *et, dummyet = {NULL};
        RenderEngine dummyengine = {NULL};
        PointerRNA dummyptr;
--      int have_function[7];
++      int have_function[8];
  
        /* setup dummy engine & engine type to store static properties in */
        dummyengine.type = &dummyet;
        RNA_struct_blender_type_set(et->ext.srna, et);
  
        et->update = (have_function[0]) ? engine_update : NULL;
 -      et->render = (have_function[1]) ? engine_render : NULL;
 +      et->render_to_image = (have_function[1]) ? engine_render_to_image : NULL;
        et->bake = (have_function[2]) ? engine_bake : NULL;
        et->view_update = (have_function[3]) ? engine_view_update : NULL;
 -      et->view_draw = (have_function[4]) ? engine_view_draw : NULL;
 +      et->render_to_view = (have_function[4]) ? engine_render_to_view : NULL;
        et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
-       et->collection_settings_create = (have_function[6]) ? engine_collection_settings_create : NULL;
+       et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL;
++      et->collection_settings_create = (have_function[7]) ? engine_collection_settings_create : NULL;
  
 -      BLI_addtail(&R_engines, et);
 +      RE_engines_register(bmain, et);
  
        return et->ext.srna;
  }
@@@ -511,13 -510,6 +532,19 @@@ static void rna_def_render_engine(Blend
        parm = RNA_def_pointer(func, "node", "Node", "", "");
        RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
  
++      func = RNA_def_function(srna, "update_render_passes", NULL);
++      RNA_def_function_ui_description(func, "Update the render passes that will be generated");
++      RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
++      parm = RNA_def_pointer(func, "scene", "Scene", "", "");
++      parm = RNA_def_pointer(func, "renderlayer", "SceneRenderLayer", "", "");
++
 +      /* per-collection engine settings initialization */
 +      func = RNA_def_function(srna, "collection_settings_create", NULL);
 +      RNA_def_function_ui_description(func, "Create the per collection settings for the engine");
 +      RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
 +      parm = RNA_def_pointer(func, "collection_settings", "LayerCollectionSettings", "", "");
 +      RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
 +
        /* tag for redraw */
        func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw");
        RNA_def_function_ui_description(func, "Request redraw for viewport rendering");
index a37c760f9d0a2646826f17ddaa0dad1be48e278a,dd30cb0d03f3a9fe55bab77da16ef25ee3121f38..2703faf803620a931182c083ac3fc1395a5b9d8c
@@@ -462,8 -448,8 +462,9 @@@ EnumPropertyItem rna_enum_layer_collect
  #include "BKE_colortools.h"
  #include "BKE_context.h"
  #include "BKE_global.h"
+ #include "BKE_idprop.h"
  #include "BKE_image.h"
 +#include "BKE_layer.h"
  #include "BKE_main.h"
  #include "BKE_node.h"
  #include "BKE_pointcache.h"
Simple merge
index 024d8296b8f8cb48e32b5d402550969562e73957,a12bdd910c39b6f2b871fa8c5dfe48d4107bbe29..282942709f01fdebe85448e2f712cd80d0b0174d
@@@ -34,8 -34,8 +34,9 @@@ set(IN
        ../depsgraph
        ../makesdna
        ../makesrna
+       ../nodes
        ../physics
 +      ../draw
        ../../../intern/atomic
        ../../../intern/guardedalloc
        ../../../intern/mikktspace
index b1add4ee168e5498b76fdc57fee49eafd392f22d,491d44b3a4e576e6ef966735a27f84a77b9608fa..1384809389978a331cd223e7e11398db563a0647
@@@ -92,21 -88,16 +92,22 @@@ 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, struct Scene *scene);
 +      void (*render_to_image)(struct RenderEngine *engine, struct Depsgraph *depsgraph);
 +      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 (*view_update)(struct RenderEngine *engine, const struct bContext *context);
 -      void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
 +      void (*render_to_view)(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 (*collection_settings_create)(struct RenderEngine *engine, struct IDProperty *props);
 +
 +      struct DrawEngineType *draw_engine;
 +
        /* RNA integration */
        ExtensionRNA ext;
  } RenderEngineType;
index 059feae71bc12cf974b22eb021f8ca0d203b1d2c,97413c31e1618516a194037e3e41cef6bd1a746f..8b9e4a3eff5180f9049bf8d993bbbc6fa31c85fb
@@@ -72,8 -68,8 +73,8 @@@
  
  static RenderEngineType internal_render_type = {
        NULL, NULL,
 -      "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
 -      NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes,
 +      "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL | RE_USE_LEGACY_PIPELINE,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++      NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes, NULL, NULL,
        {NULL, NULL, NULL}
  };
  
@@@ -81,8 -77,8 +82,8 @@@
  
  static RenderEngineType internal_game_type = {
        NULL, NULL,
 -      "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
 -      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 +      "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME | RE_USE_LEGACY_PIPELINE,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        {NULL, NULL, NULL}
  };
  
index 9a25e0131a54822016a49694c4e639210d9394fb,bbff6790c79841be33446450d43c84f2eb788245..0ab0059fd079865799f6573c8e41de18c77b2f9d
@@@ -693,13 -680,8 +695,14 @@@ void RE_point_density_free(struct Point
  void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
  void RE_FreeAllPersistentData(void) RET_NONE
  float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
+ void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int channels, const char *chanid, int type) RET_NONE
  
 +/* Draw */
 +void OBJECT_collection_settings_create(struct IDProperty *properties) RET_NONE
 +void EDIT_MESH_collection_settings_create(struct IDProperty *properties) RET_NONE
 +void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties) RET_NONE
 +void DRW_object_engine_data_free(struct Object *ob) RET_NONE
 +
  /* python */
  struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
  void WM_operatortype_iter(struct GHashIterator *ghi) RET_NONE