From b69c8b47916e4b3511c1aeff254ebfa6deef37ba Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Wed, 17 May 2023 16:22:26 +0100 Subject: [PATCH] Single Compilation Unit build. Adds support for simple SCU build (DEV_ENABLED only). This speeds up compilation by compiling multiple cpp files within a single translation unit. --- SConstruct | 12 + editor/SCsub | 5 +- editor/editor_about.cpp | 2 +- editor/editor_about.h | 2 + editor/editor_inspector.cpp | 8 +- editor/editor_inspector.h | 1 + editor/editor_node.cpp | 16 +- editor/editor_quick_open.cpp | 4 +- editor/editor_quick_open.h | 3 + editor/editor_scale.cpp | 12 +- editor/editor_scale.h | 11 +- editor/plugins/text_editor.cpp | 2 +- editor/plugins/text_editor.h | 2 + .../plugins/visual_shader_editor_plugin.cpp | 4 +- editor/project_manager.cpp | 16 +- methods.py | 84 ++++- scene/animation/animation_tree.cpp | 2 +- scene/animation/animation_tree.h | 2 + scene/gui/graph_node.cpp | 6 - scene/gui/graph_node.h | 6 + scene/resources/surface_tool.cpp | 4 +- scene/resources/surface_tool.h | 3 + scu_builders.py | 339 ++++++++++++++++++ servers/physics_3d/godot_joint_3d.h | 33 ++ .../joints/godot_cone_twist_joint_3d.cpp | 33 -- .../joints/godot_hinge_joint_3d.cpp | 33 -- .../joints/godot_slider_joint_3d.cpp | 19 - servers/rendering/renderer_canvas_cull.cpp | 2 - servers/rendering/renderer_canvas_cull.h | 2 + 29 files changed, 531 insertions(+), 137 deletions(-) create mode 100644 scu_builders.py diff --git a/SConstruct b/SConstruct index 4e67fb71179d..c383029effb5 100644 --- a/SConstruct +++ b/SConstruct @@ -55,6 +55,7 @@ _helper_module("modules.modules_builders", "modules/modules_builders.py") import methods import glsl_builders import gles3_builders +import scu_builders from platform_methods import architectures, architecture_aliases if ARGUMENTS.get("target", "editor") == "editor": @@ -223,6 +224,7 @@ opts.Add( "", ) opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False)) +opts.Add(EnumVariable("scu_build", "Use single compilation unit build", "none", ("none", "dev", "all"))) # Thirdparty libraries opts.Add(BoolVariable("builtin_certs", "Use the built-in SSL certificates bundles", True)) @@ -428,14 +430,20 @@ if env_base.debug_features: # to give *users* extra debugging information for their game development. env_base.Append(CPPDEFINES=["DEBUG_ENABLED"]) + if env_base.dev_build: # DEV_ENABLED enables *engine developer* code which should only be compiled for those # working on the engine itself. env_base.Append(CPPDEFINES=["DEV_ENABLED"]) + env_base["use_scu"] = env_base["scu_build"] in ("dev", "all") else: # Disable assert() for production targets (only used in thirdparty code). env_base.Append(CPPDEFINES=["NDEBUG"]) + # SCU builds currently use a lot of compiler memory + # in release builds, so disallow outside of DEV builds unless "all" is set. + env_base["use_scu"] = env_base["scu_build"] == "all" + # SCons speed optimization controlled by the `fast_unsafe` option, which provide # more than 10 s speed up for incremental rebuilds. # Unsafe as they reduce the certainty of rebuilding all changed files, so it's @@ -550,6 +558,10 @@ if selected_platform in platform_list: # LTO "auto" means we handle the preferred option in each platform detect.py. env["lto"] = ARGUMENTS.get("lto", "auto") + # Run SCU file generation script if in a SCU build. + if env["use_scu"]: + methods.set_scu_folders(scu_builders.generate_scu_files(env["verbose"], env_base.dev_build == False)) + # Must happen after the flags' definition, as configure is when most flags # are actually handled to change compile options, etc. detect.configure(env) diff --git a/editor/SCsub b/editor/SCsub index 20bfa78c72a4..b1a47dae4518 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -29,9 +29,8 @@ if env.editor_build: reg_exporters_inc = '#include "register_exporters.h"\n\n' reg_exporters = "void register_exporters() {\n" for e in env.platform_exporters: - # Glob all .cpp files in export folder - files = Glob("#platform/" + e + "/export/" + "*.cpp") - env.add_source_files(env.editor_sources, files) + # Add all .cpp files in export folder + env.add_source_files(env.editor_sources, "../platform/" + e + "/export/" + "*.cpp") reg_exporters += "\tregister_" + e + "_exporter();\n" reg_exporters_inc += '#include "platform/' + e + '/export/export.h"\n' diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 25bca2a099bd..a4147acadec9 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -36,7 +36,7 @@ #include "core/version.h" // The metadata key used to store and retrieve the version text to copy to the clipboard. -static const String META_TEXT_TO_COPY = "text_to_copy"; +const String EditorAbout::META_TEXT_TO_COPY = "text_to_copy"; void EditorAbout::_theme_changed() { const Ref font = get_theme_font(SNAME("source"), SNAME("EditorFonts")); diff --git a/editor/editor_about.h b/editor/editor_about.h index a49887c26098..0bc863e3c1ab 100644 --- a/editor/editor_about.h +++ b/editor/editor_about.h @@ -51,6 +51,8 @@ class EditorAbout : public AcceptDialog { GDCLASS(EditorAbout, AcceptDialog); + static const String META_TEXT_TO_COPY; + private: void _license_tree_selected(); void _version_button_pressed(); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index c138637fc98f..3f6db778c5b0 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -46,14 +46,14 @@ #include "scene/property_utils.h" #include "scene/resources/packed_scene.h" -static bool _property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style) { +bool EditorInspector::_property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style) { if (p_property_path.findn(p_filter) != -1) { return true; } - const Vector sections = p_property_path.split("/"); - for (int i = 0; i < sections.size(); i++) { - if (p_filter.is_subsequence_ofn(EditorPropertyNameProcessor::get_singleton()->process_name(sections[i], p_style))) { + const Vector prop_sections = p_property_path.split("/"); + for (int i = 0; i < prop_sections.size(); i++) { + if (p_filter.is_subsequence_ofn(EditorPropertyNameProcessor::get_singleton()->process_name(prop_sections[i], p_style))) { return true; } } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 1ce31e59acf9..a5737b7dc69e 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -512,6 +512,7 @@ class EditorInspector : public ScrollContainer { void _property_deleted(const String &p_path); void _property_checked(const String &p_path, bool p_checked); void _property_pinned(const String &p_path, bool p_pinned); + bool _property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style); void _resource_selected(const String &p_path, Ref p_resource); void _property_selected(const String &p_path, int p_focusable); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4cf48a41b060..e0863a5e5699 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -6760,28 +6760,28 @@ EditorNode::EditorNode() { switch (display_scale) { case 0: // Try applying a suitable display scale automatically. - editor_set_scale(EditorSettings::get_singleton()->get_auto_display_scale()); + EditorScale::set_scale(EditorSettings::get_singleton()->get_auto_display_scale()); break; case 1: - editor_set_scale(0.75); + EditorScale::set_scale(0.75); break; case 2: - editor_set_scale(1.0); + EditorScale::set_scale(1.0); break; case 3: - editor_set_scale(1.25); + EditorScale::set_scale(1.25); break; case 4: - editor_set_scale(1.5); + EditorScale::set_scale(1.5); break; case 5: - editor_set_scale(1.75); + EditorScale::set_scale(1.75); break; case 6: - editor_set_scale(2.0); + EditorScale::set_scale(2.0); break; default: - editor_set_scale(EDITOR_GET("interface/editor/custom_display_scale")); + EditorScale::set_scale(EDITOR_GET("interface/editor/custom_display_scale")); break; } } diff --git a/editor/editor_quick_open.cpp b/editor/editor_quick_open.cpp index c7c41a6ed0bf..f75ab875e421 100644 --- a/editor/editor_quick_open.cpp +++ b/editor/editor_quick_open.cpp @@ -34,8 +34,8 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" -static Rect2i prev_rect = Rect2i(); -static bool was_showed = false; +Rect2i EditorQuickOpen::prev_rect = Rect2i(); +bool EditorQuickOpen::was_showed = false; void EditorQuickOpen::popup_dialog(const String &p_base, bool p_enable_multi, bool p_dont_clear) { base_type = p_base; diff --git a/editor/editor_quick_open.h b/editor/editor_quick_open.h index 4b63a226c26f..2b64efb151d5 100644 --- a/editor/editor_quick_open.h +++ b/editor/editor_quick_open.h @@ -39,6 +39,9 @@ class EditorQuickOpen : public ConfirmationDialog { GDCLASS(EditorQuickOpen, ConfirmationDialog); + static Rect2i prev_rect; + static bool was_showed; + LineEdit *search_box = nullptr; Tree *search_options = nullptr; String base_type; diff --git a/editor/editor_scale.cpp b/editor/editor_scale.cpp index 45ea9a4d5bc3..0670e98e2c1c 100644 --- a/editor/editor_scale.cpp +++ b/editor/editor_scale.cpp @@ -30,14 +30,12 @@ #include "editor_scale.h" -#include "core/os/os.h" +float EditorScale::_scale = 1.0f; -static float scale = 1.0; - -void editor_set_scale(float p_scale) { - scale = p_scale; +void EditorScale::set_scale(float p_scale) { + _scale = p_scale; } -float editor_get_scale() { - return scale; +float EditorScale::get_scale() { + return _scale; } diff --git a/editor/editor_scale.h b/editor/editor_scale.h index 01836256103c..b3583fdcee48 100644 --- a/editor/editor_scale.h +++ b/editor/editor_scale.h @@ -31,9 +31,14 @@ #ifndef EDITOR_SCALE_H #define EDITOR_SCALE_H -void editor_set_scale(float p_scale); -float editor_get_scale(); +class EditorScale { + static float _scale; -#define EDSCALE (editor_get_scale()) +public: + static void set_scale(float p_scale); + static float get_scale(); +}; + +#define EDSCALE (EditorScale::get_scale()) #endif // EDITOR_SCALE_H diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 7a76e4f98975..92ee468bc290 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -481,7 +481,7 @@ void TextEditor::_convert_case(CodeTextEditor::CaseStyle p_case) { code_editor->convert_case(p_case); } -static ScriptEditorBase *create_editor(const Ref &p_resource) { +ScriptEditorBase *TextEditor::create_editor(const Ref &p_resource) { if (Object::cast_to(*p_resource) || Object::cast_to(*p_resource)) { return memnew(TextEditor); } diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index 0c218e9e0c36..d1aa2a904789 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -38,6 +38,8 @@ class TextEditor : public ScriptEditorBase { GDCLASS(TextEditor, ScriptEditorBase); + static ScriptEditorBase *create_editor(const Ref &p_resource); + private: CodeTextEditor *code_editor = nullptr; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index d631958ce992..8fbbd81e1db5 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4982,7 +4982,7 @@ void VisualShaderEditor::_preview_size_changed() { preview_vbox->set_custom_minimum_size(preview_window->get_size()); } -static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_variable) { +static ShaderLanguage::DataType _visual_shader_editor_get_global_shader_uniform_type(const StringName &p_variable) { RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(p_variable); return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt); } @@ -5001,7 +5001,7 @@ void VisualShaderEditor::_update_preview() { info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())); info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())); info.shader_types = ShaderTypes::get_singleton()->get_types(); - info.global_shader_uniform_type_func = _get_global_shader_uniform_type; + info.global_shader_uniform_type_func = _visual_shader_editor_get_global_shader_uniform_type; ShaderLanguage sl; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 994fc8c8e968..5380d106d3bf 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2763,28 +2763,28 @@ ProjectManager::ProjectManager() { switch (display_scale) { case 0: // Try applying a suitable display scale automatically. - editor_set_scale(EditorSettings::get_singleton()->get_auto_display_scale()); + EditorScale::set_scale(EditorSettings::get_singleton()->get_auto_display_scale()); break; case 1: - editor_set_scale(0.75); + EditorScale::set_scale(0.75); break; case 2: - editor_set_scale(1.0); + EditorScale::set_scale(1.0); break; case 3: - editor_set_scale(1.25); + EditorScale::set_scale(1.25); break; case 4: - editor_set_scale(1.5); + EditorScale::set_scale(1.5); break; case 5: - editor_set_scale(1.75); + EditorScale::set_scale(1.75); break; case 6: - editor_set_scale(2.0); + EditorScale::set_scale(2.0); break; default: - editor_set_scale(EDITOR_GET("interface/editor/custom_display_scale")); + EditorScale::set_scale(EDITOR_GET("interface/editor/custom_display_scale")); break; } EditorFileDialog::get_icon_func = &ProjectManager::_file_dialog_get_icon; diff --git a/methods.py b/methods.py index 33ab894f9242..2c15c4a43c03 100644 --- a/methods.py +++ b/methods.py @@ -6,9 +6,23 @@ from collections import OrderedDict from collections.abc import Mapping from typing import Iterator +from pathlib import Path +from os.path import normpath, basename +# Get the "Godot" folder name ahead of time +base_folder_path = str(os.path.abspath(Path(__file__).parent)) + "/" +base_folder_only = os.path.basename(os.path.normpath(base_folder_path)) +# Listing all the folders we have converted +# for SCU in scu_builders.py +_scu_folders = set() -def add_source_files(self, sources, files): + +def set_scu_folders(scu_folders): + global _scu_folders + _scu_folders = scu_folders + + +def add_source_files_orig(self, sources, files, allow_gen=False): # Convert string to list of absolute paths (including expanding wildcard) if isinstance(files, (str, bytes)): # Keep SCons project-absolute path as they are (no wildcard support) @@ -23,7 +37,7 @@ def add_source_files(self, sources, files): skip_gen_cpp = "*" in files dir_path = self.Dir(".").abspath files = sorted(glob.glob(dir_path + "/" + files)) - if skip_gen_cpp: + if skip_gen_cpp and not allow_gen: files = [f for f in files if not f.endswith(".gen.cpp")] # Add each path as compiled Object following environment (self) configuration @@ -35,6 +49,72 @@ def add_source_files(self, sources, files): sources.append(obj) +# The section name is used for checking +# the hash table to see whether the folder +# is included in the SCU build. +# It will be something like "core/math". +def _find_scu_section_name(subdir): + section_path = os.path.abspath(subdir) + "/" + + folders = [] + folder = "" + + for i in range(8): + folder = os.path.dirname(section_path) + folder = os.path.basename(folder) + if folder == base_folder_only: + break + folders += [folder] + section_path += "../" + section_path = os.path.abspath(section_path) + "/" + + section_name = "" + for n in range(len(folders)): + # section_name += folders[len(folders) - n - 1] + " " + section_name += folders[len(folders) - n - 1] + if n != (len(folders) - 1): + section_name += "/" + + return section_name + + +def add_source_files_scu(self, sources, files, allow_gen=False): + if self["use_scu"] and isinstance(files, str): + if "*." not in files: + return False + + # If the files are in a subdirectory, we want to create the scu gen + # files inside this subdirectory. + subdir = os.path.dirname(files) + if subdir != "": + subdir += "/" + + section_name = _find_scu_section_name(subdir) + # if the section name is in the hash table? + # i.e. is it part of the SCU build? + global _scu_folders + if section_name not in (_scu_folders): + return False + + if self["verbose"]: + print("SCU building " + section_name) + + # Add all the gen.cpp files in the SCU directory + add_source_files_orig(self, sources, subdir + "scu/scu_*.gen.cpp", True) + return True + return False + + +# Either builds the folder using the SCU system, +# or reverts to regular build. +def add_source_files(self, sources, files, allow_gen=False): + if not add_source_files_scu(self, sources, files, allow_gen): + # Wraps the original function when scu build is not active. + add_source_files_orig(self, sources, files, allow_gen) + return False + return True + + def disable_warnings(self): # 'self' is the environment if self.msvc: diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 3e62dbc1a554..abd66905d191 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -941,7 +941,7 @@ void AnimationTree::_clear_playing_caches() { playing_caches.clear(); } -static void _call_object(Object *p_object, const StringName &p_method, const Vector &p_params, bool p_deferred) { +void AnimationTree::_call_object(Object *p_object, const StringName &p_method, const Vector &p_params, bool p_deferred) { // Separate function to use alloca() more efficiently const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size()); const Variant *args = p_params.ptr(); diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 0346fc42a74b..422bd0abb1f0 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -194,6 +194,8 @@ class AnimationNodeEndState : public AnimationRootNode { class AnimationTree : public Node { GDCLASS(AnimationTree, Node); + void _call_object(Object *p_object, const StringName &p_method, const Vector &p_params, bool p_deferred); + public: enum AnimationProcessCallback { ANIMATION_PROCESS_PHYSICS, diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 6031730b81e4..b0517caab028 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -34,12 +34,6 @@ #include "graph_edit.h" -struct _MinSizeCache { - int min_size; - bool will_stretch; - int final_size; -}; - bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { String str = p_name; diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index e6ecc3d89b07..7ba2e6db94f9 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -37,6 +37,12 @@ class GraphNode : public Container { GDCLASS(GraphNode, Container); + struct _MinSizeCache { + int min_size; + bool will_stretch; + int final_size; + }; + public: enum Overlay { OVERLAY_DISABLED, diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index c296523475d0..bd41b234f534 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -795,8 +795,8 @@ void SurfaceTool::_create_list(const Ref &p_existing, int p_surface, Local _create_list_from_arrays(arr, r_vertex, r_index, lformat); } -static const uint32_t custom_mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 }; -static const uint32_t custom_shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT }; +const uint32_t SurfaceTool::custom_mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 }; +const uint32_t SurfaceTool::custom_shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT }; void SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays, LocalVector &ret, uint32_t *r_format) { ret.clear(); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 452aa835f016..eabdff19ca6f 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -38,6 +38,9 @@ class SurfaceTool : public RefCounted { GDCLASS(SurfaceTool, RefCounted); + static const uint32_t custom_mask[RS::ARRAY_CUSTOM_COUNT]; + static const uint32_t custom_shift[RS::ARRAY_CUSTOM_COUNT]; + public: struct Vertex { Vector3 vertex; diff --git a/scu_builders.py b/scu_builders.py new file mode 100644 index 000000000000..98363929aecf --- /dev/null +++ b/scu_builders.py @@ -0,0 +1,339 @@ +"""Functions used to generate scu build source files during build time +""" +import glob, os +import math +from pathlib import Path +from os.path import normpath, basename + +base_folder_path = str(Path(__file__).parent) + "/" +base_folder_only = os.path.basename(os.path.normpath(base_folder_path)) +_verbose = False +_is_release_build = False +_scu_folders = set() + + +def clear_out_existing_files(output_folder, extension): + output_folder = os.path.abspath(output_folder) + # print("clear_out_existing_files from folder: " + output_folder) + + if not os.path.isdir(output_folder): + # folder does not exist or has not been created yet, + # no files to clearout. (this is not an error) + return + + for file in glob.glob(output_folder + "/*." + extension): + # print("removed pre-existing file: " + file) + os.remove(file) + + +def folder_not_found(folder): + abs_folder = base_folder_path + folder + "/" + return not os.path.isdir(abs_folder) + + +def find_files_in_folder(folder, sub_folder, include_list, extension, sought_exceptions, found_exceptions): + abs_folder = base_folder_path + folder + "/" + sub_folder + + if not os.path.isdir(abs_folder): + print("ERROR " + abs_folder + " not found.") + return include_list, found_exceptions + + os.chdir(abs_folder) + + sub_folder_slashed = "" + if sub_folder != "": + sub_folder_slashed = sub_folder + "/" + + for file in glob.glob("*." + extension): + + simple_name = Path(file).stem + + if file.endswith(".gen.cpp"): + continue + + li = '#include "../' + sub_folder_slashed + file + '"' + + if not simple_name in sought_exceptions: + include_list.append(li) + else: + found_exceptions.append(li) + + return include_list, found_exceptions + + +def write_output_file(file_count, include_list, start_line, end_line, output_folder, output_filename_prefix, extension): + + output_folder = os.path.abspath(output_folder) + + if not os.path.isdir(output_folder): + # create + os.mkdir(output_folder) + if not os.path.isdir(output_folder): + print("ERROR " + output_folder + " could not be created.") + return + print("CREATING folder " + output_folder) + + file_text = "" + + for l in range(start_line, end_line): + if l < len(include_list): + line = include_list[l] + li = line + "\n" + file_text += li + + # print(file_text) + + num_string = "" + if file_count > 0: + num_string = "_" + str(file_count) + + short_filename = output_filename_prefix + num_string + ".gen." + extension + output_filename = output_folder + "/" + short_filename + if _verbose: + print("generating: " + short_filename) + + output_path = Path(output_filename) + output_path.write_text(file_text, encoding="utf8") + + +def write_exception_output_file(file_count, exception_string, output_folder, output_filename_prefix, extension): + output_folder = os.path.abspath(output_folder) + if not os.path.isdir(output_folder): + print("ERROR " + output_folder + " does not exist.") + return + + file_text = exception_string + "\n" + + num_string = "" + if file_count > 0: + num_string = "_" + str(file_count) + + short_filename = output_filename_prefix + "_exception" + num_string + ".gen." + extension + output_filename = output_folder + "/" + short_filename + + if _verbose: + print("generating: " + short_filename) + + # print("text: " + file_text) + # return + output_path = Path(output_filename) + output_path.write_text(file_text, encoding="utf8") + + +def find_section_name(sub_folder): + # Construct a useful name for the section from the path for debug logging + section_path = os.path.abspath(base_folder_path + sub_folder) + "/" + + folders = [] + folder = "" + + for i in range(8): + folder = os.path.dirname(section_path) + folder = os.path.basename(folder) + if folder == base_folder_only: + break + folders.append(folder) + section_path += "../" + section_path = os.path.abspath(section_path) + "/" + + section_name = "" + for n in range(len(folders)): + section_name += folders[len(folders) - n - 1] + if n != (len(folders) - 1): + section_name += "_" + + return section_name + + +# "folders" is a list of folders to add all the files from to add to the SCU +# "section (like a module)". The name of the scu file will be derived from the first folder +# (thus e.g. scene/3d becomes scu_scene_3d.gen.cpp) + +# "includes_per_scu" limits the number of includes in a single scu file. +# This allows the module to be built in several translation units instead of just 1. +# This will usually be slower to compile but will use less memory per compiler instance, which +# is most relevant in release builds. + +# "sought_exceptions" are a list of files (without extension) that contain +# e.g. naming conflicts, and are therefore not suitable for the scu build. +# These will automatically be placed in their own separate scu file, +# which is slow like a normal build, but prevents the naming conflicts. +# Ideally in these situations, the source code should be changed to prevent naming conflicts. + +# "extension" will usually be cpp, but can also be set to c (for e.g. third party libraries that use c) +def process_folder(folders, sought_exceptions=[], includes_per_scu=0, extension="cpp"): + if len(folders) == 0: + return + + # Construct the filename prefix from the FIRST folder name + # e.g. "scene_3d" + out_filename = find_section_name(folders[0]) + + found_includes = [] + found_exceptions = [] + + main_folder = folders[0] + abs_main_folder = base_folder_path + main_folder + + # Keep a record of all folders that have been processed for SCU, + # this enables deciding what to do when we call "add_source_files()" + global _scu_folders + _scu_folders.add(main_folder) + + # main folder (first) + found_includes, found_exceptions = find_files_in_folder( + main_folder, "", found_includes, extension, sought_exceptions, found_exceptions + ) + + # sub folders + for d in range(1, len(folders)): + found_includes, found_exceptions = find_files_in_folder( + main_folder, folders[d], found_includes, extension, sought_exceptions, found_exceptions + ) + + found_includes = sorted(found_includes) + + # calculate how many lines to write in each file + total_lines = len(found_includes) + + # adjust number of output files according to whether DEV or release + num_output_files = 1 + if _is_release_build: + # always have a maximum in release + includes_per_scu = 8 + num_output_files = max(math.ceil(total_lines / float(includes_per_scu)), 1) + else: + if includes_per_scu > 0: + num_output_files = max(math.ceil(total_lines / float(includes_per_scu)), 1) + + lines_per_file = math.ceil(total_lines / float(num_output_files)) + lines_per_file = max(lines_per_file, 1) + + start_line = 0 + file_number = 0 + + # These do not vary throughout the loop + output_folder = abs_main_folder + "/scu/" + output_filename_prefix = "scu_" + out_filename + + # Clear out any existing files (usually we will be overwriting, + # but we want to remove any that are pre-existing that will not be + # overwritten, so as to not compile anything stale) + clear_out_existing_files(output_folder, extension) + + for file_count in range(0, num_output_files): + end_line = start_line + lines_per_file + + # special case to cover rounding error in final file + if file_count == (num_output_files - 1): + end_line = len(found_includes) + + write_output_file( + file_count, found_includes, start_line, end_line, output_folder, output_filename_prefix, extension + ) + + start_line = end_line + + # Write the exceptions each in their own scu gen file, + # so they can effectively compile in "old style / normal build". + for exception_count in range(len(found_exceptions)): + write_exception_output_file( + exception_count, found_exceptions[exception_count], output_folder, output_filename_prefix, extension + ) + + +def generate_scu_files(verbose, is_release_build): + + print("=============================") + print("Single Compilation Unit Build") + print("=============================") + print("Generating SCU build files") + global _verbose + _verbose = verbose + global _is_release_build + _is_release_build = is_release_build + + curr_folder = os.path.abspath("./") + + # check we are running from the correct folder + if folder_not_found("core") or folder_not_found("platform") or folder_not_found("scene"): + raise RuntimeError("scu_builders.py must be run from the godot folder.") + return + + process_folder(["core"]) + process_folder(["core/crypto"]) + process_folder(["core/debugger"]) + process_folder(["core/extension"]) + process_folder(["core/input"]) + process_folder(["core/io"]) + process_folder(["core/math"]) + process_folder(["core/object"]) + process_folder(["core/os"]) + process_folder(["core/string"]) + process_folder(["core/variant"], ["variant_utility"]) + + process_folder(["drivers/unix"]) + process_folder(["drivers/png"]) + + process_folder(["editor"], ["file_system_dock", "editor_resource_preview"], 32) + process_folder(["editor/debugger"]) + process_folder(["editor/debugger/debug_adapter"]) + process_folder(["editor/export"]) + process_folder(["editor/gui"]) + process_folder(["editor/import"]) + process_folder(["editor/plugins"]) + process_folder(["editor/plugins/gizmos"]) + process_folder(["editor/plugins/tiles"]) + + process_folder(["platform/android/export"]) + process_folder(["platform/ios/export"]) + process_folder(["platform/linuxbsd/export"]) + process_folder(["platform/macos/export"]) + process_folder(["platform/uwp/export"]) + process_folder(["platform/web/export"]) + process_folder(["platform/windows/export"]) + + process_folder(["modules/gltf"]) + process_folder(["modules/gltf/structures"]) + process_folder(["modules/gltf/editor"]) + process_folder(["modules/gltf/extensions"]) + process_folder(["modules/gltf/extensions/physics"]) + process_folder(["modules/navigation"]) + process_folder(["modules/webrtc"]) + process_folder(["modules/websocket"]) + process_folder(["modules/gridmap"]) + process_folder(["modules/multiplayer"]) + process_folder(["modules/multiplayer/editor"]) + process_folder(["modules/openxr"], ["register_types"]) + process_folder(["modules/openxr/action_map"]) + process_folder(["modules/openxr/editor"]) + + process_folder(["modules/csg"]) + process_folder(["modules/gdscript"]) + process_folder(["modules/gdscript/editor"]) + process_folder(["modules/gdscript/language_server"]) + + process_folder(["scene/2d"]) + process_folder(["scene/3d"]) + process_folder(["scene/animation"]) + process_folder(["scene/gui"]) + process_folder(["scene/main"]) + process_folder(["scene/resources"]) + + process_folder(["servers"]) + process_folder(["servers/rendering"]) + process_folder(["servers/rendering/storage"]) + process_folder(["servers/rendering/renderer_rd"]) + process_folder(["servers/rendering/renderer_rd/effects"]) + process_folder(["servers/rendering/renderer_rd/environment"]) + process_folder(["servers/rendering/renderer_rd/storage_rd"]) + process_folder(["servers/physics_2d"]) + process_folder(["servers/physics_3d"]) + process_folder(["servers/physics_3d/joints"]) + process_folder(["servers/audio"]) + process_folder(["servers/audio/effects"]) + + # Finally change back the path to the calling folder + os.chdir(curr_folder) + + return _scu_folders diff --git a/servers/physics_3d/godot_joint_3d.h b/servers/physics_3d/godot_joint_3d.h index 438970e2c9d1..3207723cb48f 100644 --- a/servers/physics_3d/godot_joint_3d.h +++ b/servers/physics_3d/godot_joint_3d.h @@ -39,6 +39,39 @@ class GodotJoint3D : public GodotConstraint3D { bool dynamic_A = false; bool dynamic_B = false; + void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { + if (Math::abs(n.z) > Math_SQRT12) { + // choose p in y-z plane + real_t a = n[1] * n[1] + n[2] * n[2]; + real_t k = 1.0 / Math::sqrt(a); + p = Vector3(0, -n[2] * k, n[1] * k); + // set q = n x p + q = Vector3(a * k, -n[0] * p[2], n[0] * p[1]); + } else { + // choose p in x-y plane + real_t a = n.x * n.x + n.y * n.y; + real_t k = 1.0 / Math::sqrt(a); + p = Vector3(-n.y * k, n.x * k, 0); + // set q = n x p + q = Vector3(-n.z * p.y, n.z * p.x, a * k); + } + } + + _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { + real_t coeff_1 = Math_PI / 4.0f; + real_t coeff_2 = 3.0f * coeff_1; + real_t abs_y = Math::abs(y); + real_t angle; + if (x >= 0.0f) { + real_t r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } else { + real_t r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + return (y < 0.0f) ? -angle : angle; + } + public: virtual bool setup(real_t p_step) override { return false; } virtual bool pre_solve(real_t p_step) override { return true; } diff --git a/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp index 72d6e33c685a..c654756d3ca3 100644 --- a/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp +++ b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp @@ -51,39 +51,6 @@ Written by: Marcus Hennix #include "godot_cone_twist_joint_3d.h" -static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { - if (Math::abs(n.z) > Math_SQRT12) { - // choose p in y-z plane - real_t a = n[1] * n[1] + n[2] * n[2]; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(0, -n[2] * k, n[1] * k); - // set q = n x p - q = Vector3(a * k, -n[0] * p[2], n[0] * p[1]); - } else { - // choose p in x-y plane - real_t a = n.x * n.x + n.y * n.y; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(-n.y * k, n.x * k, 0); - // set q = n x p - q = Vector3(-n.z * p.y, n.z * p.x, a * k); - } -} - -static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { - real_t coeff_1 = Math_PI / 4.0f; - real_t coeff_2 = 3.0f * coeff_1; - real_t abs_y = Math::abs(y); - real_t angle; - if (x >= 0.0f) { - real_t r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - real_t r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - return (y < 0.0f) ? -angle : angle; -} - GodotConeTwistJoint3D::GodotConeTwistJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) : GodotJoint3D(_arr, 2) { A = rbA; diff --git a/servers/physics_3d/joints/godot_hinge_joint_3d.cpp b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp index 826401bafb65..3d423f70e206 100644 --- a/servers/physics_3d/joints/godot_hinge_joint_3d.cpp +++ b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp @@ -49,24 +49,6 @@ subject to the following restrictions: #include "godot_hinge_joint_3d.h" -static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { - if (Math::abs(n.z) > Math_SQRT12) { - // choose p in y-z plane - real_t a = n[1] * n[1] + n[2] * n[2]; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(0, -n[2] * k, n[1] * k); - // set q = n x p - q = Vector3(a * k, -n[0] * p[2], n[0] * p[1]); - } else { - // choose p in x-y plane - real_t a = n.x * n.x + n.y * n.y; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(-n.y * k, n.x * k, 0); - // set q = n x p - q = Vector3(-n.z * p.y, n.z * p.x, a * k); - } -} - GodotHingeJoint3D::GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameA, const Transform3D &frameB) : GodotJoint3D(_arr, 2) { A = rbA; @@ -368,21 +350,6 @@ void HingeJointSW::updateRHS(real_t timeStep) */ -static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { - real_t coeff_1 = Math_PI / 4.0f; - real_t coeff_2 = 3.0f * coeff_1; - real_t abs_y = Math::abs(y); - real_t angle; - if (x >= 0.0f) { - real_t r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - real_t r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - return (y < 0.0f) ? -angle : angle; -} - real_t GodotHingeJoint3D::get_hinge_angle() { const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(0)); const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(1)); diff --git a/servers/physics_3d/joints/godot_slider_joint_3d.cpp b/servers/physics_3d/joints/godot_slider_joint_3d.cpp index 21004b33958b..b9dca94b3775 100644 --- a/servers/physics_3d/joints/godot_slider_joint_3d.cpp +++ b/servers/physics_3d/joints/godot_slider_joint_3d.cpp @@ -57,25 +57,6 @@ April 04, 2008 //----------------------------------------------------------------------------- -static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { - real_t coeff_1 = Math_PI / 4.0f; - real_t coeff_2 = 3.0f * coeff_1; - real_t abs_y = Math::abs(y); - real_t angle; - if (x >= 0.0f) { - real_t r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - real_t r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - return (y < 0.0f) ? -angle : angle; -} - -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- - GodotSliderJoint3D::GodotSliderJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB) : GodotJoint3D(_arr, 2), m_frameInA(frameInA), diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 097580f3bddb..011f0327c98c 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -36,8 +36,6 @@ #include "rendering_server_globals.h" #include "servers/rendering/storage/texture_storage.h" -static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; - void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask) { RENDER_TIMESTAMP("Cull CanvasItem Tree"); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 1106fc4f1ed5..4f11d2c7b12b 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -183,6 +183,8 @@ class RendererCanvasCull { void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask); void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask); + static constexpr int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; + RendererCanvasRender::Item **z_list; RendererCanvasRender::Item **z_last_list;