[Bf-blender-cvs] [5ec79879491] master: DrawManager: External Engine Depth Buffer

Jeroen Bakker noreply at git.blender.org
Thu May 2 15:11:38 CEST 2019


Commit: 5ec79879491331c499642ea6635a4bd456b84460
Author: Jeroen Bakker
Date:   Wed May 1 12:31:59 2019 +0200
Branches: master
https://developer.blender.org/rB5ec79879491331c499642ea6635a4bd456b84460

DrawManager: External Engine Depth Buffer

Only draw the depth buffer when overlays are enabled and scene
or view has changed.

When using Cycles in the viewport for every viewport draw call
the depth buffer was renewed. Draw calls happened when a sample
was finished or the status report was updated.

This could waist some CPU/GPU cycles. This change will check when
the depth buffer needs to be updated or when the last known depth
buffer could be reused.

Reviewers: brecht, fclem

Maniphest Tasks: T63525

Differential Revision: https://developer.blender.org/D4775

===================================================================

M	source/blender/draw/engines/external/external_engine.c

===================================================================

diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index d0f8826c914..ed8c609c01f 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -54,12 +54,12 @@ typedef struct EXTERNAL_StorageList {
 } EXTERNAL_StorageList;
 
 typedef struct EXTERNAL_FramebufferList {
-  struct GPUFrameBuffer *default_fb;
+  struct GPUFrameBuffer *depth_buffer_fb;
 } EXTERNAL_FramebufferList;
 
 typedef struct EXTERNAL_TextureList {
   /* default */
-  struct GPUTexture *depth;
+  struct GPUTexture *depth_buffer_tx;
 } EXTERNAL_TextureList;
 
 typedef struct EXTERNAL_PassList {
@@ -80,30 +80,77 @@ typedef struct EXTERNAL_Data {
 static struct {
   /* Depth Pre Pass */
   struct GPUShader *depth_sh;
+  bool draw_depth;
 } e_data = {NULL}; /* Engine data */
 
 typedef struct EXTERNAL_PrivateData {
   DRWShadingGroup *depth_shgrp;
+
+  /* Do we need to update the depth or can we reuse the last calculated texture. */
+  bool update_depth;
+  bool view_updated;
+
+  float last_mat[4][4];
+  float curr_mat[4][4];
 } EXTERNAL_PrivateData; /* Transient data */
 
 /* Functions */
 
-static void external_engine_init(void *UNUSED(vedata))
+static void external_engine_init(void *vedata)
 {
+  EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl;
+  const DRWContextState *draw_ctx = DRW_context_state_get();
+  RegionView3D *rv3d = draw_ctx->rv3d;
+
   /* Depth prepass */
   if (!e_data.depth_sh) {
     e_data.depth_sh = DRW_shader_create_3d_depth_only(GPU_SHADER_CFG_DEFAULT);
   }
+
+  if (!stl->g_data) {
+    /* Alloc transient pointers */
+    stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+    stl->g_data->update_depth = true;
+    stl->g_data->view_updated = false;
+  }
+
+  if (stl->g_data->update_depth == false) {
+    if (rv3d && rv3d->rflag & RV3D_NAVIGATING) {
+      stl->g_data->update_depth = true;
+    }
+  }
+
+  if (stl->g_data->view_updated) {
+    stl->g_data->update_depth = true;
+    stl->g_data->view_updated = false;
+  }
+
+  {
+    float view[4][4];
+    float win[4][4];
+    DRW_viewport_matrix_get(view, DRW_MAT_VIEW);
+    DRW_viewport_matrix_get(win, DRW_MAT_WIN);
+    mul_m4_m4m4(stl->g_data->curr_mat, view, win);
+    if (!equals_m4m4(stl->g_data->curr_mat, stl->g_data->last_mat)) {
+      stl->g_data->update_depth = true;
+    }
+  }
 }
 
 static void external_cache_init(void *vedata)
 {
   EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl;
   EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl;
+  EXTERNAL_TextureList *txl = ((EXTERNAL_Data *)vedata)->txl;
+  EXTERNAL_FramebufferList *fbl = ((EXTERNAL_Data *)vedata)->fbl;
 
-  if (!stl->g_data) {
-    /* Alloc transient pointers */
-    stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+  {
+    DRW_texture_ensure_fullscreen_2d(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0);
+
+    GPU_framebuffer_ensure_config(&fbl->depth_buffer_fb,
+                                  {
+                                      GPU_ATTACHMENT_TEXTURE(txl->depth_buffer_tx),
+                                  });
   }
 
   /* Depth Pass */
@@ -112,6 +159,16 @@ static void external_cache_init(void *vedata)
                                       DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
     stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
   }
+
+  /* Do not draw depth pass when overlays are turned off. */
+  e_data.draw_depth = false;
+  const DRWContextState *draw_ctx = DRW_context_state_get();
+  const View3D *v3d = draw_ctx->v3d;
+  if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
+    /* mark `update_depth` for when overlays are turned on again. */
+    stl->g_data->update_depth = true;
+    return;
+  }
 }
 
 static void external_cache_populate(void *vedata, Object *ob)
@@ -122,10 +179,20 @@ static void external_cache_populate(void *vedata, Object *ob)
     return;
   }
 
-  struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
-  if (geom) {
-    /* Depth Prepass */
-    DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat);
+  /* Do not draw depth pass when overlays are turned off. */
+  const DRWContextState *draw_ctx = DRW_context_state_get();
+  const View3D *v3d = draw_ctx->v3d;
+  if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
+    return;
+  }
+
+  if (stl->g_data->update_depth) {
+    e_data.draw_depth = true;
+    struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+    if (geom) {
+      /* Depth Prepass */
+      DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat);
+    }
   }
 }
 
@@ -181,7 +248,10 @@ static void external_draw_scene_do(void *vedata)
 static void external_draw_scene(void *vedata)
 {
   const DRWContextState *draw_ctx = DRW_context_state_get();
+  EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl;
   EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl;
+  EXTERNAL_FramebufferList *fbl = ((EXTERNAL_Data *)vedata)->fbl;
+  const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
 
   /* Will be NULL during OpenGL render.
    * OpenGL render is used for quick preview (thumbnails or sequencer preview)
@@ -189,7 +259,28 @@ static void external_draw_scene(void *vedata)
   if (draw_ctx->evil_C) {
     external_draw_scene_do(vedata);
   }
-  DRW_draw_pass(psl->depth_pass);
+
+  if (e_data.draw_depth) {
+    DRW_draw_pass(psl->depth_pass);
+    // copy result to tmp buffer
+    GPU_framebuffer_blit(dfbl->depth_only_fb, 0, fbl->depth_buffer_fb, 0, GPU_DEPTH_BIT);
+    stl->g_data->update_depth = false;
+  }
+  else {
+    // copy tmp buffer to default
+    GPU_framebuffer_blit(fbl->depth_buffer_fb, 0, dfbl->depth_only_fb, 0, GPU_DEPTH_BIT);
+  }
+
+  copy_m4_m4(stl->g_data->last_mat, stl->g_data->curr_mat);
+}
+
+static void external_view_update(void *vedata)
+{
+  EXTERNAL_Data *data = vedata;
+  EXTERNAL_StorageList *stl = data->stl;
+  if (stl && stl->g_data) {
+    stl->g_data->view_updated = true;
+  }
 }
 
 static void external_engine_free(void)
@@ -211,7 +302,7 @@ static DrawEngineType draw_engine_external_type = {
     &external_cache_finish,
     NULL,
     &external_draw_scene,
-    NULL,
+    &external_view_update,
     NULL,
     NULL,
 };



More information about the Bf-blender-cvs mailing list