diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2019-10-17 16:27:53 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2019-11-27 18:08:13 +0300 |
commit | 83d3a7c12d80d360268f36878e8ffc2832544b3c (patch) | |
tree | e5ea13e5193448680b7107ece1f142f87dbea0ac | |
parent | 2e6159a4948cd0f4e0b636734bfe506796bd87f2 (diff) |
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
4 files changed, 95 insertions, 17 deletions
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); |