From 0e943939e2a4e5da7db9d1f6fd76767e2423c6d8 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Thu, 23 Sep 2021 00:54:02 +0200 Subject: [PATCH] Add an editor setting to configure number of threads for lightmap baking This can be used to free some CPU cores when baking lightmaps. When using fewer CPU cores, lightmap baking is slower but background tasks aren't slowed down as much. --- core/os/threaded_array_processor.h | 15 ++++++++++++--- editor/editor_settings.cpp | 3 +++ modules/lightmapper_cpu/lightmapper_cpu.cpp | 11 ++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h index da701ff6f3a..55902a61eef 100644 --- a/core/os/threaded_array_processor.h +++ b/core/os/threaded_array_processor.h @@ -64,8 +64,10 @@ void process_array_thread(void *ud) { } } +// p_num_threads is the number of logical CPU cores to use (0 = use all logical CPU cores available). +// Negative values subtract from the total number of logical CPU cores available. template -void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { +void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata, int p_num_threads = 0) { ThreadArrayProcessData data; data.method = p_method; data.instance = p_instance; @@ -74,7 +76,13 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us data.elements = p_elements; data.process(0); //process first, let threads increment for next - int thread_count = OS::get_singleton()->get_processor_count(); + int thread_count; + if (p_num_threads <= 0) { + thread_count = MAX(1, OS::get_singleton()->get_processor_count() + p_num_threads); + } else { + thread_count = p_num_threads; + } + Thread *threads = memnew_arr(Thread, thread_count); for (int i = 0; i < thread_count; i++) { @@ -89,8 +97,9 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us #else +// p_num_threads is intentionally unused when threads are disabled. template -void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { +void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata, int p_num_threads = 0) { ThreadArrayProcessData data; data.method = p_method; data.instance = p_instance; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 207acb42b5a..d34c5ca1c49 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -545,6 +545,9 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { _initial_set("editors/3d/default_z_near", 0.05); _initial_set("editors/3d/default_z_far", 500.0); + _initial_set("editors/3d/lightmap_baking_number_of_cpu_threads", 0); + hints["editors/3d/lightmap_baking_number_of_cpu_threads"] = PropertyInfo(Variant::INT, "editors/3d/lightmap_baking_number_of_cpu_threads", PROPERTY_HINT_RANGE, "-2,128,1", PROPERTY_USAGE_DEFAULT); + // 3D: Navigation _initial_set("editors/3d/navigation/navigation_scheme", 0); _initial_set("editors/3d/navigation/invert_y_axis", false); diff --git a/modules/lightmapper_cpu/lightmapper_cpu.cpp b/modules/lightmapper_cpu/lightmapper_cpu.cpp index e19c9096ee3..75cb45b0a03 100644 --- a/modules/lightmapper_cpu/lightmapper_cpu.cpp +++ b/modules/lightmapper_cpu/lightmapper_cpu.cpp @@ -36,6 +36,10 @@ #include "core/project_settings.h" #include "modules/raycast/lightmap_raycaster.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_settings.h" +#endif + Error LightmapperCPU::_layout_atlas(int p_max_size, Vector2i *r_atlas_size, int *r_atlas_slices) { Vector2i atlas_size; for (unsigned int i = 0; i < mesh_instances.size(); i++) { @@ -205,7 +209,12 @@ Error LightmapperCPU::_layout_atlas(int p_max_size, Vector2i *r_atlas_size, int void LightmapperCPU::_thread_func_callback(void *p_thread_data) { ThreadData *thread_data = reinterpret_cast(p_thread_data); - thread_process_array(thread_data->count, thread_data->instance, &LightmapperCPU::_thread_func_wrapper, thread_data); +#ifdef TOOLS_ENABLED + const int num_threads = EDITOR_GET("editors/3d/lightmap_baking_number_of_cpu_threads"); +#else + const int num_threads = 0; +#endif + thread_process_array(thread_data->count, thread_data->instance, &LightmapperCPU::_thread_func_wrapper, thread_data, num_threads); } void LightmapperCPU::_thread_func_wrapper(uint32_t p_idx, ThreadData *p_thread_data) {