From 6ae36ea11404d96b842735016319928f27cbfe28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 18 Feb 2025 18:49:07 +0100 Subject: [PATCH] Refactor: DRW: Move all volume and pointcloud related data into modules Rel #134690 Pull Request: https://projects.blender.org/blender/blender/pulls/134754 --- source/blender/draw/intern/draw_common_c.hh | 19 +-- source/blender/draw/intern/draw_manager_c.cc | 17 ++- source/blender/draw/intern/draw_manager_c.hh | 6 +- source/blender/draw/intern/draw_pointcloud.cc | 47 ++++--- source/blender/draw/intern/draw_volume.cc | 118 ++++++++---------- 5 files changed, 108 insertions(+), 99 deletions(-) diff --git a/source/blender/draw/intern/draw_common_c.hh b/source/blender/draw/intern/draw_common_c.hh index 05b489a3d77..c34faad62cf 100644 --- a/source/blender/draw/intern/draw_common_c.hh +++ b/source/blender/draw/intern/draw_common_c.hh @@ -28,6 +28,8 @@ struct DRWData; namespace blender::draw { class Manager; struct CurvesModule; +struct PointCloudModule; +struct VolumeModule; } // namespace blender::draw /* draw_hair.cc */ @@ -52,23 +54,24 @@ namespace blender::draw { */ gpu::VertBuf *DRW_curves_pos_buffer_get(Object *object); -/* If drw_data is nullptr, DST global is access to get it. */ +/* If drw_data is nullptr, DST global is accessed to get it. */ void DRW_curves_init(DRWData *drw_data = nullptr); void DRW_curves_module_free(draw::CurvesModule *module); void DRW_curves_update(draw::Manager &manager); /* draw_pointcloud.cc */ -void DRW_pointcloud_init(); -void DRW_pointcloud_free(); - -} // namespace blender::draw +/* If drw_data is nullptr, DST global is accessed to get it. */ +void DRW_point_cloud_init(DRWData *drw_data = nullptr); +void DRW_point_cloud_module_free(draw::PointCloudModule *module); /* draw_volume.cc */ -void DRW_volume_init(DRWData *drw_data); -void DRW_volume_ubos_pool_free(void *pool); -void DRW_volume_free(); +/* If drw_data is nullptr, DST global is accessed to get it. */ +void DRW_volume_init(DRWData *drw_data = nullptr); +void DRW_volume_module_free(draw::VolumeModule *module); + +} // namespace blender::draw /* `draw_fluid.cc` */ diff --git a/source/blender/draw/intern/draw_manager_c.cc b/source/blender/draw/intern/draw_manager_c.cc index 28d7b796bf3..314f64be973 100644 --- a/source/blender/draw/intern/draw_manager_c.cc +++ b/source/blender/draw/intern/draw_manager_c.cc @@ -352,7 +352,8 @@ void DRW_viewport_data_free(DRWData *drw_data) for (int i = 0; i < 2; i++) { DRW_view_data_free(drw_data->view_data[i]); } - DRW_volume_ubos_pool_free(drw_data->volume_grids_ubos); + DRW_volume_module_free(drw_data->volume_module); + DRW_point_cloud_module_free(drw_data->point_cloud_module); DRW_curves_module_free(drw_data->curves_module); delete drw_data->default_view; MEM_freeN(drw_data); @@ -1488,7 +1489,7 @@ void DRW_draw_render_loop_ex(Depsgraph *depsgraph, drw_engines_data_validate(); drw_debug_init(); - DRW_pointcloud_init(); + DRW_point_cloud_init(DST.vmempool); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -1849,7 +1850,7 @@ void DRW_render_object_iter( { using namespace blender::draw; const DRWContextState *draw_ctx = DRW_context_state_get(); - DRW_pointcloud_init(); + DRW_point_cloud_init(DST.vmempool); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -1907,7 +1908,7 @@ void DRW_custom_pipeline_begin(DrawEngineType *draw_engine_type, Depsgraph *deps drw_manager_init(&DST, nullptr, nullptr); - DRW_pointcloud_init(); + DRW_point_cloud_init(DST.vmempool); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -1956,7 +1957,7 @@ void DRW_cache_restart() drw_manager_init(&DST, DST.viewport, blender::int2{int(DST.size[0]), int(DST.size[1])}); - DRW_pointcloud_init(); + DRW_point_cloud_init(DST.vmempool); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2235,7 +2236,7 @@ void DRW_draw_select_loop(Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); - DRW_pointcloud_init(); + DRW_point_cloud_init(DST.vmempool); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2406,7 +2407,7 @@ void DRW_draw_depth_loop(Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); - DRW_pointcloud_init(); + DRW_point_cloud_init(DST.vmempool); DRW_curves_init(DST.vmempool); DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); @@ -2845,8 +2846,6 @@ void DRW_engines_free() GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only); DRW_shaders_free(); - DRW_pointcloud_free(); - DRW_volume_free(); drw_debug_module_free(DST.debug); DST.debug = nullptr; diff --git a/source/blender/draw/intern/draw_manager_c.hh b/source/blender/draw/intern/draw_manager_c.hh index ec153bbb94b..7b25f7c90f1 100644 --- a/source/blender/draw/intern/draw_manager_c.hh +++ b/source/blender/draw/intern/draw_manager_c.hh @@ -32,6 +32,8 @@ struct Object; struct Mesh; namespace blender::draw { struct CurvesModule; +struct VolumeModule; +struct PointCloudModule; struct DRW_Attributes; struct DRW_MeshCDMask; class CurveRefinePass; @@ -64,14 +66,14 @@ typedef struct DRWRegisteredDrawEngine { struct DRWData { /** Instance data. */ DRWInstanceDataList *idatalist; - /** Per draw-call volume object data. */ - void *volume_grids_ubos; /* VolumeUniformBufPool */ /** List of smoke textures to free after drawing. */ ListBase smoke_textures; /** Per stereo view data. Contains engine data and default frame-buffers. */ DRWViewData *view_data[2]; /** Module storage. */ blender::draw::CurvesModule *curves_module; + blender::draw::VolumeModule *volume_module; + blender::draw::PointCloudModule *point_cloud_module; /** Default view that feeds every engine. */ blender::draw::View *default_view; }; diff --git a/source/blender/draw/intern/draw_pointcloud.cc b/source/blender/draw/intern/draw_pointcloud.cc index 4d489d2351f..8eccbd70fa3 100644 --- a/source/blender/draw/intern/draw_pointcloud.cc +++ b/source/blender/draw/intern/draw_pointcloud.cc @@ -26,27 +26,43 @@ namespace blender::draw { -static gpu::VertBuf *g_dummy_vbo = nullptr; +struct PointCloudModule { + gpu::VertBuf *dummy_vbo = create_dummy_vbo(); -void DRW_pointcloud_init() -{ - if (g_dummy_vbo == nullptr) { - /* initialize vertex format */ + ~PointCloudModule() + { + GPU_VERTBUF_DISCARD_SAFE(dummy_vbo); + } + + private: + gpu::VertBuf *create_dummy_vbo() + { GPUVertFormat format = {0}; uint dummy_id = GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - g_dummy_vbo = GPU_vertbuf_create_with_format_ex( + gpu::VertBuf *vbo = GPU_vertbuf_create_with_format_ex( format, GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY); const float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPU_vertbuf_data_alloc(*g_dummy_vbo, 1); - GPU_vertbuf_attr_fill(g_dummy_vbo, dummy_id, vert); + GPU_vertbuf_data_alloc(*vbo, 1); + GPU_vertbuf_attr_fill(vbo, dummy_id, vert); + return vbo; + } +}; + +void DRW_point_cloud_init(DRWData *drw_data) +{ + if (drw_data == nullptr) { + drw_data = DST.vmempool; + } + if (drw_data->point_cloud_module == nullptr) { + drw_data->point_cloud_module = MEM_new("PointCloudModule"); } } -void DRW_pointcloud_free() +void DRW_point_cloud_module_free(PointCloudModule *point_cloud_module) { - GPU_VERTBUF_DISCARD_SAFE(g_dummy_vbo); + MEM_delete(point_cloud_module); } template @@ -57,12 +73,13 @@ gpu::Batch *point_cloud_sub_pass_setup_implementation(PassT &sub_ps, BLI_assert(object->type == OB_POINTCLOUD); PointCloud &pointcloud = *static_cast(object->data); + PointCloudModule &module = *DST.vmempool->point_cloud_module; /* Fix issue with certain driver not drawing anything if there is no texture bound to * "ac", "au", "u" or "c". */ - sub_ps.bind_texture("u", g_dummy_vbo); - sub_ps.bind_texture("au", g_dummy_vbo); - sub_ps.bind_texture("c", g_dummy_vbo); - sub_ps.bind_texture("ac", g_dummy_vbo); + sub_ps.bind_texture("u", module.dummy_vbo); + sub_ps.bind_texture("au", module.dummy_vbo); + sub_ps.bind_texture("c", module.dummy_vbo); + sub_ps.bind_texture("ac", module.dummy_vbo); gpu::VertBuf *pos_rad_buf = pointcloud_position_and_radius_get(&pointcloud); sub_ps.bind_texture("ptcloud_pos_rad_tx", pos_rad_buf); @@ -76,7 +93,7 @@ gpu::Batch *point_cloud_sub_pass_setup_implementation(PassT &sub_ps, gpu::VertBuf **attribute_buf = DRW_pointcloud_evaluated_attribute(&pointcloud, gpu_attr->name); - sub_ps.bind_texture(sampler_name, (attribute_buf) ? attribute_buf : &g_dummy_vbo); + sub_ps.bind_texture(sampler_name, (attribute_buf) ? attribute_buf : &module.dummy_vbo); } } diff --git a/source/blender/draw/intern/draw_volume.cc b/source/blender/draw/intern/draw_volume.cc index 302887f6241..c988d9ced8d 100644 --- a/source/blender/draw/intern/draw_volume.cc +++ b/source/blender/draw/intern/draw_volume.cc @@ -30,14 +30,9 @@ #include "draw_common.hh" -using namespace blender; -using namespace blender::draw; -using VolumeInfosBuf = blender::draw::UniformBuffer; +namespace blender::draw { -static struct { - GPUTexture *dummy_zero; - GPUTexture *dummy_one; -} g_data = {}; +using VolumeInfosBuf = blender::draw::UniformBuffer; struct VolumeUniformBufPool { Vector ubos; @@ -65,69 +60,62 @@ struct VolumeUniformBufPool { } }; -void DRW_volume_ubos_pool_free(void *pool) -{ - delete reinterpret_cast(pool); -} +struct VolumeModule { + VolumeUniformBufPool ubo_pool; -static void drw_volume_globals_init() -{ - const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - g_data.dummy_zero = GPU_texture_create_3d( - "dummy_zero", 1, 1, 1, 1, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ, zero); - g_data.dummy_one = GPU_texture_create_3d( - "dummy_one", 1, 1, 1, 1, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ, one); - GPU_texture_extend_mode(g_data.dummy_zero, GPU_SAMPLER_EXTEND_MODE_REPEAT); - GPU_texture_extend_mode(g_data.dummy_one, GPU_SAMPLER_EXTEND_MODE_REPEAT); -} + draw::Texture dummy_zero; + draw::Texture dummy_one; -void DRW_volume_free() -{ - GPU_TEXTURE_FREE_SAFE(g_data.dummy_zero); - GPU_TEXTURE_FREE_SAFE(g_data.dummy_one); -} - -static GPUTexture *grid_default_texture(eGPUDefaultValue default_value) -{ - if (g_data.dummy_one == nullptr) { - drw_volume_globals_init(); + VolumeModule() + { + const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ; + dummy_zero.ensure_3d(GPU_RGBA32F, int3(1), usage, zero); + dummy_one.ensure_3d(GPU_RGBA32F, int3(1), usage, one); + GPU_texture_extend_mode(dummy_zero, GPU_SAMPLER_EXTEND_MODE_REPEAT); + GPU_texture_extend_mode(dummy_one, GPU_SAMPLER_EXTEND_MODE_REPEAT); } - switch (default_value) { - case GPU_DEFAULT_0: - return g_data.dummy_zero; - case GPU_DEFAULT_1: - return g_data.dummy_one; + GPUTexture *grid_default_texture(eGPUDefaultValue default_value) + { + switch (default_value) { + case GPU_DEFAULT_0: + return dummy_zero; + case GPU_DEFAULT_1: + return dummy_one; + } + return dummy_zero; } - return g_data.dummy_zero; -} +}; void DRW_volume_init(DRWData *drw_data) { - if (drw_data->volume_grids_ubos == nullptr) { - drw_data->volume_grids_ubos = new VolumeUniformBufPool(); + if (drw_data == nullptr) { + drw_data = DST.vmempool; } - VolumeUniformBufPool *pool = (VolumeUniformBufPool *)drw_data->volume_grids_ubos; - pool->reset(); - - if (g_data.dummy_one == nullptr) { - drw_volume_globals_init(); + if (drw_data->volume_module == nullptr) { + drw_data->volume_module = MEM_new("VolumeModule"); } } -/* -------------------------------------------------------------------- */ -/** \name New Draw Manager implementation - * \{ */ +void DRW_volume_module_free(draw::VolumeModule *module) +{ + MEM_delete(module); +} -namespace blender::draw { +/* -------------------------------------------------------------------- */ +/** \name Public API for render engines. + * \{ */ template PassType *volume_world_grids_init(PassType &ps, ListBaseWrapper &attrs) { + VolumeModule &module = *DST.vmempool->volume_module; + PassType *sub = &ps.sub("World Volume"); for (const GPUMaterialAttribute *attr : attrs) { - sub->bind_texture(attr->input_name, grid_default_texture(attr->default_value)); + sub->bind_texture(attr->input_name, module.grid_default_texture(attr->default_value)); } return sub; @@ -146,8 +134,8 @@ PassType *volume_object_grids_init(PassType &ps, return nullptr; } - VolumeUniformBufPool *pool = (VolumeUniformBufPool *)DST.vmempool->volume_grids_ubos; - VolumeInfosBuf &volume_infos = *pool->alloc(); + VolumeModule &module = *DST.vmempool->volume_module; + VolumeInfosBuf &volume_infos = *module.ubo_pool.alloc(); volume_infos.density_scale = BKE_volume_density_scale(volume, ob->object_to_world().ptr()); volume_infos.color_mul = float4(1.0f); @@ -159,7 +147,7 @@ PassType *volume_object_grids_init(PassType &ps, /* Bind volume grid textures. */ int grid_id = 0; for (const GPUMaterialAttribute *attr : attrs) { - const blender::bke::VolumeGridData *volume_grid = BKE_volume_grid_find(volume, attr->name); + const bke::VolumeGridData *volume_grid = BKE_volume_grid_find(volume, attr->name); const DRWVolumeGrid *drw_grid = (volume_grid) ? DRW_volume_batch_cache_get_grid(volume, volume_grid) : nullptr; @@ -168,8 +156,8 @@ PassType *volume_object_grids_init(PassType &ps, * - Grid exists but has zero size or failed to load -> use zero. * - Grid does not exist -> use default value. */ const GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : - (volume_grid) ? g_data.dummy_zero : - grid_default_texture(attr->default_value); + (volume_grid) ? module.dummy_zero : + module.grid_default_texture(attr->default_value); /* TODO(@pragma37): bind_texture const support ? */ sub->bind_texture(attr->input_name, (GPUTexture *)grid_tex); @@ -190,8 +178,8 @@ PassType *drw_volume_object_mesh_init(PassType &ps, Object *ob, ListBaseWrapper &attrs) { - VolumeUniformBufPool *pool = (VolumeUniformBufPool *)DST.vmempool->volume_grids_ubos; - VolumeInfosBuf &volume_infos = *pool->alloc(); + VolumeModule &module = *DST.vmempool->volume_module; + VolumeInfosBuf &volume_infos = *module.ubo_pool.alloc(); ModifierData *md = nullptr; @@ -213,7 +201,7 @@ PassType *drw_volume_object_mesh_init(PassType &ps, sub = &ps.sub("Volume Mesh SubPass"); int grid_id = 0; for (const GPUMaterialAttribute *attr : attrs) { - sub->bind_texture(attr->input_name, grid_default_texture(attr->default_value)); + sub->bind_texture(attr->input_name, module.grid_default_texture(attr->default_value)); volume_infos.grids_xform[grid_id++] = float4x4::identity(); } } @@ -235,16 +223,16 @@ PassType *drw_volume_object_mesh_init(PassType &ps, for (const GPUMaterialAttribute *attr : attrs) { if (STREQ(attr->name, "density")) { sub->bind_texture(attr->input_name, - fds->tex_density ? &fds->tex_density : &g_data.dummy_one); + fds->tex_density ? &fds->tex_density : &module.dummy_one); } else if (STREQ(attr->name, "color")) { - sub->bind_texture(attr->input_name, fds->tex_color ? &fds->tex_color : &g_data.dummy_one); + sub->bind_texture(attr->input_name, fds->tex_color ? &fds->tex_color : &module.dummy_one); } else if (STR_ELEM(attr->name, "flame", "temperature")) { - sub->bind_texture(attr->input_name, fds->tex_flame ? &fds->tex_flame : &g_data.dummy_zero); + sub->bind_texture(attr->input_name, fds->tex_flame ? &fds->tex_flame : &module.dummy_zero); } else { - sub->bind_texture(attr->input_name, grid_default_texture(attr->default_value)); + sub->bind_texture(attr->input_name, module.grid_default_texture(attr->default_value)); } volume_infos.grids_xform[grid_id++] = orco_mat; } @@ -301,6 +289,6 @@ PassSimple::Sub *volume_sub_pass(PassSimple::Sub &ps, return volume_sub_pass_implementation(ps, scene, ob, gpu_material); } -} // namespace blender::draw - /** \} */ + +} // namespace blender::draw