[Bf-blender-cvs] [670413d54bd] temp-gizmo-decoupled-redraws: Draw-layers: Get it all to work!

Julian Eisel noreply at git.blender.org
Fri Jan 24 18:03:20 CET 2020


Commit: 670413d54bde64e57f59775108eb3eea06c2e8de
Author: Julian Eisel
Date:   Fri Jan 24 17:14:06 2020 +0100
Branches: temp-gizmo-decoupled-redraws
https://developer.blender.org/rB670413d54bde64e57f59775108eb3eea06c2e8de

Draw-layers: Get it all to work!

Create the framebuffers for caching viewport rendering results, and
"composite" all layers together once each is drawn. Compositing is a bit
of a big word for this, since we basically just draw all layers on top
of each other with alpha blending.
After talking with Jeroen, we decided to keep things simple for now, we
can add more features (like per-layer color-management) and do small
improvements later.

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

M	source/blender/draw/intern/draw_manager.c
M	source/blender/draw/intern/draw_manager.h
M	source/blender/draw/intern/draw_manager_layer.c

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

diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index baff62dee5b..c53636cb182 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -106,16 +106,19 @@ static ListBase DRW_engines = {NULL, NULL};
 
 static const DRWLayerType drw_layer_scene_main = {
     .poll = NULL,
+    .may_skip = drw_layer_scene_may_skip,
     .draw_layer = drw_layer_scene_draw,
 };
 
 static const DRWLayerType drw_layer_editor_overlays = {
-    .poll = drw_layer_ui_overlays_poll,
-    .draw_layer = drw_layer_ui_overlays_draw,
+    .poll = drw_layer_editor_overlays_poll,
+    .may_skip = NULL,
+    .draw_layer = drw_layer_editor_overlays_draw,
 };
 
 static const DRWLayerType drw_layer_debug_stats = {
     .poll = drw_layer_debug_stats_poll,
+    .may_skip = NULL,
     .draw_layer = drw_layer_debug_stats_draw,
 };
 
@@ -123,9 +126,8 @@ const DRWLayerType DRW_layer_types[] = {
     drw_layer_scene_main,
     drw_layer_editor_overlays,
     drw_layer_debug_stats,
-    /* Important, leave this here! */
-    {NULL},
 };
+const int DRW_layer_types_count = ARRAY_SIZE(DRW_layer_types);
 
 static void drw_state_prepare_clean_for_draw(DRWManager *dst)
 {
@@ -1508,6 +1510,11 @@ void DRW_draw_view(const bContext *C)
   DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C);
 }
 
+bool drw_layer_scene_may_skip(void)
+{
+  return ED_region_can_redraw_ui_overlays_only(DST.draw_ctx.ar);
+}
+
 void drw_layer_scene_draw(void)
 {
   View3D *v3d = DST.draw_ctx.v3d;
@@ -1526,6 +1533,9 @@ void drw_layer_scene_draw(void)
   const bool do_populate_loop = internal_engine || overlays_on || !draw_type_render ||
                                 gpencil_engine_needed;
 
+  /* Engine caches create offscreen contexts, which require no framebuffer be set. */
+  GPU_framebuffer_restore();
+
   /* Cache filling */
   {
     PROFILE_START(stime);
@@ -1615,12 +1625,12 @@ void drw_layer_scene_draw(void)
   GPU_depth_test(true);
 }
 
-bool drw_layer_ui_overlays_poll(void)
+bool drw_layer_editor_overlays_poll(void)
 {
   return DST.draw_ctx.evil_C != NULL;
 }
 
-void drw_layer_ui_overlays_draw(void)
+void drw_layer_editor_overlays_draw(void)
 {
   View3D *v3d = DST.draw_ctx.v3d;
   Depsgraph *depsgraph = DST.draw_ctx.depsgraph;
@@ -1628,9 +1638,10 @@ void drw_layer_ui_overlays_draw(void)
   const bool do_annotations = (((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
                                ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
 
+  drw_state_set(DRW_STATE_WRITE_COLOR);
+
   /* needed so gizmo isn't obscured */
   if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
-    glDisable(GL_DEPTH_TEST);
     DRW_draw_gizmo_3d();
   }
 
@@ -1639,18 +1650,14 @@ void drw_layer_ui_overlays_draw(void)
   /* annotations - temporary drawing buffer (screenspace) */
   /* XXX: Or should we use a proper draw/overlay engine for this case? */
   if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (do_annotations)) {
-    GPU_depth_test(false);
     /* XXX: as scene->gpd is not copied for COW yet */
     ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, false);
-    GPU_depth_test(true);
   }
 
   if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
     /* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
      * 'DRW_draw_region_info' sets the projection in pixel-space. */
-    GPU_depth_test(false);
     DRW_draw_gizmo_2d();
-    GPU_depth_test(true);
   }
 }
 
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 6bf0160e959..7e1b031f662 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -433,10 +433,12 @@ typedef struct DRWDebugSphere {
 
 typedef struct DRWLayerType {
   bool (*poll)(void);
+  bool (*may_skip)(void);
   void (*draw_layer)(void);
 } DRWLayerType;
 
 const extern DRWLayerType DRW_layer_types[];
+const extern int DRW_layer_types_count;
 
 /* ------------- DRAW MANAGER ------------ */
 
@@ -588,9 +590,10 @@ void DRW_layers_draw_combined_cached(void);
 void DRW_layers_free(void);
 
 /* DRWLayer callbacks */
+bool drw_layer_scene_may_skip(void);
 void drw_layer_scene_draw(void);
-bool drw_layer_ui_overlays_poll(void);
-void drw_layer_ui_overlays_draw(void);
+bool drw_layer_editor_overlays_poll(void);
+void drw_layer_editor_overlays_draw(void);
 bool drw_layer_debug_stats_poll(void);
 void drw_layer_debug_stats_draw(void);
 
diff --git a/source/blender/draw/intern/draw_manager_layer.c b/source/blender/draw/intern/draw_manager_layer.c
index 875786e588c..906acd688a8 100644
--- a/source/blender/draw/intern/draw_manager_layer.c
+++ b/source/blender/draw/intern/draw_manager_layer.c
@@ -22,13 +22,8 @@
 
 #include <stdio.h>
 
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-
-#include "ED_gpencil.h"
-#include "ED_space_api.h"
-
-#include "DEG_depsgraph_query.h"
+#include "BLI_alloca.h"
+#include "BLI_sys_types.h"
 
 #include "draw_manager.h"
 
@@ -38,27 +33,60 @@ typedef struct DRWLayer {
   const DRWLayerType *type;
 
   GPUFrameBuffer *framebuffer;
+  GPUTexture *color;
 } DRWLayer;
 
+/* TODO: Use array with DRW_layer_types_count length to avoid listbase lookups. */
 static ListBase DRW_layers = {NULL}; /* DRWLayer */
 
+static void drw_layer_recreate_textures(DRWLayer *layer)
+{
+  DRW_TEXTURE_FREE_SAFE(layer->color);
+
+  DRW_texture_ensure_fullscreen_2d(&layer->color, GPU_RGBA8, 0);
+  GPU_framebuffer_ensure_config(&layer->framebuffer,
+                                {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(layer->color)});
+}
+
 static DRWLayer *drw_layer_create(const DRWLayerType *type)
 {
   DRWLayer *layer = MEM_callocN(sizeof(*layer), __func__);
+
   layer->type = type;
+  drw_layer_recreate_textures(layer);
+
   return layer;
 }
 
 static void drw_layer_free(DRWLayer *layer)
 {
+  DRW_TEXTURE_FREE_SAFE(layer->color);
+  GPU_FRAMEBUFFER_FREE_SAFE(layer->framebuffer);
+
   MEM_SAFE_FREE(layer);
 }
 
-static DRWLayer *drw_layer_for_type_ensure(const DRWLayerType *type)
+static void drw_layer_ensure_updated_textures(DRWLayer *layer)
+{
+  const float *size = DRW_viewport_size_get();
+
+  BLI_assert(layer->color);
+
+  if ((GPU_texture_width(layer->color) != size[0]) ||
+      (GPU_texture_height(layer->color) != size[1])) {
+    drw_layer_recreate_textures(layer);
+  }
+}
+
+static DRWLayer *drw_layer_for_type_updated_ensure(const DRWLayerType *type)
 {
   DRWLayer *layer = BLI_findptr(&DRW_layers, type, offsetof(DRWLayer, type));
 
-  if (!layer) {
+  if (layer) {
+    /* Ensure updated texture dimensions. */
+    drw_layer_ensure_updated_textures(layer);
+  }
+  else {
     layer = drw_layer_create(type);
     BLI_addtail(&DRW_layers, layer);
   }
@@ -69,14 +97,6 @@ static DRWLayer *drw_layer_for_type_ensure(const DRWLayerType *type)
   return layer;
 }
 
-static void drw_layer_bind(DRWLayer *layer)
-{
-}
-
-static void drw_layer_unbind(const DRWLayer *layer)
-{
-}
-
 void DRW_layers_free(void)
 {
   LISTBASE_FOREACH_MUTABLE (DRWLayer *, layer, &DRW_layers) {
@@ -85,18 +105,74 @@ void DRW_layers_free(void)
   }
 }
 
+static void drw_layers_textures_draw_composited(GPUTexture *tex)
+{
+  drw_state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL);
+
+  /* Draw as texture for final render (without immediate mode). */
+  GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+  GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_IMAGE);
+
+  GPU_texture_bind(tex, 0);
+
+  float mat[4][4];
+  unit_m4(mat);
+  GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
+
+  GPU_batch_program_use_begin(geom);
+  GPU_batch_bind(geom);
+  GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
+  GPU_batch_program_use_end(geom);
+
+  GPU_texture_unbind(tex);
+}
+
 void DRW_layers_draw_combined_cached(void)
 {
-  for (const DRWLayerType *layer_type = &DRW_layer_types[0]; layer_type->draw_layer;
-       layer_type++) {
-    if (!layer_type->poll || layer_type->poll()) {
-      DRWLayer *layer = drw_layer_for_type_ensure(layer_type);
+  /* Store if poll succeeded, to avoid calling it twice. */
+  bool *is_layer_visible = BLI_array_alloca(is_layer_visible, DRW_layer_types_count);
 
-      drw_layer_bind(layer);
+  GPU_framebuffer_bind(DST.default_framebuffer);
+  DRW_clear_background();
 
-      layer_type->draw_layer();
+  /* First pass: Update dirty framebuffers and blit into cache. */
+  for (int i = 0; i < DRW_layer_types_count; i++) {
+    const DRWLayerType *layer_type = &DRW_layer_types[i];
+
+    if (layer_type->poll && !layer_type->poll()) {
+      is_layer_visible[i] = false;
+      continue;
+    }
+    is_layer_visible[i] = true;
 
-      drw_layer_unbind(layer);
+    if (layer_type->may_skip && layer_type->may_skip()) {
+      continue;
     }
+
+    DRWLayer *layer = drw_layer_for_type_updated_ensure(layer_type);
+
+    DRW_clear_background();
+    DRW_state_reset();
+    layer_type->draw_layer();
+
+    /* Blit the default framebuffer into the layer framebuffer cache. */
+    GPU_framebuffer_bind(DST.default_framebuffer);
+    GPU_framebuffer_blit(DST.default_framebuffer, 0, layer->framebuffer, 0, GPU_COLOR_BIT);
+  }
+
+  BLI_assert(GPU_framebuffer_active_get() == DST.default_framebuffer);
+  DRW_clear_background();
+
+  for (int i = 0; i < DRW_layer_types_count; i++) {
+    if (!is_layer_visible[i]) {
+      continue;
+    }
+
+    const DRWLayerType *layer_type = &DRW_layer_types[i];
+    const DRWLayer *layer = drw_layer_for_type_updated_ensure(layer_type);
+
+    drw_layers_textures_draw_composited(layer->color);
   }
+
+  GPU_framebuffer_bind(DST.default_framebuffer);
 }



More information about the Bf-blender-cvs mailing list