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.
This commit is contained in:
lawnjelly 2023-05-17 16:22:26 +01:00
parent 543750a1b3
commit b69c8b4791
29 changed files with 531 additions and 137 deletions

View File

@ -55,6 +55,7 @@ _helper_module("modules.modules_builders", "modules/modules_builders.py")
import methods import methods
import glsl_builders import glsl_builders
import gles3_builders import gles3_builders
import scu_builders
from platform_methods import architectures, architecture_aliases from platform_methods import architectures, architecture_aliases
if ARGUMENTS.get("target", "editor") == "editor": 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(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 # Thirdparty libraries
opts.Add(BoolVariable("builtin_certs", "Use the built-in SSL certificates bundles", True)) 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. # to give *users* extra debugging information for their game development.
env_base.Append(CPPDEFINES=["DEBUG_ENABLED"]) env_base.Append(CPPDEFINES=["DEBUG_ENABLED"])
if env_base.dev_build: if env_base.dev_build:
# DEV_ENABLED enables *engine developer* code which should only be compiled for those # DEV_ENABLED enables *engine developer* code which should only be compiled for those
# working on the engine itself. # working on the engine itself.
env_base.Append(CPPDEFINES=["DEV_ENABLED"]) env_base.Append(CPPDEFINES=["DEV_ENABLED"])
env_base["use_scu"] = env_base["scu_build"] in ("dev", "all")
else: else:
# Disable assert() for production targets (only used in thirdparty code). # Disable assert() for production targets (only used in thirdparty code).
env_base.Append(CPPDEFINES=["NDEBUG"]) 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 # SCons speed optimization controlled by the `fast_unsafe` option, which provide
# more than 10 s speed up for incremental rebuilds. # more than 10 s speed up for incremental rebuilds.
# Unsafe as they reduce the certainty of rebuilding all changed files, so it's # 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. # LTO "auto" means we handle the preferred option in each platform detect.py.
env["lto"] = ARGUMENTS.get("lto", "auto") 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 # Must happen after the flags' definition, as configure is when most flags
# are actually handled to change compile options, etc. # are actually handled to change compile options, etc.
detect.configure(env) detect.configure(env)

View File

@ -29,9 +29,8 @@ if env.editor_build:
reg_exporters_inc = '#include "register_exporters.h"\n\n' reg_exporters_inc = '#include "register_exporters.h"\n\n'
reg_exporters = "void register_exporters() {\n" reg_exporters = "void register_exporters() {\n"
for e in env.platform_exporters: for e in env.platform_exporters:
# Glob all .cpp files in export folder # Add all .cpp files in export folder
files = Glob("#platform/" + e + "/export/" + "*.cpp") env.add_source_files(env.editor_sources, "../platform/" + e + "/export/" + "*.cpp")
env.add_source_files(env.editor_sources, files)
reg_exporters += "\tregister_" + e + "_exporter();\n" reg_exporters += "\tregister_" + e + "_exporter();\n"
reg_exporters_inc += '#include "platform/' + e + '/export/export.h"\n' reg_exporters_inc += '#include "platform/' + e + '/export/export.h"\n'

View File

@ -36,7 +36,7 @@
#include "core/version.h" #include "core/version.h"
// The metadata key used to store and retrieve the version text to copy to the clipboard. // 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() { void EditorAbout::_theme_changed() {
const Ref<Font> font = get_theme_font(SNAME("source"), SNAME("EditorFonts")); const Ref<Font> font = get_theme_font(SNAME("source"), SNAME("EditorFonts"));

View File

@ -51,6 +51,8 @@
class EditorAbout : public AcceptDialog { class EditorAbout : public AcceptDialog {
GDCLASS(EditorAbout, AcceptDialog); GDCLASS(EditorAbout, AcceptDialog);
static const String META_TEXT_TO_COPY;
private: private:
void _license_tree_selected(); void _license_tree_selected();
void _version_button_pressed(); void _version_button_pressed();

View File

@ -46,14 +46,14 @@
#include "scene/property_utils.h" #include "scene/property_utils.h"
#include "scene/resources/packed_scene.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) { if (p_property_path.findn(p_filter) != -1) {
return true; return true;
} }
const Vector<String> sections = p_property_path.split("/"); const Vector<String> prop_sections = p_property_path.split("/");
for (int i = 0; i < sections.size(); i++) { for (int i = 0; i < prop_sections.size(); i++) {
if (p_filter.is_subsequence_ofn(EditorPropertyNameProcessor::get_singleton()->process_name(sections[i], p_style))) { if (p_filter.is_subsequence_ofn(EditorPropertyNameProcessor::get_singleton()->process_name(prop_sections[i], p_style))) {
return true; return true;
} }
} }

View File

@ -512,6 +512,7 @@ class EditorInspector : public ScrollContainer {
void _property_deleted(const String &p_path); void _property_deleted(const String &p_path);
void _property_checked(const String &p_path, bool p_checked); void _property_checked(const String &p_path, bool p_checked);
void _property_pinned(const String &p_path, bool p_pinned); 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<Resource> p_resource); void _resource_selected(const String &p_path, Ref<Resource> p_resource);
void _property_selected(const String &p_path, int p_focusable); void _property_selected(const String &p_path, int p_focusable);

View File

@ -6760,28 +6760,28 @@ EditorNode::EditorNode() {
switch (display_scale) { switch (display_scale) {
case 0: case 0:
// Try applying a suitable display scale automatically. // 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; break;
case 1: case 1:
editor_set_scale(0.75); EditorScale::set_scale(0.75);
break; break;
case 2: case 2:
editor_set_scale(1.0); EditorScale::set_scale(1.0);
break; break;
case 3: case 3:
editor_set_scale(1.25); EditorScale::set_scale(1.25);
break; break;
case 4: case 4:
editor_set_scale(1.5); EditorScale::set_scale(1.5);
break; break;
case 5: case 5:
editor_set_scale(1.75); EditorScale::set_scale(1.75);
break; break;
case 6: case 6:
editor_set_scale(2.0); EditorScale::set_scale(2.0);
break; break;
default: default:
editor_set_scale(EDITOR_GET("interface/editor/custom_display_scale")); EditorScale::set_scale(EDITOR_GET("interface/editor/custom_display_scale"));
break; break;
} }
} }

View File

@ -34,8 +34,8 @@
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_scale.h" #include "editor/editor_scale.h"
static Rect2i prev_rect = Rect2i(); Rect2i EditorQuickOpen::prev_rect = Rect2i();
static bool was_showed = false; bool EditorQuickOpen::was_showed = false;
void EditorQuickOpen::popup_dialog(const String &p_base, bool p_enable_multi, bool p_dont_clear) { void EditorQuickOpen::popup_dialog(const String &p_base, bool p_enable_multi, bool p_dont_clear) {
base_type = p_base; base_type = p_base;

View File

@ -39,6 +39,9 @@
class EditorQuickOpen : public ConfirmationDialog { class EditorQuickOpen : public ConfirmationDialog {
GDCLASS(EditorQuickOpen, ConfirmationDialog); GDCLASS(EditorQuickOpen, ConfirmationDialog);
static Rect2i prev_rect;
static bool was_showed;
LineEdit *search_box = nullptr; LineEdit *search_box = nullptr;
Tree *search_options = nullptr; Tree *search_options = nullptr;
String base_type; String base_type;

View File

@ -30,14 +30,12 @@
#include "editor_scale.h" #include "editor_scale.h"
#include "core/os/os.h" float EditorScale::_scale = 1.0f;
static float scale = 1.0; void EditorScale::set_scale(float p_scale) {
_scale = p_scale;
void editor_set_scale(float p_scale) {
scale = p_scale;
} }
float editor_get_scale() { float EditorScale::get_scale() {
return scale; return _scale;
} }

View File

@ -31,9 +31,14 @@
#ifndef EDITOR_SCALE_H #ifndef EDITOR_SCALE_H
#define EDITOR_SCALE_H #define EDITOR_SCALE_H
void editor_set_scale(float p_scale); class EditorScale {
float editor_get_scale(); 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 #endif // EDITOR_SCALE_H

View File

@ -481,7 +481,7 @@ void TextEditor::_convert_case(CodeTextEditor::CaseStyle p_case) {
code_editor->convert_case(p_case); code_editor->convert_case(p_case);
} }
static ScriptEditorBase *create_editor(const Ref<Resource> &p_resource) { ScriptEditorBase *TextEditor::create_editor(const Ref<Resource> &p_resource) {
if (Object::cast_to<TextFile>(*p_resource) || Object::cast_to<JSON>(*p_resource)) { if (Object::cast_to<TextFile>(*p_resource) || Object::cast_to<JSON>(*p_resource)) {
return memnew(TextEditor); return memnew(TextEditor);
} }

View File

@ -38,6 +38,8 @@
class TextEditor : public ScriptEditorBase { class TextEditor : public ScriptEditorBase {
GDCLASS(TextEditor, ScriptEditorBase); GDCLASS(TextEditor, ScriptEditorBase);
static ScriptEditorBase *create_editor(const Ref<Resource> &p_resource);
private: private:
CodeTextEditor *code_editor = nullptr; CodeTextEditor *code_editor = nullptr;

View File

@ -4982,7 +4982,7 @@ void VisualShaderEditor::_preview_size_changed() {
preview_vbox->set_custom_minimum_size(preview_window->get_size()); 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); 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); 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.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.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
info.shader_types = ShaderTypes::get_singleton()->get_types(); 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; ShaderLanguage sl;

View File

@ -2763,28 +2763,28 @@ ProjectManager::ProjectManager() {
switch (display_scale) { switch (display_scale) {
case 0: case 0:
// Try applying a suitable display scale automatically. // 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; break;
case 1: case 1:
editor_set_scale(0.75); EditorScale::set_scale(0.75);
break; break;
case 2: case 2:
editor_set_scale(1.0); EditorScale::set_scale(1.0);
break; break;
case 3: case 3:
editor_set_scale(1.25); EditorScale::set_scale(1.25);
break; break;
case 4: case 4:
editor_set_scale(1.5); EditorScale::set_scale(1.5);
break; break;
case 5: case 5:
editor_set_scale(1.75); EditorScale::set_scale(1.75);
break; break;
case 6: case 6:
editor_set_scale(2.0); EditorScale::set_scale(2.0);
break; break;
default: default:
editor_set_scale(EDITOR_GET("interface/editor/custom_display_scale")); EditorScale::set_scale(EDITOR_GET("interface/editor/custom_display_scale"));
break; break;
} }
EditorFileDialog::get_icon_func = &ProjectManager::_file_dialog_get_icon; EditorFileDialog::get_icon_func = &ProjectManager::_file_dialog_get_icon;

View File

@ -6,9 +6,23 @@ import subprocess
from collections import OrderedDict from collections import OrderedDict
from collections.abc import Mapping from collections.abc import Mapping
from typing import Iterator 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) # Convert string to list of absolute paths (including expanding wildcard)
if isinstance(files, (str, bytes)): if isinstance(files, (str, bytes)):
# Keep SCons project-absolute path as they are (no wildcard support) # 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 skip_gen_cpp = "*" in files
dir_path = self.Dir(".").abspath dir_path = self.Dir(".").abspath
files = sorted(glob.glob(dir_path + "/" + files)) 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")] files = [f for f in files if not f.endswith(".gen.cpp")]
# Add each path as compiled Object following environment (self) configuration # Add each path as compiled Object following environment (self) configuration
@ -35,6 +49,72 @@ def add_source_files(self, sources, files):
sources.append(obj) 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): def disable_warnings(self):
# 'self' is the environment # 'self' is the environment
if self.msvc: if self.msvc:

View File

@ -941,7 +941,7 @@ void AnimationTree::_clear_playing_caches() {
playing_caches.clear(); playing_caches.clear();
} }
static void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) { void AnimationTree::_call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) {
// Separate function to use alloca() more efficiently // Separate function to use alloca() more efficiently
const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size()); const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size());
const Variant *args = p_params.ptr(); const Variant *args = p_params.ptr();

View File

@ -194,6 +194,8 @@ class AnimationNodeEndState : public AnimationRootNode {
class AnimationTree : public Node { class AnimationTree : public Node {
GDCLASS(AnimationTree, Node); GDCLASS(AnimationTree, Node);
void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred);
public: public:
enum AnimationProcessCallback { enum AnimationProcessCallback {
ANIMATION_PROCESS_PHYSICS, ANIMATION_PROCESS_PHYSICS,

View File

@ -34,12 +34,6 @@
#include "graph_edit.h" #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) { bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name; String str = p_name;

View File

@ -37,6 +37,12 @@
class GraphNode : public Container { class GraphNode : public Container {
GDCLASS(GraphNode, Container); GDCLASS(GraphNode, Container);
struct _MinSizeCache {
int min_size;
bool will_stretch;
int final_size;
};
public: public:
enum Overlay { enum Overlay {
OVERLAY_DISABLED, OVERLAY_DISABLED,

View File

@ -795,8 +795,8 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, Local
_create_list_from_arrays(arr, r_vertex, r_index, lformat); _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 }; 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 };
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_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<SurfaceTool::Vertex> &ret, uint32_t *r_format) { void SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays, LocalVector<SurfaceTool::Vertex> &ret, uint32_t *r_format) {
ret.clear(); ret.clear();

View File

@ -38,6 +38,9 @@
class SurfaceTool : public RefCounted { class SurfaceTool : public RefCounted {
GDCLASS(SurfaceTool, 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: public:
struct Vertex { struct Vertex {
Vector3 vertex; Vector3 vertex;

339
scu_builders.py Normal file
View File

@ -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

View File

@ -39,6 +39,39 @@ protected:
bool dynamic_A = false; bool dynamic_A = false;
bool dynamic_B = 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: public:
virtual bool setup(real_t p_step) override { return false; } virtual bool setup(real_t p_step) override { return false; }
virtual bool pre_solve(real_t p_step) override { return true; } virtual bool pre_solve(real_t p_step) override { return true; }

View File

@ -51,39 +51,6 @@ Written by: Marcus Hennix
#include "godot_cone_twist_joint_3d.h" #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) : GodotConeTwistJoint3D::GodotConeTwistJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) :
GodotJoint3D(_arr, 2) { GodotJoint3D(_arr, 2) {
A = rbA; A = rbA;

View File

@ -49,24 +49,6 @@ subject to the following restrictions:
#include "godot_hinge_joint_3d.h" #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) : GodotHingeJoint3D::GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameA, const Transform3D &frameB) :
GodotJoint3D(_arr, 2) { GodotJoint3D(_arr, 2) {
A = rbA; 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() { real_t GodotHingeJoint3D::get_hinge_angle() {
const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(0)); 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)); const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(1));

View File

@ -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) : GodotSliderJoint3D::GodotSliderJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB) :
GodotJoint3D(_arr, 2), GodotJoint3D(_arr, 2),
m_frameInA(frameInA), m_frameInA(frameInA),

View File

@ -36,8 +36,6 @@
#include "rendering_server_globals.h" #include "rendering_server_globals.h"
#include "servers/rendering/storage/texture_storage.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) { 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"); RENDER_TIMESTAMP("Cull CanvasItem Tree");

View File

@ -183,6 +183,8 @@ private:
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 _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); 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_list;
RendererCanvasRender::Item **z_last_list; RendererCanvasRender::Item **z_last_list;