diff --git a/examples_dd3d/DebugDrawDemoScene.gd b/examples_dd3d/DebugDrawDemoScene.gd index 52078ccc..b8b80ecc 100644 --- a/examples_dd3d/DebugDrawDemoScene.gd +++ b/examples_dd3d/DebugDrawDemoScene.gd @@ -3,11 +3,13 @@ extends Node3D @export var custom_font : Font @export var zylann_example := false +@export var update_in_physics := false @export var test_text := true @export var test_graphs := false @export var more_test_cases := true @export var draw_array_of_boxes := false @export_range(0, 5, 0.001) var debug_thickness := 0.05 +@export_range(0, 1, 0.001) var debug_center_brightness := 0.8 @export_range(0, 1024) var start_culling_distance := 55.0 @export_group("Text groups", "text_groups") @@ -67,11 +69,24 @@ func _update_keys_just_press(): button_presses[KEY_3] = set_key.call(KEY_3) -func _process(delta: float) -> void: +func _process(delta): + if !update_in_physics: + main_update(delta) + + +func _physics_process(delta: float) -> void: + if update_in_physics: + main_update(delta) + + if not zylann_example: + DebugDraw3D.draw_line($"Lines/8".global_transform.origin, $Lines/Target.global_transform.origin, Color.YELLOW) + + +func main_update(delta: float) -> void: if Input.is_action_just_pressed("ui_end"): DebugDraw3D.regenerate_geometry_meshes() - DebugDraw3D.scoped_config().set_thickness(debug_thickness) + DebugDraw3D.scoped_config().set_thickness(debug_thickness).set_center_brightness(debug_center_brightness) if false: #test var _s11 = DebugDraw3D.new_scoped_config().set_thickness(1) if true: @@ -204,7 +219,10 @@ func _process(delta: float) -> void: var points_below2: PackedVector3Array = [] var points_below3: PackedVector3Array = [] var lines_above: PackedVector3Array = [] + for c in $LinePath.get_children(): + if not c is Node3D: + break points.append(c.global_transform.origin) points_below.append(c.global_transform.origin + Vector3.DOWN) points_below2.append(c.global_transform.origin + Vector3.DOWN * 2) @@ -226,15 +244,19 @@ func _process(delta: float) -> void: var _a11 = DebugDraw3D.new_scoped_config().set_thickness(0) DebugDraw3D.draw_camera_frustum($Camera, Color.DARK_ORANGE) - DebugDraw3D.draw_arrow($Misc/Arrow.global_transform, Color.YELLOW_GREEN) + if true: + var _s123 = DebugDraw3D.new_scoped_config().set_center_brightness(0.1) + DebugDraw3D.draw_arrow($Misc/Arrow.global_transform, Color.YELLOW_GREEN) DebugDraw3D.draw_square($Misc/Billboard.global_transform.origin, 0.5, Color.GREEN) DebugDraw3D.draw_position($Misc/Position.global_transform, Color.BROWN) DebugDraw3D.draw_gizmo($Misc/GizmoTransform.global_transform, DebugDraw3D.empty_color, true) - DebugDraw3D.draw_gizmo($Misc/GizmoNormal.global_transform.orthonormalized(), DebugDraw3D.empty_color, false) DebugDraw3D.draw_gizmo($Misc/GizmoOneColor.global_transform, Color.BROWN, true) + if true: + var _s123 = DebugDraw3D.new_scoped_config().set_center_brightness(0.5) + DebugDraw3D.draw_gizmo($Misc/GizmoNormal.global_transform.orthonormalized(), DebugDraw3D.empty_color, false) var tg : Transform3D = $Misc/Grids/Grid.global_transform var tn : Vector3 = $Misc/Grids/Grid/Subdivision.transform.origin diff --git a/examples_dd3d/DebugDrawDemoScene.tscn b/examples_dd3d/DebugDrawDemoScene.tscn index 089f1961..2a382104 100644 --- a/examples_dd3d/DebugDrawDemoScene.tscn +++ b/examples_dd3d/DebugDrawDemoScene.tscn @@ -375,6 +375,9 @@ func _on_Button_pressed() -> void: process_priority = 1 script = ExtResource("1") custom_font = ExtResource("2_aedbq") +update_in_physics = true +draw_array_of_boxes = true +text_groups_show_stats = true text_groups_position = 2 [node name="Camera" type="Camera3D" parent="."] @@ -430,13 +433,6 @@ transform = Transform3D(9.78549, 0, 0, 0, 4.20302, 0, 0, 0, 5.62455, -23.6827, - [node name="Lines" type="Node3D" parent="Zones"] transform = Transform3D(10.7186, 0, 0, 0, 3.9777, 0, 0, 0, 7.05487, 10.6302, 1.91174, -7.11416) -[node name="LinePathAnim" type="AnimationPlayer" parent="."] -root_node = NodePath("../LinePath") -libraries = { -"": SubResource("AnimationLibrary_nj4nv") -} -autoplay = "New Anim" - [node name="Label3D" type="Label3D" parent="."] transform = Transform3D(1, -1.93359e-07, -8.48396e-08, -1.17881e-07, 1, 5.96046e-08, 6.22839e-09, 0, 1, 0, 0, 0) visible = false @@ -449,6 +445,13 @@ text = "TestTestTestTest TestTestTest" font_size = 80 +[node name="LinesAnim" type="AnimationPlayer" parent="."] +root_node = NodePath("../LinePath") +libraries = { +"": SubResource("AnimationLibrary_nj4nv") +} +autoplay = "New Anim" + [node name="LinePath" type="Node3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.67362, -8) @@ -624,11 +627,14 @@ transform = Transform3D(1, 6.61592e-09, 2.23038e-08, 4.9239e-07, 1, 0, -3.40677e transform = Transform3D(-0.998871, -0.0207882, -0.0355643, 0.0855375, -0.5714, -2.68836, 0.0136011, -0.249864, 0.572532, 1.43126, 0.26242, 1.92347) [node name="6" type="Node3D" parent="Lines"] -transform = Transform3D(-0.998872, -0.0207882, -0.0355643, 0.0855371, -0.5714, -2.68836, 0.0136012, -0.249864, 0.572533, 1.43441, 1.50606, 1.20028) +transform = Transform3D(-0.998872, -0.0207882, -0.0355643, 0.085537, -0.5714, -2.68836, 0.0136012, -0.249864, 0.572533, 1.43441, 1.50606, 1.20028) [node name="7" type="Node3D" parent="Lines"] transform = Transform3D(-0.998873, -0.0207882, -0.0355641, 0.0855357, -0.5714, -2.68836, 0.0136014, -0.249864, 0.572533, 0.0511096, -1.3236, 1.06745) +[node name="8" type="Node3D" parent="Lines"] +transform = Transform3D(-0.998873, -0.0207882, -0.0355641, 0.0855353, -0.5714, -2.68836, 0.0136016, -0.249864, 0.572533, -1.01372, -3.80486, 1.25019) + [node name="Target" type="Node3D" parent="Lines"] transform = Transform3D(1, -2.7352e-06, 2.60722e-07, 3.7807e-06, 1, 0, -3.59182e-07, -1.49012e-08, 1, -0.69134, 0.176476, 1.30597) diff --git a/src/2d/debug_draw_2d.cpp b/src/2d/debug_draw_2d.cpp index 09d35d17..61b69c87 100644 --- a/src/2d/debug_draw_2d.cpp +++ b/src/2d/debug_draw_2d.cpp @@ -128,6 +128,21 @@ void DebugDraw2D::process(double delta) { #endif } +void DebugDraw2D::physics_process_start(double delta) { + ZoneScoped; +#ifndef DISABLE_DEBUG_RENDERING + FrameMarkStart("2D Physics Step"); +#endif +} + +void DebugDraw2D::physics_process_end(double delta) { + ZoneScoped; +#ifndef DISABLE_DEBUG_RENDERING + // TODO implement + FrameMarkEnd("2D Physics Step"); +#endif +} + #ifndef DISABLE_DEBUG_RENDERING void DebugDraw2D::_finish_frame_and_update() { ZoneScoped; diff --git a/src/2d/debug_draw_2d.h b/src/2d/debug_draw_2d.h index 5aabbd7d..fe4590a8 100644 --- a/src/2d/debug_draw_2d.h +++ b/src/2d/debug_draw_2d.h @@ -52,6 +52,8 @@ class DebugDraw2D : public Object { inline bool _is_enabled_override() const; void process(double delta); + void physics_process_start(double delta); + void physics_process_end(double delta); #pragma region Exposed Parameter Values diff --git a/src/3d/debug_draw_3d.cpp b/src/3d/debug_draw_3d.cpp index 1c1c7382..d4486f22 100644 --- a/src/3d/debug_draw_3d.cpp +++ b/src/3d/debug_draw_3d.cpp @@ -128,15 +128,31 @@ DebugDraw3D::~DebugDraw3D() { void DebugDraw3D::process(double delta) { ZoneScoped; - FrameMarkStart("3D Setup"); #ifndef DISABLE_DEBUG_RENDERING + FrameMarkStart("3D Update"); // Update 3D debug dgc->update_geometry(delta); _clear_scoped_configs(); + FrameMarkEnd("3D Update"); +#endif +} + +void DebugDraw3D::physics_process_start(double delta) { + ZoneScoped; +#ifndef DISABLE_DEBUG_RENDERING + FrameMarkStart("3D Physics Step"); + dgc->update_geometry_physics_start(delta); +#endif +} + +void DebugDraw3D::physics_process_end(double delta) { + ZoneScoped; +#ifndef DISABLE_DEBUG_RENDERING + dgc->update_geometry_physics_end(delta); + FrameMarkEnd("3D Physics Step"); #endif - FrameMarkEnd("3D Setup"); } #ifndef DISABLE_DEBUG_RENDERING @@ -459,6 +475,7 @@ void DebugDraw3D::clear_all() { #ifndef DISABLE_DEBUG_RENDERING #define IS_DEFAULT_COLOR(name) (name == Colors::empty_color) +#define GET_PROC_TYPE() (root_node->is_physics_processing() ? ProcessType::PHYSICS_PROCESS : ProcessType::PROCESS) #define CHECK_BEFORE_CALL() \ if (!dgc || NEED_LEAVE || config->is_freeze_3d_render()) return; #else @@ -479,7 +496,7 @@ void DebugDraw3D::add_or_update_line_with_thickness(real_t _exp_time, const std: LOCK_GUARD(datalock); if (!scfg->get_thickness()) { - dgc->geometry_pool.add_or_update_line(_exp_time, _lines, _col); + dgc->geometry_pool.add_or_update_line(_exp_time, GET_PROC_TYPE(), _lines, _col); } else { for (int i = 0; i < _lines.size(); i += 2) { ZoneScoped; @@ -490,6 +507,7 @@ void DebugDraw3D::add_or_update_line_with_thickness(real_t _exp_time, const std: dgc->geometry_pool.add_or_update_instance( InstanceType::LINE_VOLUMETRIC, _exp_time, + GET_PROC_TYPE(), Transform3D(Basis().looking_at(center, get_up_vector(center)).scaled(Vector3(len, len, len)), a), // slow _col, _scoped_config_to_custom(scfg.ptr()), @@ -520,6 +538,7 @@ void DebugDraw3D::draw_sphere_xf_base(const Transform3D &transform, const Color dgc->geometry_pool.add_or_update_instance( _scoped_config_type_convert(hd ? ConvertableInstanceType::SPHERE_HD : ConvertableInstanceType::SPHERE, scfg.ptr()), duration, + GET_PROC_TYPE(), transform, IS_DEFAULT_COLOR(color) ? Colors::chartreuse : color, _scoped_config_to_custom(scfg.ptr()), @@ -563,6 +582,7 @@ void DebugDraw3D::draw_cylinder(const Transform3D &transform, const Color &color dgc->geometry_pool.add_or_update_instance( _scoped_config_type_convert(ConvertableInstanceType::CYLINDER, scfg.ptr()), duration, + GET_PROC_TYPE(), transform, IS_DEFAULT_COLOR(color) ? Colors::forest_green : color, _scoped_config_to_custom(scfg.ptr()), @@ -637,6 +657,7 @@ void DebugDraw3D::draw_box_xf(const Transform3D &transform, const Color &color, dgc->geometry_pool.add_or_update_instance( _scoped_config_type_convert(is_box_centered ? ConvertableInstanceType::CUBE_CENTERED : ConvertableInstanceType::CUBE, scfg.ptr()), duration, + GET_PROC_TYPE(), transform, IS_DEFAULT_COLOR(color) ? Colors::forest_green : color, _scoped_config_to_custom(scfg.ptr()), @@ -678,6 +699,7 @@ void DebugDraw3D::draw_line_hit(const Vector3 &start, const Vector3 &end, const dgc->geometry_pool.add_or_update_instance( InstanceType::BILLBOARD_SQUARE, duration, + GET_PROC_TYPE(), Transform3D(Basis().scaled(Vector3_ONE * hit_size), hit), IS_DEFAULT_COLOR(hit_color) ? config->get_line_hit_color() : hit_color, Color(), // Just a plane, no need to store custom data @@ -779,6 +801,7 @@ void DebugDraw3D::create_arrow(const Vector3 &a, const Vector3 &b, const Color & dgc->geometry_pool.add_or_update_instance( _scoped_config_type_convert(ConvertableInstanceType::ARROWHEAD, scfg.ptr()), duration, + GET_PROC_TYPE(), t, IS_DEFAULT_COLOR(color) ? Colors::light_green : color, _scoped_config_to_custom(scfg.ptr()), @@ -795,6 +818,7 @@ void DebugDraw3D::draw_arrow(const Transform3D &transform, const Color &color, c dgc->geometry_pool.add_or_update_instance( _scoped_config_type_convert(ConvertableInstanceType::ARROWHEAD, scfg.ptr()), duration, + GET_PROC_TYPE(), transform, IS_DEFAULT_COLOR(color) ? Colors::light_green : color, _scoped_config_to_custom(scfg.ptr()), @@ -861,6 +885,7 @@ void DebugDraw3D::draw_square(const Vector3 &position, const real_t &size, const dgc->geometry_pool.add_or_update_instance( InstanceType::BILLBOARD_SQUARE, duration, + GET_PROC_TYPE(), t, IS_DEFAULT_COLOR(color) ? Colors::red : color, _scoped_config_to_custom(scfg.ptr()), @@ -887,6 +912,7 @@ void DebugDraw3D::draw_position(const Transform3D &transform, const Color &color dgc->geometry_pool.add_or_update_instance( _scoped_config_type_convert(ConvertableInstanceType::POSITION, scfg.ptr()), duration, + GET_PROC_TYPE(), transform, IS_DEFAULT_COLOR(color) ? Colors::crimson : color, _scoped_config_to_custom(scfg.ptr()), @@ -1001,4 +1027,5 @@ void DebugDraw3D::draw_camera_frustum_planes(const Array &camera_frustum, const #endif #undef IS_DEFAULT_COLOR +#undef GET_PROC_TYPE #undef NEED_LEAVE diff --git a/src/3d/debug_draw_3d.h b/src/3d/debug_draw_3d.h index 82e9e81d..ff99973c 100644 --- a/src/3d/debug_draw_3d.h +++ b/src/3d/debug_draw_3d.h @@ -108,6 +108,8 @@ class DebugDraw3D : public Object, public IScopedStorage { inline bool _is_enabled_override() const; void process(double delta); + void physics_process_start(double delta); + void physics_process_end(double delta); #pragma region Exposed Parameter Values diff --git a/src/3d/debug_geometry_container.cpp b/src/3d/debug_geometry_container.cpp index acf1126b..589065d4 100644 --- a/src/3d/debug_geometry_container.cpp +++ b/src/3d/debug_geometry_container.cpp @@ -269,6 +269,7 @@ void DebugGeometryContainer::update_geometry(double delta) { geometry_pool.add_or_update_instance( InstanceType::SPHERE, 0, + ProcessType::PROCESS, Transform3D(Basis().scaled(Vector3_ONE * i.second * 2), i.first), Colors::debug_bounds, Color(), @@ -286,6 +287,7 @@ void DebugGeometryContainer::update_geometry(double delta) { geometry_pool.add_or_update_instance( InstanceType::CUBE, 0, + ProcessType::PROCESS, Transform3D(Basis().scaled(diag), bottom), Colors::debug_bounds, Color(), @@ -298,16 +300,29 @@ void DebugGeometryContainer::update_geometry(double delta) { geometry_pool.fill_lines_data(immediate_mesh_storage.mesh); // Update MultiMeshInstances - std::array *, (int)InstanceType::ALL> meshes; - for (int i = 0; i < (int)InstanceType::ALL; i++) { + static std::array *, (int)InstanceType::MAX> meshes; + for (int i = 0; i < (int)InstanceType::MAX; i++) { meshes[i] = &multi_mesh_storage[i].mesh; } geometry_pool.fill_instance_data(meshes); geometry_pool.scan_visible_instances(); - geometry_pool.update_expiration(delta); - geometry_pool.reset_counter(delta); + geometry_pool.update_expiration(delta, ProcessType::PROCESS); + geometry_pool.reset_counter(delta, ProcessType::PROCESS); + + is_frame_rendered = true; +} + +void DebugGeometryContainer::update_geometry_physics_start(double delta) { + if (is_frame_rendered) { + geometry_pool.reset_counter(delta, ProcessType::PHYSICS_PROCESS); + is_frame_rendered = false; + } +} + +void DebugGeometryContainer::update_geometry_physics_end(double delta) { + geometry_pool.update_expiration(delta, ProcessType::PHYSICS_PROCESS); } void DebugGeometryContainer::get_render_stats(Ref &stats) { diff --git a/src/3d/debug_geometry_container.h b/src/3d/debug_geometry_container.h index 58af212b..b87d17b1 100644 --- a/src/3d/debug_geometry_container.h +++ b/src/3d/debug_geometry_container.h @@ -32,7 +32,7 @@ class DebugGeometryContainer { mesh.unref(); } }; - MultiMeshStorage multi_mesh_storage[(int)InstanceType::ALL] = {}; + MultiMeshStorage multi_mesh_storage[(int)InstanceType::MAX] = {}; struct ImmediateMeshStorage { RID instance; @@ -50,6 +50,7 @@ class DebugGeometryContainer { GeometryPool geometry_pool; Node *scene_world_node = nullptr; int32_t render_layers = 1; + bool is_frame_rendered = false; void CreateMMI(InstanceType type, UsingShaderType shader, const String &name, Ref mesh); @@ -61,6 +62,8 @@ class DebugGeometryContainer { Node *get_world(); void update_geometry(double delta); + void update_geometry_physics_start(double delta); + void update_geometry_physics_end(double delta); void set_render_layer_mask(int32_t layers); int32_t get_render_layer_mask() const; diff --git a/src/3d/render_instances.cpp b/src/3d/render_instances.cpp index c845802c..5d19cdd3 100644 --- a/src/3d/render_instances.cpp +++ b/src/3d/render_instances.cpp @@ -15,7 +15,7 @@ template struct TempBigBuffer { private: T m_buffer; - int m_accesses_before_shrink = (int)InstanceType::ALL * 60; // try to shrink after 60 frames + int m_accesses_before_shrink = (int)InstanceType::MAX * 60; // try to shrink after 60 frames int m_shrink_timer; public: @@ -61,11 +61,10 @@ DelayedRendererInstance::DelayedRendererInstance() : DEV_PRINT_STD("New " NAMEOF(DelayedRendererInstance) " created\n"); } -void DelayedRendererInstance::update(real_t _exp_time, const InstanceType &_type, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds) { +void DelayedRendererInstance::update(const real_t &_exp_time, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds) { ZoneScoped; _update(_exp_time, true); - type = _type; bounds = _bounds; data = InstanceTransformAndData3D(_transform, _col, _custom_col); } @@ -75,7 +74,7 @@ DelayedRendererLine::DelayedRendererLine() : DEV_PRINT_STD("New " NAMEOF(DelayedRendererLine) " created\n"); } -void DelayedRendererLine::update(real_t _exp_time, const std::vector &_lines, const Color &_col) { +void DelayedRendererLine::update(const real_t &_exp_time, const std::vector &_lines, const Color &_col) { ZoneScoped; _update(_exp_time, true); @@ -127,7 +126,7 @@ AABB DelayedRendererLine::calculate_bounds_based_on_lines(const std::vector *, (int)InstanceType::ALL> &t_meshes) { +void GeometryPool::fill_instance_data(const std::array *, (int)InstanceType::MAX> &t_meshes) { ZoneScoped; time_spent_to_fill_buffers_of_instances = Time::get_singleton()->get_ticks_usec(); @@ -153,59 +152,52 @@ void GeometryPool::fill_instance_data(const std::array *, (int)In PackedFloat32Array GeometryPool::get_raw_data(InstanceType _type) { ZoneScoped; - auto &inst = instances[(int)_type]; - - size_t buffer_size = (inst.used_instant + inst.delayed.size()) * INSTANCE_DATA_FLOAT_COUNT; thread_local static auto temp_buffer = TempBigBuffer(); - temp_buffer.prepare_buffer(buffer_size); - size_t last_added = 0; + size_t buffer_size = 0; + + { + ZoneScopedN("Prepare buffer"); + for (auto &proc : pools) { + auto &inst = proc.instances[(int)_type]; + buffer_size += (inst.used_instant + inst.delayed.size()) * INSTANCE_DATA_FLOAT_COUNT; + } + temp_buffer.prepare_buffer(buffer_size); + } + if (buffer_size > 0) { + ZoneScopedN("Fill buffer"); auto w = temp_buffer.ptrw(); - auto write_data = [&last_added, &w](DelayedRendererInstance &o) { - size_t id = last_added * INSTANCE_DATA_FLOAT_COUNT; - - last_added++; - - // 7500 instances. 1.2-1.3ms with the old approach and 0.8-0.9ms with the current approach - memcpy(w + id, reinterpret_cast(&o.data), INSTANCE_DATA_FLOAT_COUNT * sizeof(real_t)); - - /*w[id + 0] = o.transform.basis.rows[0][0]; - w[id + 1] = o.transform.basis.rows[0][1]; - w[id + 2] = o.transform.basis.rows[0][2]; - w[id + 3] = o.transform.origin.x; - w[id + 4] = o.transform.basis.rows[1][0]; - w[id + 5] = o.transform.basis.rows[1][1]; - w[id + 6] = o.transform.basis.rows[1][2]; - w[id + 7] = o.transform.origin.y; - w[id + 8] = o.transform.basis.rows[2][0]; - w[id + 9] = o.transform.basis.rows[2][1]; - w[id + 10] = o.transform.basis.rows[2][2]; - w[id + 11] = o.transform.origin.z; - w[id + 12] = o.color[0]; - w[id + 13] = o.color[1]; - w[id + 14] = o.color[2]; - w[id + 15] = o.color[3];*/ - }; - - for (size_t i = 0; i < inst.used_instant; i++) { - auto &o = inst.instant[i]; - o.is_used_one_time = true; - if (o.is_visible) { - write_data(o); - } - } - inst._prev_used_instant = inst.used_instant; + for (auto &proc : pools) { + auto &inst = proc.instances[(int)_type]; - inst.used_delayed = 0; - for (size_t i = 0; i < inst.delayed.size(); i++) { - auto &o = inst.delayed[i]; - if (!o.is_expired()) { - inst.used_delayed++; + auto write_instance_data = [&last_added, &w](DelayedRendererInstance &o) { + size_t id = last_added * INSTANCE_DATA_FLOAT_COUNT; + last_added++; + + // 7500 instances. 1.2-1.3ms with the old approach and 0.8-0.9ms with the current approach + memcpy(w + id, reinterpret_cast(&o.data), INSTANCE_DATA_FLOAT_COUNT * sizeof(real_t)); + }; + + for (size_t i = 0; i < inst.used_instant; i++) { + auto &o = inst.instant[i]; o.is_used_one_time = true; if (o.is_visible) { - write_data(o); + write_instance_data(o); + } + } + inst._prev_used_instant = inst.used_instant; + + inst.used_delayed = 0; + for (size_t i = 0; i < inst.delayed.size(); i++) { + auto &o = inst.delayed[i]; + if (!o.is_expired()) { + inst.used_delayed++; + o.is_used_one_time = true; + if (o.is_visible) { + write_instance_data(o); + } } } } @@ -218,8 +210,14 @@ void GeometryPool::fill_lines_data(Ref _ig) { ZoneScoped; time_spent_to_fill_buffers_of_lines = 0; - if (lines.used_instant == 0 && lines.delayed.size() == 0) + uint64_t used_lines = 0; + for (auto &proc : pools) { + used_lines += proc.lines.used_instant; + used_lines += proc.lines.delayed.size(); + } + if (used_lines == 0) { return; + } size_t spent_timer = Time::get_singleton()->get_ticks_usec(); @@ -227,16 +225,18 @@ void GeometryPool::fill_lines_data(Ref _ig) { size_t used_vertices = 0; // pre calculate buffer size - for (size_t i = 0; i < lines.used_instant; i++) { - auto &o = lines.instant[i]; - if (o.is_visible) { - used_vertices += o.get_lines().size(); + for (auto &proc : pools) { + for (size_t i = 0; i < proc.lines.used_instant; i++) { + auto &o = proc.lines.instant[i]; + if (o.is_visible) { + used_vertices += o.get_lines().size(); + } } - } - for (size_t i = 0; i < lines.delayed.size(); i++) { - auto &o = lines.delayed[i]; - if (o.is_visible && !o.is_expired()) { - used_vertices += o.get_lines().size(); + for (size_t i = 0; i < proc.lines.delayed.size(); i++) { + auto &o = proc.lines.delayed[i]; + if (o.is_visible && !o.is_expired()) { + used_vertices += o.get_lines().size(); + } } } @@ -249,7 +249,7 @@ void GeometryPool::fill_lines_data(Ref _ig) { auto vertices_write = verices_buffer.ptrw(); auto colors_write = colors_buffer.ptrw(); - auto append_lines = [&](const DelayedRendererLine &o) { + auto append_lines = [&vertices_write, &colors_write, &prev_pos](const DelayedRendererLine &o) { size_t lines_size = o.get_lines().size(); std::copy(o.get_lines().begin(), o.get_lines().end(), vertices_write + prev_pos); @@ -258,25 +258,27 @@ void GeometryPool::fill_lines_data(Ref _ig) { prev_pos += lines_size; }; - for (size_t i = 0; i < lines.used_instant; i++) { - auto &o = lines.instant[i]; - if (o.is_visible) { - append_lines(o); - } - o.is_used_one_time = true; - } - lines._prev_used_instant = lines.used_instant; - - lines.used_delayed = 0; - for (size_t i = 0; i < lines.delayed.size(); i++) { - auto &o = lines.delayed[i]; - if (!o.is_expired()) { - lines.used_delayed++; + for (auto &proc : pools) { + for (size_t i = 0; i < proc.lines.used_instant; i++) { + auto &o = proc.lines.instant[i]; if (o.is_visible) { append_lines(o); } + o.is_used_one_time = true; + } + proc.lines._prev_used_instant = proc.lines.used_instant; + + proc.lines.used_delayed = 0; + for (size_t i = 0; i < proc.lines.delayed.size(); i++) { + auto &o = proc.lines.delayed[i]; + if (!o.is_expired()) { + proc.lines.used_delayed++; + if (o.is_visible) { + append_lines(o); + } + } + o.is_used_one_time = true; } - o.is_used_one_time = true; } if (used_vertices > 1) { @@ -291,45 +293,61 @@ void GeometryPool::fill_lines_data(Ref _ig) { time_spent_to_fill_buffers_of_lines = Time::get_singleton()->get_ticks_usec() - spent_timer; } -void GeometryPool::reset_counter(double _delta) { +void GeometryPool::reset_counter(const double &_delta, const ProcessType &p_proc) { ZoneScoped; - lines.reset_counter(_delta); - - for (int i = 0; i < (int)InstanceType::ALL; i++) { - instances[i].reset_counter(_delta, i); + if (p_proc == ProcessType::MAX) { + for (auto &proc : pools) { + for (int i = 0; i < (int)InstanceType::MAX; i++) { + proc.instances[i].reset_counter(_delta, i); + } + proc.lines.reset_counter(_delta); + } + } else { + for (int i = 0; i < (int)InstanceType::MAX; i++) { + pools[(int)p_proc].instances[i].reset_counter(_delta, i); + } + pools[(int)p_proc].lines.reset_counter(_delta); } } void GeometryPool::reset_visible_objects() { ZoneScoped; - for (auto &i : instances) { - i.reset_visible_counter(); + for (auto &proc : pools) { + for (auto &i : proc.instances) { + i.reset_visible_counter(); + } + proc.lines.reset_visible_counter(); } - lines.reset_visible_counter(); } void GeometryPool::update_stats(Ref &stats) const { ZoneScoped; size_t used_instances = 0; - for (auto &i : instances) { - used_instances += i._prev_used_instant; - used_instances += i.used_delayed; - } - + size_t used_lines = 0; size_t visible_instances = 0; - for (auto &i : instances) { - visible_instances += i.visible_objects; - } + size_t visible_lines = 0; + + for (auto &proc : pools) { + for (auto &i : proc.instances) { + used_instances += i._prev_used_instant; + used_instances += i.used_delayed; + } + + for (auto &i : proc.instances) { + visible_instances += i.visible_objects; + } - size_t used_lines = lines._prev_used_instant + lines.used_delayed; + used_lines += proc.lines._prev_used_instant + proc.lines.used_delayed; + visible_lines += proc.lines.visible_objects; + } stats->set_render_stats( /* t_instances */ used_instances, /* t_lines */ used_lines, /* t_visible_instances */ visible_instances, - /* t_visible_lines */ lines.visible_objects, + /* t_visible_lines */ visible_lines, /* t_time_filling_buffers_instances_usec */ time_spent_to_fill_buffers_of_instances, /* t_time_filling_buffers_lines_usec */ time_spent_to_fill_buffers_of_lines, @@ -340,118 +358,133 @@ void GeometryPool::update_stats(Ref &stats) const { void GeometryPool::clear_pool() { ZoneScoped; - for (auto &i : instances) { - i.clear_pools(); + for (auto &proc : pools) { + for (auto &i : proc.instances) { + i.clear_pools(); + } + proc.lines.clear_pools(); } - lines.clear_pools(); } void GeometryPool::for_each_instance(const std::function &_func) { ZoneScoped; - for (auto &inst : instances) { - for (size_t i = 0; i < inst.used_instant; i++) { - _func(&inst.instant[i]); - } - for (size_t i = 0; i < inst.delayed.size(); i++) { - if (!inst.delayed[i].is_expired()) - _func(&inst.delayed[i]); + for (auto &proc : pools) { + for (auto &inst : proc.instances) { + for (size_t i = 0; i < inst.used_instant; i++) { + _func(&inst.instant[i]); + } + for (size_t i = 0; i < inst.delayed.size(); i++) { + if (!inst.delayed[i].is_expired()) + _func(&inst.delayed[i]); + } } } } void GeometryPool::for_each_line(const std::function &_func) { ZoneScoped; - for (size_t i = 0; i < lines.used_instant; i++) { - _func(&lines.instant[i]); - } - for (size_t i = 0; i < lines.delayed.size(); i++) { - if (!lines.delayed[i].is_expired()) - _func(&lines.delayed[i]); + for (auto &proc : pools) { + for (size_t i = 0; i < proc.lines.used_instant; i++) { + _func(&proc.lines.instant[i]); + } + for (size_t i = 0; i < proc.lines.delayed.size(); i++) { + if (!proc.lines.delayed[i].is_expired()) + _func(&proc.lines.delayed[i]); + } } } void GeometryPool::update_visibility(const std::vector > &t_frustums, const GeometryPoolDistanceCullingData &t_distance_data) { ZoneScoped; - uint64_t instant_time = 0; - uint64_t delayed_time = 0; - for (auto &t : instances) { // loop over instance types - uint64_t i_t = Time::get_singleton()->get_ticks_usec(); + uint64_t dt_i = 0, dt_d = 0; + for (auto &proc : pools) { + uint64_t instant_time = 0; + uint64_t delayed_time = 0; + for (auto &t : proc.instances) { // loop over instance types + uint64_t i_t = Time::get_singleton()->get_ticks_usec(); - for (size_t i = 0; i < t.used_instant; i++) - t.instant[i].update_visibility(t_frustums, t_distance_data, true); + for (size_t i = 0; i < t.used_instant; i++) + t.instant[i].update_visibility(t_frustums, t_distance_data, true); - instant_time += Time::get_singleton()->get_ticks_usec() - i_t; - uint64_t d_t = Time::get_singleton()->get_ticks_usec(); + instant_time += Time::get_singleton()->get_ticks_usec() - i_t; + uint64_t d_t = Time::get_singleton()->get_ticks_usec(); - for (size_t i = 0; i < t.delayed.size(); i++) - t.delayed[i].update_visibility(t_frustums, t_distance_data, false); + for (size_t i = 0; i < t.delayed.size(); i++) + t.delayed[i].update_visibility(t_frustums, t_distance_data, false); - delayed_time += Time::get_singleton()->get_ticks_usec() - d_t; - } + delayed_time += Time::get_singleton()->get_ticks_usec() - d_t; + } - // loop over lines - time_spent_to_cull_instant = Time::get_singleton()->get_ticks_usec(); + // loop over lines + uint64_t instant_dt = Time::get_singleton()->get_ticks_usec(); - for (size_t i = 0; i < lines.used_instant; i++) - lines.instant[i].update_visibility(t_frustums, t_distance_data, true); + for (size_t i = 0; i < proc.lines.used_instant; i++) + proc.lines.instant[i].update_visibility(t_frustums, t_distance_data, true); - time_spent_to_cull_instant = Time::get_singleton()->get_ticks_usec() - time_spent_to_cull_instant + instant_time; - time_spent_to_cull_delayed = Time::get_singleton()->get_ticks_usec(); + instant_dt = Time::get_singleton()->get_ticks_usec() - instant_dt + instant_time; + uint64_t delayed_dt = Time::get_singleton()->get_ticks_usec(); - for (size_t i = 0; i < lines.delayed.size(); i++) - lines.delayed[i].update_visibility(t_frustums, t_distance_data, false); + for (size_t i = 0; i < proc.lines.delayed.size(); i++) + proc.lines.delayed[i].update_visibility(t_frustums, t_distance_data, false); - time_spent_to_cull_delayed = Time::get_singleton()->get_ticks_usec() - time_spent_to_cull_delayed + delayed_time; + delayed_dt = Time::get_singleton()->get_ticks_usec() - delayed_dt + delayed_time; + } + time_spent_to_cull_instant = dt_i; + time_spent_to_cull_delayed = dt_d; } -void GeometryPool::update_expiration(double _delta) { +void GeometryPool::update_expiration(const double &_delta, const ProcessType &p_proc) { ZoneScoped; - for (auto &t : instances) + auto &proc = pools[(int)p_proc]; + + for (auto &t : proc.instances) for (size_t i = 0; i < t.delayed.size(); i++) t.delayed[i].update_expiration(_delta); - for (size_t i = 0; i < lines.delayed.size(); i++) - lines.delayed[i].update_expiration(_delta); + for (size_t i = 0; i < proc.lines.delayed.size(); i++) + proc.lines.delayed[i].update_expiration(_delta); } void GeometryPool::scan_visible_instances() { ZoneScoped; reset_visible_objects(); - for (auto &t : instances) { - for (size_t i = 0; i < t.used_instant; i++) - if (t.instant[i].is_visible) - t.visible_objects++; - for (size_t i = 0; i < t.delayed.size(); i++) { - auto &o = t.delayed[i]; - if (o.is_visible && !o.is_expired()) - t.visible_objects++; + for (auto &proc : pools) { + for (auto &t : proc.instances) { + for (size_t i = 0; i < t.used_instant; i++) + if (t.instant[i].is_visible) + t.visible_objects++; + for (size_t i = 0; i < t.delayed.size(); i++) { + auto &o = t.delayed[i]; + if (o.is_visible && !o.is_expired()) + t.visible_objects++; + } } - } - for (size_t i = 0; i < lines.used_instant; i++) - if (lines.instant[i].is_visible) - lines.visible_objects++; + for (size_t i = 0; i < proc.lines.used_instant; i++) + if (proc.lines.instant[i].is_visible) + proc.lines.visible_objects++; - for (size_t i = 0; i < lines.delayed.size(); i++) { - auto &o = lines.delayed[i]; - if (o.is_visible && !o.is_expired()) - lines.visible_objects++; + for (size_t i = 0; i < proc.lines.delayed.size(); i++) { + auto &o = proc.lines.delayed[i]; + if (o.is_visible && !o.is_expired()) + proc.lines.visible_objects++; + } } } -void GeometryPool::add_or_update_instance(InstanceType _type, real_t _exp_time, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds, const std::function &_custom_upd) { +void GeometryPool::add_or_update_instance(InstanceType _type, const real_t &_exp_time, const ProcessType &p_proc, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds, const std::function &_custom_upd) { ZoneScoped; - DelayedRendererInstance *inst = instances[(int)_type].get(_exp_time > 0); - inst->update(_exp_time, _type, _transform, _col, _custom_col, _bounds); + DelayedRendererInstance *inst = pools[(int)p_proc].instances[(int)_type].get(_exp_time > 0); + inst->update(_exp_time, _transform, _col, _custom_col, _bounds); if (_custom_upd) _custom_upd(inst); } -void GeometryPool::add_or_update_line(real_t _exp_time, const std::vector &_lines, const Color &_col, const std::function _custom_upd) { +void GeometryPool::add_or_update_line(const real_t &_exp_time, const ProcessType &p_proc, const std::vector &_lines, const Color &_col, const std::function _custom_upd) { ZoneScoped; - DelayedRendererLine *inst = lines.get(_exp_time > 0); + DelayedRendererLine *inst = pools[(int)p_proc].lines.get(_exp_time > 0); inst->update(_exp_time, _lines, _col); if (_custom_upd) _custom_upd(inst); diff --git a/src/3d/render_instances.h b/src/3d/render_instances.h index 1a5259d9..32c19835 100644 --- a/src/3d/render_instances.h +++ b/src/3d/render_instances.h @@ -51,7 +51,13 @@ enum class InstanceType : char { // Solid geometry BILLBOARD_SQUARE, - ALL, + MAX, +}; + +enum class ProcessType : char { + PROCESS, + PHYSICS_PROCESS, + MAX, }; class GeometryPoolDistanceCullingData { @@ -67,7 +73,7 @@ class GeometryPoolDistanceCullingData { template class DelayedRenderer { protected: - void _update(double exp_time, bool is_vis) { + void _update(const double &exp_time, const bool &is_vis) { ZoneScoped; expiration_time = exp_time; is_used_one_time = false; @@ -75,9 +81,9 @@ class DelayedRenderer { } public: - double expiration_time = 0; - bool is_used_one_time = false; - bool is_visible = true; + double expiration_time; + bool is_used_one_time; + bool is_visible; TBounds bounds; DelayedRenderer() : @@ -122,9 +128,9 @@ class DelayedRenderer { return is_visible; } - void update_expiration(double delta) { + void update_expiration(const double &_delta) { if (!is_expired()) { - expiration_time -= delta; + expiration_time -= _delta; } } }; @@ -164,10 +170,9 @@ class InstanceTransformAndData3D { class DelayedRendererInstance : public DelayedRenderer { public: InstanceTransformAndData3D data; - InstanceType type = InstanceType::CUBE; DelayedRendererInstance(); - void update(real_t _exp_time, const InstanceType &_type, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds); + void update(const real_t &_exp_time, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds); }; class DelayedRendererLine : public DelayedRenderer { @@ -178,7 +183,7 @@ class DelayedRendererLine : public DelayedRenderer { Color customColor; DelayedRendererLine(); - void update(real_t _exp_time, const std::vector &_lines, const Color &_col); + void update(const real_t &_exp_time, const std::vector &_lines, const Color &_col); void set_lines(const std::vector &_lines); const std::vector &get_lines() const; @@ -280,8 +285,10 @@ class GeometryPool { } }; - ObjectsPool instances[(int)InstanceType::ALL] = {}; - ObjectsPool lines; + struct { + ObjectsPool instances[(int)InstanceType::MAX]; + ObjectsPool lines; + } pools[(int)ProcessType::MAX]; uint64_t time_spent_to_fill_buffers_of_instances = 0; uint64_t time_spent_to_fill_buffers_of_lines = 0; @@ -296,19 +303,19 @@ class GeometryPool { ~GeometryPool() { } - void fill_instance_data(const std::array *, (int)InstanceType::ALL> &t_meshes); + void fill_instance_data(const std::array *, (int)InstanceType::MAX> &t_meshes); void fill_lines_data(Ref _ig); - void reset_counter(double _delta); + void reset_counter(const double &_delta, const ProcessType &p_proc = ProcessType::MAX); void reset_visible_objects(); void update_stats(Ref &stats) const; void clear_pool(); void for_each_instance(const std::function &_func); void for_each_line(const std::function &_func); void update_visibility(const std::vector > &t_frustums, const GeometryPoolDistanceCullingData &t_distance_data); - void update_expiration(double _delta); + void update_expiration(const double &_delta, const ProcessType &p_proc); void scan_visible_instances(); - void add_or_update_instance(InstanceType _type, real_t _exp_time, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds, const std::function &_custom_upd = nullptr); - void add_or_update_line(real_t _exp_time, const std::vector &_lines, const Color &_col, const std::function _custom_upd = nullptr); + void add_or_update_instance(InstanceType _type, const real_t &_exp_time, const ProcessType &p_proc, const Transform3D &_transform, const Color &_col, const Color &_custom_col, const SphereBounds &_bounds, const std::function &_custom_upd = nullptr); + void add_or_update_line(const real_t &_exp_time, const ProcessType &p_proc, const std::vector &_lines, const Color &_col, const std::function _custom_upd = nullptr); }; #endif \ No newline at end of file diff --git a/src/debug_draw_manager.cpp b/src/debug_draw_manager.cpp index 5d684d8d..4d6ed580 100644 --- a/src/debug_draw_manager.cpp +++ b/src/debug_draw_manager.cpp @@ -19,6 +19,17 @@ using namespace godot; Object *DebugDrawManager::default_arg_obj = nullptr; #endif +#ifndef DISABLE_DEBUG_RENDERING +void DD3D_PhysicsWatcher::init(DebugDrawManager *p_root) { + root_node = p_root; + set_physics_process_priority(INT32_MIN); +} + +void DD3D_PhysicsWatcher::_physics_process(double delta) { + root_node->_physics_process_start(delta); +} +#endif + DebugDrawManager *DebugDrawManager::singleton = nullptr; const char *DebugDrawManager::s_initial_state = "initial_debug_state"; @@ -115,15 +126,24 @@ void DebugDrawManager::_integrate_into_engine() { // Other classes will not face similar problems ASSIGN_SINGLETON(DebugDrawManager); + // Draw everything after calls from scripts to avoid lagging + set_process_priority(INT32_MAX); + set_physics_process_priority(INT32_MAX); + SCENE_ROOT()->add_child(this); SCENE_ROOT()->move_child(this, 0); - set_process(true); - - debug_draw_3d_singleton->init(this); debug_draw_2d_singleton->init(this); + debug_draw_3d_singleton->init(this); #ifndef DISABLE_DEBUG_RENDERING + { + // will be auto deleted as child + DD3D_PhysicsWatcher *physics_watcher = memnew(DD3D_PhysicsWatcher); + add_child(physics_watcher); + physics_watcher->init(this); + } + // Useful nodes and names: // CanvasItemEditor - probably 2D editor viewport // Node3DEditorViewportContainer - base 3D viewport @@ -191,7 +211,7 @@ void DebugDrawManager::_integrate_into_engine() { ((Control *)default_canvas)->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); debug_draw_2d_singleton->default_canvas = default_canvas; - // will be auto deleted + // will be auto deleted as child add_child(default_canvas); } @@ -255,9 +275,6 @@ void DebugDrawManager::init() { dd2d_aliases = TypedArray(dd2d_a); dd3d_aliases = TypedArray(dd3d_a); - // Draw everything after calls from scripts to avoid lagging - set_process_priority(INT32_MAX); - Engine::get_singleton()->register_singleton(NAMEOF(DebugDrawManager), this); _register_singleton_aliases(manager_aliases, this); @@ -345,6 +362,24 @@ void DebugDrawManager::_process(double delta) { } } +void DebugDrawManager::_physics_process_start(double delta) { + if (debug_enabled) { + DebugDraw3D::get_singleton()->physics_process_start(get_process_delta_time()); + + DebugDraw2D::get_singleton()->physics_process_start(get_process_delta_time()); + } +} + +void DebugDrawManager::_physics_process(double delta) { +#ifndef DISABLE_DEBUG_RENDERING + if (debug_enabled) { + DebugDraw3D::get_singleton()->physics_process_end(get_process_delta_time()); + + DebugDraw2D::get_singleton()->physics_process_end(get_process_delta_time()); + } +#endif +} + #ifdef TOOLS_ENABLED void DebugDrawManager::_try_to_update_cs_bindings() { ZoneScoped; diff --git a/src/debug_draw_manager.h b/src/debug_draw_manager.h index 418e6a17..3789f974 100644 --- a/src/debug_draw_manager.h +++ b/src/debug_draw_manager.h @@ -9,10 +9,29 @@ using namespace godot; class DebugDraw2D; class DebugDraw3D; +class DebugDrawManager; + +#ifndef DISABLE_DEBUG_RENDERING +class DD3D_PhysicsWatcher : public Node { + GDCLASS(DD3D_PhysicsWatcher, Node) +protected: + DebugDrawManager *root_node; + static void _bind_methods(){}; + +public: + void init(DebugDrawManager *p_root); + + virtual void _physics_process(double delta) override; +}; +#endif class DebugDrawManager : public CanvasLayer { GDCLASS(DebugDrawManager, CanvasLayer) protected: +#ifndef DISABLE_DEBUG_RENDERING + friend DD3D_PhysicsWatcher; +#endif + static DebugDrawManager *singleton; String root_settings_section; @@ -92,6 +111,8 @@ class DebugDrawManager : public CanvasLayer { void init(); void deinit(); virtual void _process(double delta) override; + void _physics_process_start(double delta); + virtual void _physics_process(double delta) override; }; #ifdef DEV_ENABLED diff --git a/src/dev_debug_draw_3d_Library.vcxproj b/src/dev_debug_draw_3d_Library.vcxproj index 34d5aff3..4022bb48 100644 --- a/src/dev_debug_draw_3d_Library.vcxproj +++ b/src/dev_debug_draw_3d_Library.vcxproj @@ -148,14 +148,14 @@ WIN64;NOMINMAX;TYPED_METHOD_BIND;TRACY_ENABLE;TRACY_ON_DEMAND;TRACY_DELAYED_INIT;TRACY_MANUAL_LIFETIME;HOT_RELOAD_ENABLED;DEBUG_ENABLED;GDEXTENSION_LIBRARY;TOOLS_ENABLED;%(PreprocessorDefinitions) true Sync - true + false ProgramDatabase stdcpp17 NotSet true - MaxSpeed + Disabled MultiThreaded Default diff --git a/src/register_types.cpp b/src/register_types.cpp index 8cf12530..df05cce7 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -46,6 +46,10 @@ void initialize_debug_draw_3d_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); +#ifndef DISABLE_DEBUG_RENDERING + // TODO register as unexposed + ClassDB::register_class(); +#endif // Since this manager is a node in the scene tree, // it will already be destroyed at the time of cleaning this library.