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
This commit is contained in:
@@ -30,6 +30,77 @@
|
|||||||
|
|
||||||
#include "GPU_batch.h"
|
#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)
|
void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info)
|
||||||
{
|
{
|
||||||
effect_info->jitter_index = 0;
|
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 */
|
/* Cavity settings */
|
||||||
{
|
{
|
||||||
@@ -203,31 +275,29 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
|
|||||||
BLI_listbase_clear(&wpd->smoke_domains);
|
BLI_listbase_clear(&wpd->smoke_domains);
|
||||||
}
|
}
|
||||||
|
|
||||||
void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd,
|
void workbench_private_data_get_light_direction(float r_light_direction[3])
|
||||||
float r_light_direction[3])
|
|
||||||
{
|
{
|
||||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||||
Scene *scene = draw_ctx->scene;
|
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);
|
copy_v3_v3(r_light_direction, scene->display.light_direction);
|
||||||
SWAP(float, r_light_direction[2], r_light_direction[1]);
|
SWAP(float, r_light_direction[2], r_light_direction[1]);
|
||||||
r_light_direction[2] = -r_light_direction[2];
|
r_light_direction[2] = -r_light_direction[2];
|
||||||
r_light_direction[0] = -r_light_direction[0];
|
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)
|
void workbench_private_data_free(WORKBENCH_PrivateData *wpd)
|
||||||
{
|
{
|
||||||
BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN);
|
BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN);
|
||||||
BLI_ghash_free(wpd->material_transp_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);
|
DRW_UBO_FREE_SAFE(wpd->dof_ubo);
|
||||||
GPU_BATCH_DISCARD_SAFE(wpd->world_clip_planes_batch);
|
GPU_BATCH_DISCARD_SAFE(wpd->world_clip_planes_batch);
|
||||||
}
|
}
|
||||||
|
@@ -746,7 +746,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
|
|||||||
|
|
||||||
/* Deferred Mix Pass */
|
/* 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);
|
studiolight_update_light(wpd, e_data.display.light_direction);
|
||||||
|
|
||||||
if (SHADOW_ENABLED(wpd)) {
|
if (SHADOW_ENABLED(wpd)) {
|
||||||
|
@@ -337,8 +337,6 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
|
|||||||
}
|
}
|
||||||
WORKBENCH_PrivateData *wpd = stl->g_data;
|
WORKBENCH_PrivateData *wpd = stl->g_data;
|
||||||
workbench_private_data_init(wpd);
|
workbench_private_data_init(wpd);
|
||||||
float light_direction[3];
|
|
||||||
workbench_private_data_get_light_direction(wpd, light_direction);
|
|
||||||
|
|
||||||
if (!e_data.checker_depth_sh) {
|
if (!e_data.checker_depth_sh) {
|
||||||
e_data.checker_depth_sh = DRW_shader_create_fullscreen(
|
e_data.checker_depth_sh = DRW_shader_create_fullscreen(
|
||||||
|
@@ -217,6 +217,11 @@ typedef struct WORKBENCH_PrivateData {
|
|||||||
View3DShading shading;
|
View3DShading shading;
|
||||||
StudioLight *studio_light;
|
StudioLight *studio_light;
|
||||||
const UserDef *preferences;
|
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 GPUUniformBuffer *world_ubo;
|
||||||
struct DRWShadingGroup *shadow_shgrp;
|
struct DRWShadingGroup *shadow_shgrp;
|
||||||
struct DRWShadingGroup *depth_shgrp;
|
struct DRWShadingGroup *depth_shgrp;
|
||||||
@@ -307,6 +312,12 @@ typedef struct WORKBENCH_ObjectData {
|
|||||||
bool shadow_bbox_dirty;
|
bool shadow_bbox_dirty;
|
||||||
} WORKBENCH_ObjectData;
|
} 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 */
|
/* inline helper functions */
|
||||||
BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd)
|
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_effect_info_init(WORKBENCH_EffectInfo *effect_info);
|
||||||
void workbench_private_data_init(WORKBENCH_PrivateData *wpd);
|
void workbench_private_data_init(WORKBENCH_PrivateData *wpd);
|
||||||
void workbench_private_data_free(WORKBENCH_PrivateData *wpd);
|
void workbench_private_data_free(WORKBENCH_PrivateData *wpd);
|
||||||
void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd,
|
void workbench_private_data_get_light_direction(float r_light_direction[3]);
|
||||||
float r_light_direction[3]);
|
|
||||||
|
|
||||||
/* workbench_volume.c */
|
/* workbench_volume.c */
|
||||||
void workbench_volume_engine_init(void);
|
void workbench_volume_engine_init(void);
|
||||||
|
Reference in New Issue
Block a user