[Bf-blender-cvs] [83d3a7c12d8] master: Workbench: Performance

Jeroen Bakker noreply at git.blender.org
Wed Nov 27 16:09:17 CET 2019


Commit: 83d3a7c12d80d360268f36878e8ffc2832544b3c
Author: Jeroen Bakker
Date:   Thu Oct 17 15:27:53 2019 +0200
Branches: master
https://developer.blender.org/rB83d3a7c12d80d360268f36878e8ffc2832544b3c

Workbench: Performance

Small performance improvements by caching the world_ubo in the World.
It was detected that NVIDIA driver created threads to update the
world_ubo (304 bytes). This patch will reuse the previous created
ubo when not changed.

Reviewed By: fclem

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

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

M	source/blender/draw/engines/workbench/workbench_data.c
M	source/blender/draw/engines/workbench/workbench_deferred.c
M	source/blender/draw/engines/workbench/workbench_forward.c
M	source/blender/draw/engines/workbench/workbench_private.h

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

diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 3e63f05ca64..42375f29d4d 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -30,6 +30,77 @@
 
 #include "GPU_batch.h"
 
+/* -------------------------------------------------------------------- */
+/** \name World Data
+ * \{ */
+
+static void workbench_world_data_free(DrawData *dd)
+{
+  WORKBENCH_WorldData *data = (WORKBENCH_WorldData *)dd;
+  DRW_UBO_FREE_SAFE(data->world_ubo);
+}
+
+/* Ensure the availability of the world_ubo in the given WORKBENCH_PrivateData
+ *
+ * See T70167: Some platforms create threads to upload ubo's.
+ *
+ * Reuses the last previous created `world_ubo`. Due to limitations of
+ * DrawData it will only be reused when there is a world attached to the Scene.
+ * Future development: The best location would be to store it in the View3D.
+ *
+ * We don't cache the data itself as there was no indication that that lead to
+ * an improvement.
+ *
+ * This functions also sets the `WORKBENCH_PrivateData.is_world_ubo_owner` that must
+ * be respected.
+ */
+static void workbench_world_data_ubo_ensure(const Scene *scene, WORKBENCH_PrivateData *wpd)
+{
+  World *world = scene->world;
+  if (world) {
+    WORKBENCH_WorldData *engine_world_data = (WORKBENCH_WorldData *)DRW_drawdata_ensure(
+        &world->id,
+        &draw_engine_workbench_solid,
+        sizeof(WORKBENCH_WorldData),
+        NULL,
+        &workbench_world_data_free);
+
+    if (engine_world_data->world_ubo == NULL) {
+      engine_world_data->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World),
+                                                              &wpd->world_data);
+    }
+    else {
+      DRW_uniformbuffer_update(engine_world_data->world_ubo, &wpd->world_data);
+    }
+
+    /* Borrow world data ubo */
+    wpd->is_world_ubo_owner = false;
+    wpd->world_ubo = engine_world_data->world_ubo;
+  }
+  else {
+    /* there is no world so we cannot cache the UBO. */
+    BLI_assert(!wpd->world_ubo || wpd->is_world_ubo_owner);
+    if (!wpd->world_ubo) {
+      wpd->is_world_ubo_owner = true;
+      wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data);
+    }
+  }
+}
+
+static void workbench_world_data_update_shadow_direction_vs(WORKBENCH_PrivateData *wpd)
+{
+  WORKBENCH_UBO_World *wd = &wpd->world_data;
+  float light_direction[3];
+  float view_matrix[4][4];
+  DRW_view_viewmat_get(NULL, view_matrix, false);
+
+  workbench_private_data_get_light_direction(light_direction);
+
+  /* Shadow direction. */
+  mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, light_direction);
+}
+/* \} */
+
 void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info)
 {
   effect_info->jitter_index = 0;
@@ -139,7 +210,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
     }
   }
 
-  wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data);
+  workbench_world_data_update_shadow_direction_vs(wpd);
+  workbench_world_data_ubo_ensure(scene, wpd);
 
   /* Cavity settings */
   {
@@ -203,31 +275,29 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
   BLI_listbase_clear(&wpd->smoke_domains);
 }
 
-void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd,
-                                                float r_light_direction[3])
+void workbench_private_data_get_light_direction(float r_light_direction[3])
 {
   const DRWContextState *draw_ctx = DRW_context_state_get();
   Scene *scene = draw_ctx->scene;
-  WORKBENCH_UBO_World *wd = &wpd->world_data;
-  float view_matrix[4][4];
-  DRW_view_viewmat_get(NULL, view_matrix, false);
 
   copy_v3_v3(r_light_direction, scene->display.light_direction);
   SWAP(float, r_light_direction[2], r_light_direction[1]);
   r_light_direction[2] = -r_light_direction[2];
   r_light_direction[0] = -r_light_direction[0];
-
-  /* Shadow direction. */
-  mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction);
-
-  DRW_uniformbuffer_update(wpd->world_ubo, wd);
 }
 
 void workbench_private_data_free(WORKBENCH_PrivateData *wpd)
 {
   BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN);
   BLI_ghash_free(wpd->material_transp_hash, NULL, MEM_freeN);
-  DRW_UBO_FREE_SAFE(wpd->world_ubo);
+
+  if (wpd->is_world_ubo_owner) {
+    DRW_UBO_FREE_SAFE(wpd->world_ubo);
+  }
+  else {
+    wpd->world_ubo = NULL;
+  }
+
   DRW_UBO_FREE_SAFE(wpd->dof_ubo);
   GPU_BATCH_DISCARD_SAFE(wpd->world_clip_planes_batch);
 }
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 2e8b952f234..f84bd34545c 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -746,7 +746,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
 
   /* Deferred Mix Pass */
   {
-    workbench_private_data_get_light_direction(wpd, e_data.display.light_direction);
+    workbench_private_data_get_light_direction(e_data.display.light_direction);
     studiolight_update_light(wpd, e_data.display.light_direction);
 
     if (SHADOW_ENABLED(wpd)) {
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index d731b167c06..7a027bf9c86 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -337,8 +337,6 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
   }
   WORKBENCH_PrivateData *wpd = stl->g_data;
   workbench_private_data_init(wpd);
-  float light_direction[3];
-  workbench_private_data_get_light_direction(wpd, light_direction);
 
   if (!e_data.checker_depth_sh) {
     e_data.checker_depth_sh = DRW_shader_create_fullscreen(
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 595b92d19d0..9fcd9651f94 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -217,6 +217,11 @@ typedef struct WORKBENCH_PrivateData {
   View3DShading shading;
   StudioLight *studio_light;
   const UserDef *preferences;
+  /* Does this instance owns the `world_ubo` field.
+   * Normally the field is borrowed from `WORKBENCH_WorldData`. In case that
+   * there is no World attached to the scene the UBO cannot be cached and should
+   * be freed after using. */
+  bool is_world_ubo_owner;
   struct GPUUniformBuffer *world_ubo;
   struct DRWShadingGroup *shadow_shgrp;
   struct DRWShadingGroup *depth_shgrp;
@@ -307,6 +312,12 @@ typedef struct WORKBENCH_ObjectData {
   bool shadow_bbox_dirty;
 } WORKBENCH_ObjectData;
 
+typedef struct WORKBENCH_WorldData {
+  DrawData dd;
+  /* The cached `GPUUniformBuffer`, that is reused between draw calls. */
+  struct GPUUniformBuffer *world_ubo;
+} WORKBENCH_WorldData;
+
 /* inline helper functions */
 BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd)
 {
@@ -526,8 +537,7 @@ bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd,
 void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info);
 void workbench_private_data_init(WORKBENCH_PrivateData *wpd);
 void workbench_private_data_free(WORKBENCH_PrivateData *wpd);
-void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd,
-                                                float r_light_direction[3]);
+void workbench_private_data_get_light_direction(float r_light_direction[3]);
 
 /* workbench_volume.c */
 void workbench_volume_engine_init(void);



More information about the Bf-blender-cvs mailing list