Browse Source

Merge pull request #45852 from reduz/make-servers-truly-thread-safe

Make Servers truly Thread Safe
Rémi Verschelde 4 năm trước cách đây
mục cha
commit
1808f1d76d
74 tập tin đã thay đổi với 2902 bổ sung2806 xóa
  1. 2 2
      core/config/project_settings.cpp
  2. 5 0
      core/templates/command_queue_mt.h
  3. 82 9
      core/templates/rid_owner.h
  4. 3 7
      main/main.cpp
  5. 4 4
      modules/bullet/bullet_physics_server.cpp
  6. 2 2
      modules/bullet/bullet_physics_server.h
  7. 2 1
      modules/bullet/config.py
  8. 4 4
      modules/bullet/soft_body_bullet.cpp
  9. 3 3
      modules/bullet/soft_body_bullet.h
  10. 4 2
      modules/csg/csg_shape.cpp
  11. 3 2
      modules/gridmap/grid_map.cpp
  12. 0 1
      platform/uwp/os_uwp.cpp
  13. 0 1
      platform/windows/os_windows.cpp
  14. 1 1
      scene/2d/cpu_particles_2d.cpp
  15. 34 27
      scene/2d/joints_2d.cpp
  16. 8 4
      scene/2d/joints_2d.h
  17. 1 1
      scene/2d/skeleton_2d.cpp
  18. 1 1
      scene/3d/cpu_particles_3d.cpp
  19. 1 1
      scene/3d/gi_probe.cpp
  20. 13 16
      scene/3d/physics_body_3d.cpp
  21. 54 53
      scene/3d/physics_joint_3d.cpp
  22. 10 6
      scene/3d/physics_joint_3d.h
  23. 1 1
      scene/3d/skeleton_3d.cpp
  24. 7 7
      scene/3d/soft_body_3d.cpp
  25. 2 2
      scene/3d/soft_body_3d.h
  26. 1 1
      scene/main/viewport.cpp
  27. 1 1
      scene/resources/multimesh.cpp
  28. 1 1
      servers/display_server.h
  29. 8 0
      servers/physics_2d/joints_2d_sw.cpp
  30. 9 4
      servers/physics_2d/joints_2d_sw.h
  31. 54 29
      servers/physics_2d/physics_server_2d_sw.cpp
  32. 14 9
      servers/physics_2d/physics_server_2d_sw.h
  33. 0 13
      servers/physics_2d/physics_server_2d_wrap_mt.cpp
  34. 26 35
      servers/physics_2d/physics_server_2d_wrap_mt.h
  35. 5 5
      servers/physics_3d/collision_object_3d_sw.cpp
  36. 1 1
      servers/physics_3d/joints/cone_twist_joint_3d_sw.h
  37. 1 1
      servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
  38. 1 1
      servers/physics_3d/joints/hinge_joint_3d_sw.h
  39. 1 1
      servers/physics_3d/joints/pin_joint_3d_sw.h
  40. 1 1
      servers/physics_3d/joints/slider_joint_3d_sw.h
  41. 10 1
      servers/physics_3d/joints_3d_sw.h
  42. 182 135
      servers/physics_3d/physics_server_3d_sw.cpp
  43. 49 34
      servers/physics_3d/physics_server_3d_sw.h
  44. 140 0
      servers/physics_3d/physics_server_3d_wrap_mt.cpp
  45. 422 0
      servers/physics_3d/physics_server_3d_wrap_mt.h
  46. 6 6
      servers/physics_3d/space_3d_sw.cpp
  47. 11 6
      servers/physics_server_2d.cpp
  48. 11 6
      servers/physics_server_2d.h
  49. 53 15
      servers/physics_server_3d.cpp
  50. 47 31
      servers/physics_server_3d.h
  51. 11 2
      servers/register_server_types.cpp
  52. 31 18
      servers/rendering/renderer_canvas_cull.cpp
  53. 23 11
      servers/rendering/renderer_canvas_cull.h
  54. 9 3
      servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
  55. 12 6
      servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
  56. 28 10
      servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
  57. 10 6
      servers/rendering/renderer_rd/renderer_scene_render_rd.h
  58. 139 76
      servers/rendering/renderer_rd/renderer_storage_rd.cpp
  59. 78 52
      servers/rendering/renderer_rd/renderer_storage_rd.h
  60. 14 6
      servers/rendering/renderer_scene.h
  61. 17 14
      servers/rendering/renderer_scene_cull.cpp
  62. 17 9
      servers/rendering/renderer_scene_cull.h
  63. 8 5
      servers/rendering/renderer_scene_render.h
  64. 52 28
      servers/rendering/renderer_storage.h
  65. 12 6
      servers/rendering/renderer_viewport.cpp
  66. 6 2
      servers/rendering/renderer_viewport.h
  67. 101 12
      servers/rendering/rendering_server_default.cpp
  68. 622 589
      servers/rendering/rendering_server_default.h
  69. 0 174
      servers/rendering/rendering_server_wrap_mt.cpp
  70. 0 808
      servers/rendering/rendering_server_wrap_mt.h
  71. 2 2
      servers/rendering_server.cpp
  72. 3 3
      servers/rendering_server.h
  73. 395 465
      servers/server_wrap_mt_common.h
  74. 10 4
      tests/test_physics_3d.cpp

+ 2 - 2
core/config/project_settings.cpp

@@ -1244,8 +1244,8 @@ ProjectSettings::ProjectSettings() {
 
 	custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::STRING, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
 	custom_prop_info["rendering/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
-	custom_prop_info["physics/2d/thread_model"] = PropertyInfo(Variant::INT, "physics/2d/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
-	custom_prop_info["rendering/quality/intended_usage/framebuffer_allocation"] = PropertyInfo(Variant::INT, "rendering/quality/intended_usage/framebuffer_allocation", PROPERTY_HINT_ENUM, "2D,2D Without Sampling,3D,3D Without Effects");
+	GLOBAL_DEF("physics/2d/run_on_thread", false);
+	GLOBAL_DEF("physics/3d/run_on_thread", false);
 
 	GLOBAL_DEF("debug/settings/profiler/max_functions", 16384);
 	custom_prop_info["debug/settings/profiler/max_functions"] = PropertyInfo(Variant::INT, "debug/settings/profiler/max_functions", PROPERTY_HINT_RANGE, "128,65535,1");

+ 5 - 0
core/templates/command_queue_mt.h

@@ -498,6 +498,11 @@ public:
 		flush_one();
 	}
 
+	_FORCE_INLINE_ void flush_if_pending() {
+		if (unlikely(read_ptr_and_epoch != write_ptr_and_epoch)) {
+			flush_all();
+		}
+	}
 	void flush_all() {
 		//ERR_FAIL_COND(sync);
 		lock();

+ 82 - 9
core/templates/rid_owner.h

@@ -79,8 +79,7 @@ class RID_Alloc : public RID_AllocBase {
 
 	SpinLock spin_lock;
 
-public:
-	RID make_rid(const T &p_value) {
+	_FORCE_INLINE_ RID _allocate_rid(const T *p_initializer) {
 		if (THREAD_SAFE) {
 			spin_lock.lock();
 		}
@@ -115,15 +114,22 @@ public:
 		uint32_t free_chunk = free_index / elements_in_chunk;
 		uint32_t free_element = free_index % elements_in_chunk;
 
-		T *ptr = &chunks[free_chunk][free_element];
-		memnew_placement(ptr, T(p_value));
+		if (p_initializer) {
+			T *ptr = &chunks[free_chunk][free_element];
+			memnew_placement(ptr, T(*p_initializer));
+		}
 
-		uint32_t validator = (uint32_t)(_gen_id() & 0xFFFFFFFF);
+		uint32_t validator = (uint32_t)(_gen_id() & 0x7FFFFFFF);
 		uint64_t id = validator;
 		id <<= 32;
 		id |= free_index;
 
 		validator_chunks[free_chunk][free_element] = validator;
+
+		if (!p_initializer) {
+			validator_chunks[free_chunk][free_element] |= 0x80000000; //mark uninitialized bit
+		}
+
 		alloc_count++;
 
 		if (THREAD_SAFE) {
@@ -133,7 +139,20 @@ public:
 		return _make_from_id(id);
 	}
 
-	_FORCE_INLINE_ T *getornull(const RID &p_rid) {
+public:
+	RID make_rid(const T &p_value) {
+		return _allocate_rid(&p_value);
+	}
+
+	//allocate but don't initialize, use initialize_rid afterwards
+	RID allocate_rid() {
+		return _allocate_rid(nullptr);
+	}
+
+	_FORCE_INLINE_ T *getornull(const RID &p_rid, bool p_initialize = false) {
+		if (p_rid == RID()) {
+			return nullptr;
+		}
 		if (THREAD_SAFE) {
 			spin_lock.lock();
 		}
@@ -151,10 +170,32 @@ public:
 		uint32_t idx_element = idx % elements_in_chunk;
 
 		uint32_t validator = uint32_t(id >> 32);
-		if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
+
+		if (unlikely(p_initialize)) {
+			if (unlikely(!(validator_chunks[idx_chunk][idx_element] & 0x80000000))) {
+				if (THREAD_SAFE) {
+					spin_lock.unlock();
+				}
+				ERR_FAIL_V_MSG(nullptr, "Initializing already initialized RID");
+			}
+
+			if (unlikely((validator_chunks[idx_chunk][idx_element] & 0x7FFFFFFF) != validator)) {
+				if (THREAD_SAFE) {
+					spin_lock.unlock();
+				}
+				ERR_FAIL_V_MSG(nullptr, "Attempting to initialize the wrong RID");
+				return nullptr;
+			}
+
+			validator_chunks[idx_chunk][idx_element] &= 0x7FFFFFFF; //initialized
+
+		} else if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
 			if (THREAD_SAFE) {
 				spin_lock.unlock();
 			}
+			if (validator_chunks[idx_chunk][idx_element] & 0x80000000) {
+				ERR_FAIL_V_MSG(nullptr, "Attempting to use an uninitialized RID");
+			}
 			return nullptr;
 		}
 
@@ -166,6 +207,11 @@ public:
 
 		return ptr;
 	}
+	void initialize_rid(RID p_rid, const T &p_value) {
+		T *mem = getornull(p_rid, true);
+		ERR_FAIL_COND(!mem);
+		memnew_placement(mem, T(p_value));
+	}
 
 	_FORCE_INLINE_ bool owns(const RID &p_rid) {
 		if (THREAD_SAFE) {
@@ -186,7 +232,7 @@ public:
 
 		uint32_t validator = uint32_t(id >> 32);
 
-		bool owned = validator_chunks[idx_chunk][idx_element] == validator;
+		bool owned = (validator_chunks[idx_chunk][idx_element] & 0x7FFFFFFF) == validator;
 
 		if (THREAD_SAFE) {
 			spin_lock.unlock();
@@ -213,7 +259,12 @@ public:
 		uint32_t idx_element = idx % elements_in_chunk;
 
 		uint32_t validator = uint32_t(id >> 32);
-		if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
+		if (unlikely(validator_chunks[idx_chunk][idx_element] & 0x80000000)) {
+			if (THREAD_SAFE) {
+				spin_lock.unlock();
+			}
+			ERR_FAIL_MSG("Attempted to free an uninitialized or invalid RID");
+		} else if (unlikely(validator_chunks[idx_chunk][idx_element] != validator)) {
 			if (THREAD_SAFE) {
 				spin_lock.unlock();
 			}
@@ -330,6 +381,14 @@ public:
 		return alloc.make_rid(p_ptr);
 	}
 
+	_FORCE_INLINE_ RID allocate_rid() {
+		return alloc.allocate_rid();
+	}
+
+	_FORCE_INLINE_ void initialize_rid(RID p_rid, T *p_ptr) {
+		alloc.initialize_rid(p_rid, p_ptr);
+	}
+
 	_FORCE_INLINE_ T *getornull(const RID &p_rid) {
 		T **ptr = alloc.getornull(p_rid);
 		if (unlikely(!ptr)) {
@@ -338,6 +397,12 @@ public:
 		return *ptr;
 	}
 
+	_FORCE_INLINE_ void replace(const RID &p_rid, T *p_new_ptr) {
+		T **ptr = alloc.getornull(p_rid);
+		ERR_FAIL_COND(!ptr);
+		*ptr = p_new_ptr;
+	}
+
 	_FORCE_INLINE_ bool owns(const RID &p_rid) {
 		return alloc.owns(p_rid);
 	}
@@ -379,6 +444,14 @@ public:
 		return alloc.make_rid(p_ptr);
 	}
 
+	_FORCE_INLINE_ RID allocate_rid() {
+		return alloc.allocate_rid();
+	}
+
+	_FORCE_INLINE_ void initialize_rid(RID p_rid, const T &p_ptr) {
+		alloc.initialize_rid(p_rid, p_ptr);
+	}
+
 	_FORCE_INLINE_ T *getornull(const RID &p_rid) {
 		return alloc.getornull(p_rid);
 	}

+ 3 - 7
main/main.cpp

@@ -71,7 +71,6 @@
 #include "servers/physics_server_3d.h"
 #include "servers/register_server_types.h"
 #include "servers/rendering/rendering_server_default.h"
-#include "servers/rendering/rendering_server_wrap_mt.h"
 #include "servers/text_server.h"
 #include "servers/xr_server.h"
 
@@ -1570,12 +1569,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 
 	/* Initialize Visual Server */
 
-	rendering_server = memnew(RenderingServerDefault);
-	if (OS::get_singleton()->get_render_thread_mode() != OS::RENDER_THREAD_UNSAFE) {
-		rendering_server = memnew(RenderingServerWrapMT(rendering_server,
-				OS::get_singleton()->get_render_thread_mode() ==
-						OS::RENDER_SEPARATE_THREAD));
-	}
+	rendering_server = memnew(RenderingServerDefault(OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD));
 
 	rendering_server->init();
 	rendering_server->set_render_loop_enabled(!disable_render_loop);
@@ -2451,6 +2445,7 @@ bool Main::iteration() {
 	for (int iters = 0; iters < advance.physics_steps; ++iters) {
 		uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
 
+		PhysicsServer3D::get_singleton()->sync();
 		PhysicsServer3D::get_singleton()->flush_queries();
 
 		PhysicsServer2D::get_singleton()->sync();
@@ -2465,6 +2460,7 @@ bool Main::iteration() {
 
 		message_queue->flush();
 
+		PhysicsServer3D::get_singleton()->end_sync();
 		PhysicsServer3D::get_singleton()->step(physics_step * time_scale);
 
 		PhysicsServer2D::get_singleton()->end_sync();

+ 4 - 4
modules/bullet/bullet_physics_server.cpp

@@ -1059,16 +1059,16 @@ real_t BulletPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) {
 	return body->get_linear_stiffness();
 }
 
-void BulletPhysicsServer3D::soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) {
+void BulletPhysicsServer3D::soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) {
 	SoftBodyBullet *body = soft_body_owner.getornull(p_body);
 	ERR_FAIL_COND(!body);
-	body->set_areaAngular_stiffness(p_stiffness);
+	body->set_angular_stiffness(p_stiffness);
 }
 
-real_t BulletPhysicsServer3D::soft_body_get_areaAngular_stiffness(RID p_body) {
+real_t BulletPhysicsServer3D::soft_body_get_angular_stiffness(RID p_body) {
 	SoftBodyBullet *body = soft_body_owner.getornull(p_body);
 	ERR_FAIL_COND_V(!body, 0.f);
-	return body->get_areaAngular_stiffness();
+	return body->get_angular_stiffness();
 }
 
 void BulletPhysicsServer3D::soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) {

+ 2 - 2
modules/bullet/bullet_physics_server.h

@@ -298,8 +298,8 @@ public:
 	virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override;
 	virtual real_t soft_body_get_linear_stiffness(RID p_body) override;
 
-	virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) override;
-	virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) override;
+	virtual void soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) override;
+	virtual real_t soft_body_get_angular_stiffness(RID p_body) override;
 
 	virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) override;
 	virtual real_t soft_body_get_volume_stiffness(RID p_body) override;

+ 2 - 1
modules/bullet/config.py

@@ -1,5 +1,6 @@
 def can_build(env, platform):
-    return True
+    # API Changed and bullet is disabled at the moment
+    return False
 
 
 def configure(env):

+ 4 - 4
modules/bullet/soft_body_bullet.cpp

@@ -259,10 +259,10 @@ void SoftBodyBullet::set_linear_stiffness(real_t p_val) {
 	}
 }
 
-void SoftBodyBullet::set_areaAngular_stiffness(real_t p_val) {
-	areaAngular_stiffness = p_val;
+void SoftBodyBullet::set_angular_stiffness(real_t p_val) {
+	angular_stiffness = p_val;
 	if (bt_soft_body) {
-		mat0->m_kAST = areaAngular_stiffness;
+		mat0->m_kAST = angular_stiffness;
 	}
 }
 
@@ -409,7 +409,7 @@ void SoftBodyBullet::setup_soft_body() {
 	bt_soft_body->generateBendingConstraints(2, mat0);
 
 	mat0->m_kLST = linear_stiffness;
-	mat0->m_kAST = areaAngular_stiffness;
+	mat0->m_kAST = angular_stiffness;
 	mat0->m_kVST = volume_stiffness;
 
 	// Clusters allow to have Soft vs Soft collision but doesn't work well right now

+ 3 - 3
modules/bullet/soft_body_bullet.h

@@ -67,7 +67,7 @@ private:
 	int simulation_precision = 5;
 	real_t total_mass = 1.;
 	real_t linear_stiffness = 0.5; // [0,1]
-	real_t areaAngular_stiffness = 0.5; // [0,1]
+	real_t angular_stiffness = 0.5; // [0,1]
 	real_t volume_stiffness = 0.5; // [0,1]
 	real_t pressure_coefficient = 0.; // [-inf,+inf]
 	real_t pose_matching_coefficient = 0.; // [0,1]
@@ -129,8 +129,8 @@ public:
 	void set_linear_stiffness(real_t p_val);
 	_FORCE_INLINE_ real_t get_linear_stiffness() const { return linear_stiffness; }
 
-	void set_areaAngular_stiffness(real_t p_val);
-	_FORCE_INLINE_ real_t get_areaAngular_stiffness() const { return areaAngular_stiffness; }
+	void set_angular_stiffness(real_t p_val);
+	_FORCE_INLINE_ real_t get_angular_stiffness() const { return angular_stiffness; }
 
 	void set_volume_stiffness(real_t p_val);
 	_FORCE_INLINE_ real_t get_volume_stiffness() const { return volume_stiffness; }

+ 4 - 2
modules/csg/csg_shape.cpp

@@ -45,7 +45,8 @@ void CSGShape3D::set_use_collision(bool p_enable) {
 
 	if (use_collision) {
 		root_collision_shape.instance();
-		root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+		root_collision_instance = PhysicsServer3D::get_singleton()->body_create();
+		PhysicsServer3D::get_singleton()->body_set_mode(root_collision_instance, PhysicsServer3D::BODY_MODE_STATIC);
 		PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
 		PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
 		PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space());
@@ -494,7 +495,8 @@ void CSGShape3D::_notification(int p_what) {
 
 		if (use_collision && is_root_shape()) {
 			root_collision_shape.instance();
-			root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+			root_collision_instance = PhysicsServer3D::get_singleton()->body_create();
+			PhysicsServer3D::get_singleton()->body_set_mode(root_collision_instance, PhysicsServer3D::BODY_MODE_STATIC);
 			PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
 			PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
 			PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space());

+ 3 - 2
modules/gridmap/grid_map.cpp

@@ -286,7 +286,8 @@ void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) {
 		//create octant because it does not exist
 		Octant *g = memnew(Octant);
 		g->dirty = true;
-		g->static_body = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+		g->static_body = PhysicsServer3D::get_singleton()->body_create();
+		PhysicsServer3D::get_singleton()->body_set_mode(g->static_body, PhysicsServer3D::BODY_MODE_STATIC);
 		PhysicsServer3D::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id());
 		PhysicsServer3D::get_singleton()->body_set_collision_layer(g->static_body, collision_layer);
 		PhysicsServer3D::get_singleton()->body_set_collision_mask(g->static_body, collision_mask);
@@ -491,7 +492,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
 			Octant::MultimeshInstance mmi;
 
 			RID mm = RS::get_singleton()->multimesh_create();
-			RS::get_singleton()->multimesh_allocate(mm, E->get().size(), RS::MULTIMESH_TRANSFORM_3D);
+			RS::get_singleton()->multimesh_allocate_data(mm, E->get().size(), RS::MULTIMESH_TRANSFORM_3D);
 			RS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid());
 
 			int idx = 0;

+ 0 - 1
platform/uwp/os_uwp.cpp

@@ -44,7 +44,6 @@
 #include "platform/windows/windows_terminal_logger.h"
 #include "servers/audio_server.h"
 #include "servers/rendering/rendering_server_default.h"
-#include "servers/rendering/rendering_server_wrap_mt.h"
 
 #include <ppltasks.h>
 #include <wrl.h>

+ 0 - 1
platform/windows/os_windows.cpp

@@ -45,7 +45,6 @@
 #include "platform/windows/display_server_windows.h"
 #include "servers/audio_server.h"
 #include "servers/rendering/rendering_server_default.h"
-#include "servers/rendering/rendering_server_wrap_mt.h"
 #include "windows_terminal_logger.h"
 
 #include <avrt.h>

+ 1 - 1
scene/2d/cpu_particles_2d.cpp

@@ -60,7 +60,7 @@ void CPUParticles2D::set_amount(int p_amount) {
 	}
 
 	particle_data.resize((8 + 4 + 4) * p_amount);
-	RS::get_singleton()->multimesh_allocate(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_2D, true, true);
+	RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_2D, true, true);
 
 	particle_order.resize(p_amount);
 }

+ 34 - 27
scene/2d/joints_2d.cpp

@@ -65,18 +65,16 @@ void Joint2D::_body_exit_tree(const ObjectID &p_body_id) {
 }
 
 void Joint2D::_update_joint(bool p_only_free) {
-	if (joint.is_valid()) {
-		if (ba.is_valid() && bb.is_valid() && exclude_from_collision) {
-			PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, false);
-		}
-
-		PhysicsServer2D::get_singleton()->free(joint);
-		joint = RID();
-		ba = RID();
-		bb = RID();
+	if (ba.is_valid() && bb.is_valid() && exclude_from_collision) {
+		PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, false);
 	}
 
+	ba = RID();
+	bb = RID();
+	configured = false;
+
 	if (p_only_free || !is_inside_tree()) {
+		PhysicsServer2D::get_singleton()->joint_clear(joint);
 		warning = String();
 		return;
 	}
@@ -88,30 +86,35 @@ void Joint2D::_update_joint(bool p_only_free) {
 	PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
 
 	if (node_a && !body_a && node_b && !body_b) {
+		PhysicsServer2D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node A and Node B must be PhysicsBody2Ds");
 		update_configuration_warning();
 		return;
 	}
 
 	if (node_a && !body_a) {
+		PhysicsServer2D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node A must be a PhysicsBody2D");
 		update_configuration_warning();
 		return;
 	}
 
 	if (node_b && !body_b) {
+		PhysicsServer2D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node B must be a PhysicsBody2D");
 		update_configuration_warning();
 		return;
 	}
 
 	if (!body_a || !body_b) {
+		PhysicsServer2D::get_singleton()->joint_clear(joint);
 		warning = TTR("Joint is not connected to two PhysicsBody2Ds");
 		update_configuration_warning();
 		return;
 	}
 
 	if (body_a == body_b) {
+		PhysicsServer2D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node A and Node B must be different PhysicsBody2Ds");
 		update_configuration_warning();
 		return;
@@ -128,7 +131,9 @@ void Joint2D::_update_joint(bool p_only_free) {
 		body_b->force_update_transform();
 	}
 
-	joint = _configure_joint(body_a, body_b);
+	configured = true;
+
+	_configure_joint(joint, body_a, body_b);
 
 	ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
 
@@ -249,6 +254,11 @@ void Joint2D::_bind_methods() {
 }
 
 Joint2D::Joint2D() {
+	joint = PhysicsServer2D::get_singleton()->joint_create();
+}
+
+Joint2D::~Joint2D() {
+	PhysicsServer2D::get_singleton()->free(joint);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -272,16 +282,15 @@ void PinJoint2D::_notification(int p_what) {
 	}
 }
 
-RID PinJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
-	RID pj = PhysicsServer2D::get_singleton()->pin_joint_create(get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
-	PhysicsServer2D::get_singleton()->pin_joint_set_param(pj, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness);
-	return pj;
+void PinJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+	PhysicsServer2D::get_singleton()->joint_make_pin(p_joint, get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
+	PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness);
 }
 
 void PinJoint2D::set_softness(real_t p_softness) {
 	softness = p_softness;
 	update();
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer2D::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer2D::PIN_JOINT_SOFTNESS, p_softness);
 	}
 }
@@ -323,13 +332,13 @@ void GrooveJoint2D::_notification(int p_what) {
 	}
 }
 
-RID GrooveJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+void GrooveJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
 	Transform2D gt = get_global_transform();
 	Vector2 groove_A1 = gt.get_origin();
 	Vector2 groove_A2 = gt.xform(Vector2(0, length));
 	Vector2 anchor_B = gt.xform(Vector2(0, initial_offset));
 
-	return PhysicsServer2D::get_singleton()->groove_joint_create(groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid());
+	PhysicsServer2D::get_singleton()->joint_make_groove(p_joint, groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid());
 }
 
 void GrooveJoint2D::set_length(real_t p_length) {
@@ -385,19 +394,17 @@ void DampedSpringJoint2D::_notification(int p_what) {
 	}
 }
 
-RID DampedSpringJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+void DampedSpringJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
 	Transform2D gt = get_global_transform();
 	Vector2 anchor_A = gt.get_origin();
 	Vector2 anchor_B = gt.xform(Vector2(0, length));
 
-	RID dsj = PhysicsServer2D::get_singleton()->damped_spring_joint_create(anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid());
+	PhysicsServer2D::get_singleton()->joint_make_damped_spring(p_joint, anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid());
 	if (rest_length) {
-		PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(dsj, PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, rest_length);
+		PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, rest_length);
 	}
-	PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(dsj, PhysicsServer2D::DAMPED_SPRING_STIFFNESS, stiffness);
-	PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(dsj, PhysicsServer2D::DAMPED_SPRING_DAMPING, damping);
-
-	return dsj;
+	PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_STIFFNESS, stiffness);
+	PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_DAMPING, damping);
 }
 
 void DampedSpringJoint2D::set_length(real_t p_length) {
@@ -412,7 +419,7 @@ real_t DampedSpringJoint2D::get_length() const {
 void DampedSpringJoint2D::set_rest_length(real_t p_rest_length) {
 	rest_length = p_rest_length;
 	update();
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, p_rest_length ? p_rest_length : length);
 	}
 }
@@ -424,7 +431,7 @@ real_t DampedSpringJoint2D::get_rest_length() const {
 void DampedSpringJoint2D::set_stiffness(real_t p_stiffness) {
 	stiffness = p_stiffness;
 	update();
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_SPRING_STIFFNESS, p_stiffness);
 	}
 }
@@ -436,7 +443,7 @@ real_t DampedSpringJoint2D::get_stiffness() const {
 void DampedSpringJoint2D::set_damping(real_t p_damping) {
 	damping = p_damping;
 	update();
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_SPRING_DAMPING, p_damping);
 	}
 }

+ 8 - 4
scene/2d/joints_2d.h

@@ -46,6 +46,7 @@ class Joint2D : public Node2D {
 	real_t bias = 0.0;
 
 	bool exclude_from_collision = true;
+	bool configured = false;
 	String warning;
 
 protected:
@@ -54,10 +55,12 @@ protected:
 	void _update_joint(bool p_only_free = false);
 
 	void _notification(int p_what);
-	virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0;
+	virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0;
 
 	static void _bind_methods();
 
+	_FORCE_INLINE_ bool is_configured() const { return configured; }
+
 public:
 	virtual String get_configuration_warning() const override;
 
@@ -75,6 +78,7 @@ public:
 
 	RID get_joint() const { return joint; }
 	Joint2D();
+	~Joint2D();
 };
 
 class PinJoint2D : public Joint2D {
@@ -84,7 +88,7 @@ class PinJoint2D : public Joint2D {
 
 protected:
 	void _notification(int p_what);
-	virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
 	static void _bind_methods();
 
 public:
@@ -102,7 +106,7 @@ class GrooveJoint2D : public Joint2D {
 
 protected:
 	void _notification(int p_what);
-	virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
 	static void _bind_methods();
 
 public:
@@ -125,7 +129,7 @@ class DampedSpringJoint2D : public Joint2D {
 
 protected:
 	void _notification(int p_what);
-	virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
 	static void _bind_methods();
 
 public:

+ 1 - 1
scene/2d/skeleton_2d.cpp

@@ -182,7 +182,7 @@ void Skeleton2D::_update_bone_setup() {
 	}
 
 	bone_setup_dirty = false;
-	RS::get_singleton()->skeleton_allocate(skeleton, bones.size(), true);
+	RS::get_singleton()->skeleton_allocate_data(skeleton, bones.size(), true);
 
 	bones.sort(); //sorty so they are always in the same order/index
 

+ 1 - 1
scene/3d/cpu_particles_3d.cpp

@@ -73,7 +73,7 @@ void CPUParticles3D::set_amount(int p_amount) {
 	}
 
 	particle_data.resize((12 + 4 + 4) * p_amount);
-	RS::get_singleton()->multimesh_allocate(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true);
+	RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true);
 
 	particle_order.resize(p_amount);
 }

+ 1 - 1
scene/3d/gi_probe.cpp

@@ -91,7 +91,7 @@ Dictionary GIProbeData::_get_data() const {
 }
 
 void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
-	RS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
+	RS::get_singleton()->gi_probe_allocate_data(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
 	bounds = p_aabb;
 	to_cell_xform = p_to_cell_xform;
 	octree_size = p_octree_size;

+ 13 - 16
scene/3d/physics_body_3d.cpp

@@ -148,7 +148,8 @@ void PhysicsBody3D::_bind_methods() {
 }
 
 PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
-		CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(p_mode), false) {
+		CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
+	PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), p_mode);
 	collision_layer = 1;
 	collision_mask = 1;
 }
@@ -2011,7 +2012,7 @@ void PhysicalBone3D::_notification(int p_what) {
 			update_bone_id();
 			reset_to_rest_position();
 			reset_physics_simulation_state();
-			if (!joint.is_valid() && joint_data) {
+			if (joint_data) {
 				_reload_joint();
 			}
 			break;
@@ -2022,10 +2023,7 @@ void PhysicalBone3D::_notification(int p_what) {
 				}
 			}
 			parent_skeleton = nullptr;
-			if (joint.is_valid()) {
-				PhysicsServer3D::get_singleton()->free(joint);
-				joint = RID();
-			}
+			PhysicsServer3D::get_singleton()->joint_clear(joint);
 			break;
 		case NOTIFICATION_TRANSFORM_CHANGED:
 			if (Engine::get_singleton()->is_editor_hint()) {
@@ -2175,17 +2173,14 @@ void PhysicalBone3D::_fix_joint_offset() {
 }
 
 void PhysicalBone3D::_reload_joint() {
-	if (joint.is_valid()) {
-		PhysicsServer3D::get_singleton()->free(joint);
-		joint = RID();
-	}
-
 	if (!parent_skeleton) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		return;
 	}
 
 	PhysicalBone3D *body_a = parent_skeleton->get_physical_bone_parent(bone_id);
 	if (!body_a) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		return;
 	}
 
@@ -2195,7 +2190,7 @@ void PhysicalBone3D::_reload_joint() {
 
 	switch (get_joint_type()) {
 		case JOINT_TYPE_PIN: {
-			joint = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin);
+			PhysicsServer3D::get_singleton()->joint_make_pin(joint, body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin);
 			const PinJointData *pjd(static_cast<const PinJointData *>(joint_data));
 			PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_BIAS, pjd->bias);
 			PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_DAMPING, pjd->damping);
@@ -2203,7 +2198,7 @@ void PhysicalBone3D::_reload_joint() {
 
 		} break;
 		case JOINT_TYPE_CONE: {
-			joint = PhysicsServer3D::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset);
+			PhysicsServer3D::get_singleton()->joint_make_cone_twist(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
 			const ConeJointData *cjd(static_cast<const ConeJointData *>(joint_data));
 			PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span);
 			PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span);
@@ -2213,7 +2208,7 @@ void PhysicalBone3D::_reload_joint() {
 
 		} break;
 		case JOINT_TYPE_HINGE: {
-			joint = PhysicsServer3D::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset);
+			PhysicsServer3D::get_singleton()->joint_make_hinge(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
 			const HingeJointData *hjd(static_cast<const HingeJointData *>(joint_data));
 			PhysicsServer3D::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled);
 			PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper);
@@ -2224,7 +2219,7 @@ void PhysicalBone3D::_reload_joint() {
 
 		} break;
 		case JOINT_TYPE_SLIDER: {
-			joint = PhysicsServer3D::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset);
+			PhysicsServer3D::get_singleton()->joint_make_slider(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
 			const SliderJointData *sjd(static_cast<const SliderJointData *>(joint_data));
 			PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper);
 			PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower);
@@ -2239,7 +2234,7 @@ void PhysicalBone3D::_reload_joint() {
 
 		} break;
 		case JOINT_TYPE_6DOF: {
-			joint = PhysicsServer3D::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset);
+			PhysicsServer3D::get_singleton()->joint_make_generic_6dof(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
 			const SixDOFJointData *g6dofjd(static_cast<const SixDOFJointData *>(joint_data));
 			for (int axis = 0; axis < 3; ++axis) {
 				PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled);
@@ -2493,6 +2488,7 @@ bool PhysicalBone3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
 
 PhysicalBone3D::PhysicalBone3D() :
 		PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
+	joint = PhysicsServer3D::get_singleton()->joint_create();
 	reset_physics_simulation_state();
 }
 
@@ -2500,6 +2496,7 @@ PhysicalBone3D::~PhysicalBone3D() {
 	if (joint_data) {
 		memdelete(joint_data);
 	}
+	PhysicsServer3D::get_singleton()->free(joint);
 }
 
 void PhysicalBone3D::update_bone_id() {

+ 54 - 53
scene/3d/physics_joint_3d.cpp

@@ -62,18 +62,17 @@ void Joint3D::_body_exit_tree(const ObjectID &p_body_id) {
 }
 
 void Joint3D::_update_joint(bool p_only_free) {
-	if (joint.is_valid()) {
-		if (ba.is_valid() && bb.is_valid()) {
-			PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb);
-		}
-
-		PhysicsServer3D::get_singleton()->free(joint);
-		joint = RID();
-		ba = RID();
-		bb = RID();
+	if (ba.is_valid() && bb.is_valid()) {
+		PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb);
 	}
 
+	ba = RID();
+	bb = RID();
+
+	configured = false;
+
 	if (p_only_free || !is_inside_tree()) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		warning = String();
 		return;
 	}
@@ -85,30 +84,35 @@ void Joint3D::_update_joint(bool p_only_free) {
 	PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
 
 	if (node_a && !body_a && node_b && !body_b) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node A and Node B must be PhysicsBody3Ds");
 		update_configuration_warning();
 		return;
 	}
 
 	if (node_a && !body_a) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node A must be a PhysicsBody3D");
 		update_configuration_warning();
 		return;
 	}
 
 	if (node_b && !body_b) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node B must be a PhysicsBody3D");
 		update_configuration_warning();
 		return;
 	}
 
 	if (!body_a && !body_b) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		warning = TTR("Joint is not connected to any PhysicsBody3Ds");
 		update_configuration_warning();
 		return;
 	}
 
 	if (body_a == body_b) {
+		PhysicsServer3D::get_singleton()->joint_clear(joint);
 		warning = TTR("Node A and Node B must be different PhysicsBody3Ds");
 		update_configuration_warning();
 		return;
@@ -117,14 +121,14 @@ void Joint3D::_update_joint(bool p_only_free) {
 	warning = String();
 	update_configuration_warning();
 
+	configured = true;
+
 	if (body_a) {
-		joint = _configure_joint(body_a, body_b);
+		_configure_joint(joint, body_a, body_b);
 	} else if (body_b) {
-		joint = _configure_joint(body_b, nullptr);
+		_configure_joint(joint, body_b, nullptr);
 	}
 
-	ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
-
 	PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
 
 	if (body_a) {
@@ -246,6 +250,11 @@ void Joint3D::_bind_methods() {
 
 Joint3D::Joint3D() {
 	set_notify_transform(true);
+	joint = PhysicsServer3D::get_singleton()->joint_create();
+}
+
+Joint3D::~Joint3D() {
+	PhysicsServer3D::get_singleton()->free(joint);
 }
 
 ///////////////////////////////////
@@ -266,7 +275,7 @@ void PinJoint3D::_bind_methods() {
 void PinJoint3D::set_param(Param p_param, real_t p_value) {
 	ERR_FAIL_INDEX(p_param, 3);
 	params[p_param] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer3D::PinJointParam(p_param), p_value);
 	}
 }
@@ -276,7 +285,7 @@ real_t PinJoint3D::get_param(Param p_param) const {
 	return params[p_param];
 }
 
-RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void PinJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
 	Vector3 pinpos = get_global_transform().origin;
 	Vector3 local_a = body_a->get_global_transform().affine_inverse().xform(pinpos);
 	Vector3 local_b;
@@ -287,11 +296,10 @@ RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
 		local_b = pinpos;
 	}
 
-	RID j = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+	PhysicsServer3D::get_singleton()->joint_make_pin(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
 	for (int i = 0; i < 3; i++) {
-		PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PinJointParam(i), params[i]);
+		PhysicsServer3D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer3D::PinJointParam(i), params[i]);
 	}
-	return j;
 }
 
 PinJoint3D::PinJoint3D() {
@@ -364,7 +372,7 @@ void HingeJoint3D::_bind_methods() {
 void HingeJoint3D::set_param(Param p_param, real_t p_value) {
 	ERR_FAIL_INDEX(p_param, PARAM_MAX);
 	params[p_param] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer3D::HingeJointParam(p_param), p_value);
 	}
 
@@ -379,7 +387,7 @@ real_t HingeJoint3D::get_param(Param p_param) const {
 void HingeJoint3D::set_flag(Flag p_flag, bool p_value) {
 	ERR_FAIL_INDEX(p_flag, FLAG_MAX);
 	flags[p_flag] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer3D::HingeJointFlag(p_flag), p_value);
 	}
 
@@ -391,7 +399,7 @@ bool HingeJoint3D::get_flag(Flag p_flag) const {
 	return flags[p_flag];
 }
 
-RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void HingeJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
 	Transform gt = get_global_transform();
 	Transform ainv = body_a->get_global_transform().affine_inverse();
 
@@ -406,15 +414,14 @@ RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b)
 
 	local_b.orthonormalize();
 
-	RID j = PhysicsServer3D::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+	PhysicsServer3D::get_singleton()->joint_make_hinge(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
 	for (int i = 0; i < PARAM_MAX; i++) {
-		PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HingeJointParam(i), params[i]);
+		PhysicsServer3D::get_singleton()->hinge_joint_set_param(p_joint, PhysicsServer3D::HingeJointParam(i), params[i]);
 	}
 	for (int i = 0; i < FLAG_MAX; i++) {
 		set_flag(Flag(i), flags[i]);
-		PhysicsServer3D::get_singleton()->hinge_joint_set_flag(j, PhysicsServer3D::HingeJointFlag(i), flags[i]);
+		PhysicsServer3D::get_singleton()->hinge_joint_set_flag(p_joint, PhysicsServer3D::HingeJointFlag(i), flags[i]);
 	}
-	return j;
 }
 
 HingeJoint3D::HingeJoint3D() {
@@ -515,7 +522,7 @@ void SliderJoint3D::_bind_methods() {
 void SliderJoint3D::set_param(Param p_param, real_t p_value) {
 	ERR_FAIL_INDEX(p_param, PARAM_MAX);
 	params[p_param] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer3D::SliderJointParam(p_param), p_value);
 	}
 	update_gizmo();
@@ -526,7 +533,7 @@ real_t SliderJoint3D::get_param(Param p_param) const {
 	return params[p_param];
 }
 
-RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void SliderJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
 	Transform gt = get_global_transform();
 	Transform ainv = body_a->get_global_transform().affine_inverse();
 
@@ -541,12 +548,10 @@ RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b
 
 	local_b.orthonormalize();
 
-	RID j = PhysicsServer3D::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+	PhysicsServer3D::get_singleton()->joint_make_slider(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
 	for (int i = 0; i < PARAM_MAX; i++) {
-		PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SliderJointParam(i), params[i]);
+		PhysicsServer3D::get_singleton()->slider_joint_set_param(p_joint, PhysicsServer3D::SliderJointParam(i), params[i]);
 	}
-
-	return j;
 }
 
 SliderJoint3D::SliderJoint3D() {
@@ -621,7 +626,7 @@ void ConeTwistJoint3D::_bind_methods() {
 void ConeTwistJoint3D::set_param(Param p_param, real_t p_value) {
 	ERR_FAIL_INDEX(p_param, PARAM_MAX);
 	params[p_param] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value);
 	}
 
@@ -633,7 +638,7 @@ real_t ConeTwistJoint3D::get_param(Param p_param) const {
 	return params[p_param];
 }
 
-RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void ConeTwistJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
 	Transform gt = get_global_transform();
 	//Vector3 cone_twistpos = gt.origin;
 	//Vector3 cone_twistdir = gt.basis.get_axis(2);
@@ -651,12 +656,10 @@ RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *bod
 
 	local_b.orthonormalize();
 
-	RID j = PhysicsServer3D::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+	PhysicsServer3D::get_singleton()->joint_make_cone_twist(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
 	for (int i = 0; i < PARAM_MAX; i++) {
-		PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::ConeTwistJointParam(i), params[i]);
+		PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(p_joint, PhysicsServer3D::ConeTwistJointParam(i), params[i]);
 	}
-
-	return j;
 }
 
 ConeTwistJoint3D::ConeTwistJoint3D() {
@@ -878,7 +881,7 @@ void Generic6DOFJoint3D::_bind_methods() {
 void Generic6DOFJoint3D::set_param_x(Param p_param, real_t p_value) {
 	ERR_FAIL_INDEX(p_param, PARAM_MAX);
 	params_x[p_param] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
 	}
 
@@ -893,7 +896,7 @@ real_t Generic6DOFJoint3D::get_param_x(Param p_param) const {
 void Generic6DOFJoint3D::set_param_y(Param p_param, real_t p_value) {
 	ERR_FAIL_INDEX(p_param, PARAM_MAX);
 	params_y[p_param] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
 	}
 	update_gizmo();
@@ -907,7 +910,7 @@ real_t Generic6DOFJoint3D::get_param_y(Param p_param) const {
 void Generic6DOFJoint3D::set_param_z(Param p_param, real_t p_value) {
 	ERR_FAIL_INDEX(p_param, PARAM_MAX);
 	params_z[p_param] = p_value;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
 	}
 	update_gizmo();
@@ -921,7 +924,7 @@ real_t Generic6DOFJoint3D::get_param_z(Param p_param) const {
 void Generic6DOFJoint3D::set_flag_x(Flag p_flag, bool p_enabled) {
 	ERR_FAIL_INDEX(p_flag, FLAG_MAX);
 	flags_x[p_flag] = p_enabled;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
 	}
 	update_gizmo();
@@ -935,7 +938,7 @@ bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const {
 void Generic6DOFJoint3D::set_flag_y(Flag p_flag, bool p_enabled) {
 	ERR_FAIL_INDEX(p_flag, FLAG_MAX);
 	flags_y[p_flag] = p_enabled;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
 	}
 	update_gizmo();
@@ -949,7 +952,7 @@ bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const {
 void Generic6DOFJoint3D::set_flag_z(Flag p_flag, bool p_enabled) {
 	ERR_FAIL_INDEX(p_flag, FLAG_MAX);
 	flags_z[p_flag] = p_enabled;
-	if (get_joint().is_valid()) {
+	if (is_configured()) {
 		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
 	}
 	update_gizmo();
@@ -960,7 +963,7 @@ bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const {
 	return flags_z[p_flag];
 }
 
-RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+void Generic6DOFJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
 	Transform gt = get_global_transform();
 	//Vector3 cone_twistpos = gt.origin;
 	//Vector3 cone_twistdir = gt.basis.get_axis(2);
@@ -978,19 +981,17 @@ RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *b
 
 	local_b.orthonormalize();
 
-	RID j = PhysicsServer3D::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+	PhysicsServer3D::get_singleton()->joint_make_generic_6dof(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
 	for (int i = 0; i < PARAM_MAX; i++) {
-		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(i), params_x[i]);
-		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(i), params_y[i]);
-		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(i), params_z[i]);
+		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(p_joint, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(i), params_x[i]);
+		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(p_joint, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(i), params_y[i]);
+		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(p_joint, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(i), params_z[i]);
 	}
 	for (int i = 0; i < FLAG_MAX; i++) {
-		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_x[i]);
-		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_y[i]);
-		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_z[i]);
+		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(p_joint, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_x[i]);
+		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(p_joint, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_y[i]);
+		PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(p_joint, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_z[i]);
 	}
-
-	return j;
 }
 
 Generic6DOFJoint3D::Generic6DOFJoint3D() {

+ 10 - 6
scene/3d/physics_joint_3d.h

@@ -47,6 +47,7 @@ class Joint3D : public Node3D {
 	int solver_priority = 1;
 	bool exclude_from_collision = true;
 	String warning;
+	bool configured = false;
 
 protected:
 	void _disconnect_signals();
@@ -55,10 +56,12 @@ protected:
 
 	void _notification(int p_what);
 
-	virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) = 0;
+	virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) = 0;
 
 	static void _bind_methods();
 
+	_FORCE_INLINE_ bool is_configured() const { return configured; }
+
 public:
 	virtual String get_configuration_warning() const override;
 
@@ -76,6 +79,7 @@ public:
 
 	RID get_joint() const { return joint; }
 	Joint3D();
+	~Joint3D();
 };
 
 ///////////////////////////////////////////
@@ -92,7 +96,7 @@ public:
 
 protected:
 	real_t params[3];
-	virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
 	static void _bind_methods();
 
 public:
@@ -129,7 +133,7 @@ public:
 protected:
 	real_t params[PARAM_MAX];
 	bool flags[FLAG_MAX];
-	virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
 	static void _bind_methods();
 
 	void _set_upper_limit(real_t p_limit);
@@ -191,7 +195,7 @@ protected:
 	real_t _get_lower_limit_angular() const;
 
 	real_t params[PARAM_MAX];
-	virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
 	static void _bind_methods();
 
 public:
@@ -224,7 +228,7 @@ protected:
 	real_t _get_twist_span() const;
 
 	real_t params[PARAM_MAX];
-	virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
 	static void _bind_methods();
 
 public:
@@ -302,7 +306,7 @@ protected:
 	real_t params_z[PARAM_MAX];
 	bool flags_z[FLAG_MAX];
 
-	virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+	virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
 	static void _bind_methods();
 
 public:

+ 1 - 1
scene/3d/skeleton_3d.cpp

@@ -304,7 +304,7 @@ void Skeleton3D::_notification(int p_what) {
 				uint32_t bind_count = skin->get_bind_count();
 
 				if (E->get()->bind_count != bind_count) {
-					RS::get_singleton()->skeleton_allocate(skeleton, bind_count);
+					RS::get_singleton()->skeleton_allocate_data(skeleton, bind_count);
 					E->get()->bind_count = bind_count;
 					E->get()->skin_bone_indices.resize(bind_count);
 					E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw();

+ 7 - 7
scene/3d/soft_body_3d.cpp

@@ -337,8 +337,8 @@ void SoftBody3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness);
 	ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness);
 
-	ClassDB::bind_method(D_METHOD("set_areaAngular_stiffness", "areaAngular_stiffness"), &SoftBody3D::set_areaAngular_stiffness);
-	ClassDB::bind_method(D_METHOD("get_areaAngular_stiffness"), &SoftBody3D::get_areaAngular_stiffness);
+	ClassDB::bind_method(D_METHOD("set_angular_stiffness", "angular_stiffness"), &SoftBody3D::set_angular_stiffness);
+	ClassDB::bind_method(D_METHOD("get_angular_stiffness"), &SoftBody3D::get_angular_stiffness);
 
 	ClassDB::bind_method(D_METHOD("set_volume_stiffness", "volume_stiffness"), &SoftBody3D::set_volume_stiffness);
 	ClassDB::bind_method(D_METHOD("get_volume_stiffness"), &SoftBody3D::get_volume_stiffness);
@@ -366,7 +366,7 @@ void SoftBody3D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness");
-	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "areaAngular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_areaAngular_stiffness", "get_areaAngular_stiffness");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_angular_stiffness", "get_angular_stiffness");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient");
@@ -612,12 +612,12 @@ real_t SoftBody3D::get_linear_stiffness() {
 	return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid);
 }
 
-void SoftBody3D::set_areaAngular_stiffness(real_t p_areaAngular_stiffness) {
-	PhysicsServer3D::get_singleton()->soft_body_set_areaAngular_stiffness(physics_rid, p_areaAngular_stiffness);
+void SoftBody3D::set_angular_stiffness(real_t p_angular_stiffness) {
+	PhysicsServer3D::get_singleton()->soft_body_set_angular_stiffness(physics_rid, p_angular_stiffness);
 }
 
-real_t SoftBody3D::get_areaAngular_stiffness() {
-	return PhysicsServer3D::get_singleton()->soft_body_get_areaAngular_stiffness(physics_rid);
+real_t SoftBody3D::get_angular_stiffness() {
+	return PhysicsServer3D::get_singleton()->soft_body_get_angular_stiffness(physics_rid);
 }
 
 void SoftBody3D::set_volume_stiffness(real_t p_volume_stiffness) {

+ 2 - 2
scene/3d/soft_body_3d.h

@@ -149,8 +149,8 @@ public:
 	void set_linear_stiffness(real_t p_linear_stiffness);
 	real_t get_linear_stiffness();
 
-	void set_areaAngular_stiffness(real_t p_areaAngular_stiffness);
-	real_t get_areaAngular_stiffness();
+	void set_angular_stiffness(real_t p_angular_stiffness);
+	real_t get_angular_stiffness();
 
 	void set_volume_stiffness(real_t p_volume_stiffness);
 	real_t get_volume_stiffness();

+ 1 - 1
scene/main/viewport.cpp

@@ -468,7 +468,7 @@ void Viewport::_notification(int p_what) {
 				//3D
 				PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world_3d()->get_space(), get_tree()->get_collision_debug_contact_count());
 				contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create();
-				RenderingServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true);
+				RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true);
 				RenderingServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0);
 				RenderingServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid());
 				contact_3d_debug_instance = RenderingServer::get_singleton()->instance_create();

+ 1 - 1
scene/resources/multimesh.cpp

@@ -217,7 +217,7 @@ Ref<Mesh> MultiMesh::get_mesh() const {
 
 void MultiMesh::set_instance_count(int p_count) {
 	ERR_FAIL_COND(p_count < 0);
-	RenderingServer::get_singleton()->multimesh_allocate(multimesh, p_count, RS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data);
+	RenderingServer::get_singleton()->multimesh_allocate_data(multimesh, p_count, RS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data);
 	instance_count = p_count;
 }
 

+ 1 - 1
servers/display_server.h

@@ -83,7 +83,7 @@ protected:
 	static DisplayServerCreate server_create_functions[MAX_SERVERS];
 	static int server_create_count;
 
-	friend class RenderingServerDefault;
+	friend class RendererViewport;
 	virtual void _set_use_vsync(bool p_enable);
 
 public:

+ 8 - 0
servers/physics_2d/joints_2d_sw.cpp

@@ -55,6 +55,14 @@
  * SOFTWARE.
  */
 
+void Joint2DSW::copy_settings_from(Joint2DSW *p_joint) {
+	set_self(p_joint->get_self());
+	set_max_force(p_joint->get_max_force());
+	set_bias(p_joint->get_bias());
+	set_max_bias(p_joint->get_max_bias());
+	disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies());
+}
+
 static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const Vector2 &rB, const Vector2 &n) {
 	real_t value = 0;
 

+ 9 - 4
servers/physics_2d/joints_2d_sw.h

@@ -49,7 +49,12 @@ public:
 	_FORCE_INLINE_ void set_max_bias(real_t p_bias) { max_bias = p_bias; }
 	_FORCE_INLINE_ real_t get_max_bias() const { return max_bias; }
 
-	virtual PhysicsServer2D::JointType get_type() const = 0;
+	virtual bool setup(real_t p_step) { return false; }
+	virtual void solve(real_t p_step) {}
+
+	void copy_settings_from(Joint2DSW *p_joint);
+
+	virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_MAX; }
 	Joint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) :
 			Constraint2DSW(p_body_ptr, p_body_count) {
 		bias = 0;
@@ -76,7 +81,7 @@ class PinJoint2DSW : public Joint2DSW {
 	real_t softness;
 
 public:
-	virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_PIN; }
+	virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_PIN; }
 
 	virtual bool setup(real_t p_step);
 	virtual void solve(real_t p_step);
@@ -113,7 +118,7 @@ class GrooveJoint2DSW : public Joint2DSW {
 	bool correct;
 
 public:
-	virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_GROOVE; }
+	virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_GROOVE; }
 
 	virtual bool setup(real_t p_step);
 	virtual void solve(real_t p_step);
@@ -146,7 +151,7 @@ class DampedSpringJoint2DSW : public Joint2DSW {
 	real_t v_coef;
 
 public:
-	virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_DAMPED_SPRING; }
+	virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_DAMPED_SPRING; }
 
 	virtual bool setup(real_t p_step);
 	virtual void solve(real_t p_step);

+ 54 - 29
servers/physics_2d/physics_server_2d_sw.cpp

@@ -985,6 +985,24 @@ PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) {
 
 /* JOINT API */
 
+RID PhysicsServer2DSW::joint_create() {
+	Joint2DSW *joint = memnew(Joint2DSW);
+	RID joint_rid = joint_owner.make_rid(joint);
+	joint->set_self(joint_rid);
+	return joint_rid;
+}
+
+void PhysicsServer2DSW::joint_clear(RID p_joint) {
+	Joint2DSW *joint = joint_owner.getornull(p_joint);
+	if (joint->get_type() != JOINT_TYPE_MAX) {
+		Joint2DSW *empty_joint = memnew(Joint2DSW);
+		empty_joint->copy_settings_from(joint);
+
+		joint_owner.replace(p_joint, empty_joint);
+		memdelete(joint);
+	}
+}
+
 void PhysicsServer2DSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) {
 	Joint2DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
@@ -1048,52 +1066,63 @@ bool PhysicsServer2DSW::joint_is_disabled_collisions_between_bodies(RID p_joint)
 	return joint->is_disabled_collisions_between_bodies();
 }
 
-RID PhysicsServer2DSW::pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
+void PhysicsServer2DSW::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
 	Body2DSW *A = body_owner.getornull(p_body_a);
-	ERR_FAIL_COND_V(!A, RID());
+	ERR_FAIL_COND(!A);
 	Body2DSW *B = nullptr;
 	if (body_owner.owns(p_body_b)) {
 		B = body_owner.getornull(p_body_b);
-		ERR_FAIL_COND_V(!B, RID());
+		ERR_FAIL_COND(!B);
 	}
 
+	Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
+
 	Joint2DSW *joint = memnew(PinJoint2DSW(p_pos, A, B));
-	RID self = joint_owner.make_rid(joint);
-	joint->set_self(self);
 
-	return self;
+	joint_owner.replace(p_joint, joint);
+	joint->copy_settings_from(prev_joint);
+	memdelete(prev_joint);
 }
 
-RID PhysicsServer2DSW::groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
+void PhysicsServer2DSW::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
 	Body2DSW *A = body_owner.getornull(p_body_a);
-	ERR_FAIL_COND_V(!A, RID());
+	ERR_FAIL_COND(!A);
 
 	Body2DSW *B = body_owner.getornull(p_body_b);
-	ERR_FAIL_COND_V(!B, RID());
+	ERR_FAIL_COND(!B);
+
+	Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint2DSW *joint = memnew(GrooveJoint2DSW(p_a_groove1, p_a_groove2, p_b_anchor, A, B));
-	RID self = joint_owner.make_rid(joint);
-	joint->set_self(self);
-	return self;
+
+	joint_owner.replace(p_joint, joint);
+	joint->copy_settings_from(prev_joint);
+	memdelete(prev_joint);
 }
 
-RID PhysicsServer2DSW::damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
+void PhysicsServer2DSW::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
 	Body2DSW *A = body_owner.getornull(p_body_a);
-	ERR_FAIL_COND_V(!A, RID());
+	ERR_FAIL_COND(!A);
 
 	Body2DSW *B = body_owner.getornull(p_body_b);
-	ERR_FAIL_COND_V(!B, RID());
+	ERR_FAIL_COND(!B);
+
+	Joint2DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint2DSW *joint = memnew(DampedSpringJoint2DSW(p_anchor_a, p_anchor_b, A, B));
-	RID self = joint_owner.make_rid(joint);
-	joint->set_self(self);
-	return self;
+
+	joint_owner.replace(p_joint, joint);
+	joint->copy_settings_from(prev_joint);
+	memdelete(prev_joint);
 }
 
 void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
 	Joint2DSW *j = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!j);
-	ERR_FAIL_COND(j->get_type() != JOINT_PIN);
+	ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN);
 
 	PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j);
 	pin_joint->set_param(p_param, p_value);
@@ -1102,7 +1131,7 @@ void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param,
 real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
 	Joint2DSW *j = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!j, 0);
-	ERR_FAIL_COND_V(j->get_type() != JOINT_PIN, 0);
+	ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0);
 
 	PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j);
 	return pin_joint->get_param(p_param);
@@ -1111,7 +1140,7 @@ real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param
 void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) {
 	Joint2DSW *j = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!j);
-	ERR_FAIL_COND(j->get_type() != JOINT_DAMPED_SPRING);
+	ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING);
 
 	DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j);
 	dsj->set_param(p_param, p_value);
@@ -1120,7 +1149,7 @@ void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringP
 real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const {
 	Joint2DSW *j = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!j, 0);
-	ERR_FAIL_COND_V(j->get_type() != JOINT_DAMPED_SPRING, 0);
+	ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
 
 	DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j);
 	return dsj->get_param(p_param);
@@ -1128,7 +1157,7 @@ real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSprin
 
 PhysicsServer2D::JointType PhysicsServer2DSW::joint_get_type(RID p_joint) const {
 	Joint2DSW *joint = joint_owner.getornull(p_joint);
-	ERR_FAIL_COND_V(!joint, JOINT_PIN);
+	ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
 
 	return joint->get_type();
 }
@@ -1325,7 +1354,7 @@ int PhysicsServer2DSW::get_process_info(ProcessInfo p_info) {
 
 PhysicsServer2DSW *PhysicsServer2DSW::singletonsw = nullptr;
 
-PhysicsServer2DSW::PhysicsServer2DSW() {
+PhysicsServer2DSW::PhysicsServer2DSW(bool p_using_threads) {
 	singletonsw = this;
 	BroadPhase2DSW::create_func = BroadPhase2DHashGrid::_create;
 	//BroadPhase2DSW::create_func=BroadPhase2DBasic::_create;
@@ -1334,10 +1363,6 @@ PhysicsServer2DSW::PhysicsServer2DSW() {
 	island_count = 0;
 	active_objects = 0;
 	collision_pairs = 0;
-#ifdef NO_THREADS
-	using_threads = false;
-#else
-	using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
-#endif
+	using_threads = p_using_threads;
 	flushing_queries = false;
 };

+ 14 - 9
servers/physics_2d/physics_server_2d_sw.h

@@ -61,11 +61,11 @@ class PhysicsServer2DSW : public PhysicsServer2D {
 
 	PhysicsDirectBodyState2DSW *direct_state;
 
-	mutable RID_PtrOwner<Shape2DSW> shape_owner;
-	mutable RID_PtrOwner<Space2DSW> space_owner;
-	mutable RID_PtrOwner<Area2DSW> area_owner;
-	mutable RID_PtrOwner<Body2DSW> body_owner;
-	mutable RID_PtrOwner<Joint2DSW> joint_owner;
+	mutable RID_PtrOwner<Shape2DSW, true> shape_owner;
+	mutable RID_PtrOwner<Space2DSW, true> space_owner;
+	mutable RID_PtrOwner<Area2DSW, true> area_owner;
+	mutable RID_PtrOwner<Body2DSW, true> body_owner;
+	mutable RID_PtrOwner<Joint2DSW, true> joint_owner;
 
 	static PhysicsServer2DSW *singletonsw;
 
@@ -255,15 +255,20 @@ public:
 
 	/* JOINT API */
 
+	virtual RID joint_create() override;
+
+	virtual void joint_clear(RID p_joint) override;
+
 	virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value) override;
 	virtual real_t joint_get_param(RID p_joint, JointParam p_param) const override;
 
 	virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disabled) override;
 	virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const override;
 
-	virtual RID pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b = RID()) override;
-	virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) override;
-	virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) override;
+	virtual void joint_make_pin(RID p_joint, const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) override;
+	virtual void joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) override;
+	virtual void joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) override;
+
 	virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) override;
 	virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const override;
 	virtual void damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) override;
@@ -287,7 +292,7 @@ public:
 
 	int get_process_info(ProcessInfo p_info) override;
 
-	PhysicsServer2DSW();
+	PhysicsServer2DSW(bool p_using_threads = false);
 	~PhysicsServer2DSW() {}
 };
 

+ 0 - 13
servers/physics_2d/physics_server_2d_wrap_mt.cpp

@@ -113,19 +113,6 @@ void PhysicsServer2DWrapMT::finish() {
 	} else {
 		physics_2d_server->finish();
 	}
-
-	line_shape_free_cached_ids();
-	ray_shape_free_cached_ids();
-	segment_shape_free_cached_ids();
-	circle_shape_free_cached_ids();
-	rectangle_shape_free_cached_ids();
-	capsule_shape_free_cached_ids();
-	convex_polygon_shape_free_cached_ids();
-	concave_polygon_shape_free_cached_ids();
-
-	space_free_cached_ids();
-	area_free_cached_ids();
-	body_free_cached_ids();
 }
 
 PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) :

+ 26 - 35
servers/physics_2d/physics_server_2d_wrap_mt.h

@@ -73,6 +73,8 @@ public:
 #define ServerName PhysicsServer2D
 #define ServerNameWrapMT PhysicsServer2DWrapMT
 #define server_name physics_2d_server
+#define WRITE_ACTION
+
 #include "servers/server_wrap_mt_common.h"
 
 	//FUNC1RID(shape,ShapeType); todo fix
@@ -93,7 +95,7 @@ public:
 	FUNC1RC(real_t, shape_get_custom_solver_bias, RID);
 
 	//these work well, but should be used from the main thread only
-	bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) {
+	bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override {
 		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
 		return physics_2d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
 	}
@@ -108,18 +110,18 @@ public:
 	FUNC2RC(real_t, space_get_param, RID, SpaceParameter);
 
 	// this function only works on physics process, errors and returns null otherwise
-	PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) {
+	PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override {
 		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
 		return physics_2d_server->space_get_direct_state(p_space);
 	}
 
 	FUNC2(space_set_debug_contacts, RID, int);
-	virtual Vector<Vector2> space_get_contacts(RID p_space) const {
+	virtual Vector<Vector2> space_get_contacts(RID p_space) const override {
 		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector2>());
 		return physics_2d_server->space_get_contacts(p_space);
 	}
 
-	virtual int space_get_contact_count(RID p_space) const {
+	virtual int space_get_contact_count(RID p_space) const override {
 		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
 		return physics_2d_server->space_get_contact_count(p_space);
 	}
@@ -244,30 +246,34 @@ public:
 
 	FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &);
 
-	bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {
+	bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
 		return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
 	}
 
 	FUNC2(body_set_pickable, RID, bool);
 
-	bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) {
+	bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
 		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
 		return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
 	}
 
-	int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) {
+	int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
 		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
 		return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
 	}
 
 	// this function only works on physics process, errors and returns null otherwise
-	PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) {
+	PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override {
 		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
 		return physics_2d_server->body_get_direct_state(p_body);
 	}
 
 	/* JOINT API */
 
+	FUNCRID(joint)
+
+	FUNC1(joint_clear, RID)
+
 	FUNC3(joint_set_param, RID, JointParam, real_t);
 	FUNC2RC(real_t, joint_get_param, RID, JointParam);
 
@@ -280,9 +286,9 @@ public:
 
 	//TODO need to convert this to FUNCRID, but it's a hassle..
 
-	FUNC3R(RID, pin_joint_create, const Vector2 &, RID, RID);
-	FUNC5R(RID, groove_joint_create, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID);
-	FUNC4R(RID, damped_spring_joint_create, const Vector2 &, const Vector2 &, RID, RID);
+	FUNC4(joint_make_pin, RID, const Vector2 &, RID, RID);
+	FUNC6(joint_make_groove, RID, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID);
+	FUNC5(joint_make_damped_spring, RID, const Vector2 &, const Vector2 &, RID, RID);
 
 	FUNC3(pin_joint_set_param, RID, PinJointParam, real_t);
 	FUNC2RC(real_t, pin_joint_get_param, RID, PinJointParam);
@@ -297,43 +303,28 @@ public:
 	FUNC1(free, RID);
 	FUNC1(set_active, bool);
 
-	virtual void init();
-	virtual void step(real_t p_step);
-	virtual void sync();
-	virtual void end_sync();
-	virtual void flush_queries();
-	virtual void finish();
+	virtual void init() override;
+	virtual void step(real_t p_step) override;
+	virtual void sync() override;
+	virtual void end_sync() override;
+	virtual void flush_queries() override;
+	virtual void finish() override;
 
-	virtual bool is_flushing_queries() const {
+	virtual bool is_flushing_queries() const override {
 		return physics_2d_server->is_flushing_queries();
 	}
 
-	int get_process_info(ProcessInfo p_info) {
+	int get_process_info(ProcessInfo p_info) override {
 		return physics_2d_server->get_process_info(p_info);
 	}
 
 	PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread);
 	~PhysicsServer2DWrapMT();
 
-	template <class T>
-	static PhysicsServer2D *init_server() {
-#ifdef NO_THREADS
-		return memnew(T); // Always single unsafe when no threads are available.
-#else
-		int tm = GLOBAL_DEF("physics/2d/thread_model", 1);
-		if (tm == 0) { // single unsafe
-			return memnew(T);
-		} else if (tm == 1) { // single safe
-			return memnew(PhysicsServer2DWrapMT(memnew(T), false));
-		} else { // multi threaded
-			return memnew(PhysicsServer2DWrapMT(memnew(T), true));
-		}
-#endif
-	}
-
 #undef ServerNameWrapMT
 #undef ServerName
 #undef server_name
+#undef WRITE_ACTION
 };
 
 #ifdef DEBUG_SYNC

+ 5 - 5
servers/physics_3d/collision_object_3d_sw.cpp

@@ -43,7 +43,7 @@ void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform &p_trans
 	p_shape->add_owner(this);
 
 	if (!pending_shape_update_list.in_list()) {
-		PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+		PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
 	}
 	//_update_shapes();
 	//_shapes_changed();
@@ -56,7 +56,7 @@ void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) {
 
 	p_shape->add_owner(this);
 	if (!pending_shape_update_list.in_list()) {
-		PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+		PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
 	}
 	//_update_shapes();
 	//_shapes_changed();
@@ -68,7 +68,7 @@ void CollisionObject3DSW::set_shape_transform(int p_index, const Transform &p_tr
 	shapes.write[p_index].xform = p_transform;
 	shapes.write[p_index].xform_inv = p_transform.affine_inverse();
 	if (!pending_shape_update_list.in_list()) {
-		PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+		PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
 	}
 	//_update_shapes();
 	//_shapes_changed();
@@ -77,7 +77,7 @@ void CollisionObject3DSW::set_shape_transform(int p_index, const Transform &p_tr
 void CollisionObject3DSW::set_shape_as_disabled(int p_idx, bool p_enable) {
 	shapes.write[p_idx].disabled = p_enable;
 	if (!pending_shape_update_list.in_list()) {
-		PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+		PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
 	}
 }
 
@@ -106,7 +106,7 @@ void CollisionObject3DSW::remove_shape(int p_index) {
 	shapes.remove(p_index);
 
 	if (!pending_shape_update_list.in_list()) {
-		PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+		PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
 	}
 	//_update_shapes();
 	//_shapes_changed();

+ 1 - 1
servers/physics_3d/joints/cone_twist_joint_3d_sw.h

@@ -102,7 +102,7 @@ public:
 	bool m_solveSwingLimit;
 
 public:
-	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_CONE_TWIST; }
+	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_CONE_TWIST; }
 
 	virtual bool setup(real_t p_timestep);
 	virtual void solve(real_t p_timestep);

+ 1 - 1
servers/physics_3d/joints/generic_6dof_joint_3d_sw.h

@@ -234,7 +234,7 @@ protected:
 public:
 	Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA);
 
-	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_6DOF; }
+	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_6DOF; }
 
 	virtual bool setup(real_t p_timestep);
 	virtual void solve(real_t p_timestep);

+ 1 - 1
servers/physics_3d/joints/hinge_joint_3d_sw.h

@@ -96,7 +96,7 @@ class HingeJoint3DSW : public Joint3DSW {
 	real_t m_appliedImpulse;
 
 public:
-	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_HINGE; }
+	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_HINGE; }
 
 	virtual bool setup(real_t p_step);
 	virtual void solve(real_t p_step);

+ 1 - 1
servers/physics_3d/joints/pin_joint_3d_sw.h

@@ -74,7 +74,7 @@ class PinJoint3DSW : public Joint3DSW {
 	Vector3 m_pivotInB;
 
 public:
-	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_PIN; }
+	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_PIN; }
 
 	virtual bool setup(real_t p_step);
 	virtual void solve(real_t p_step);

+ 1 - 1
servers/physics_3d/joints/slider_joint_3d_sw.h

@@ -243,7 +243,7 @@ public:
 	bool setup(real_t p_step);
 	void solve(real_t p_step);
 
-	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_SLIDER; }
+	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_SLIDER; }
 };
 
 #endif // SLIDER_JOINT_SW_H

+ 10 - 1
servers/physics_3d/joints_3d_sw.h

@@ -36,7 +36,16 @@
 
 class Joint3DSW : public Constraint3DSW {
 public:
-	virtual PhysicsServer3D::JointType get_type() const = 0;
+	virtual bool setup(real_t p_step) { return false; }
+	virtual void solve(real_t p_step) {}
+
+	void copy_settings_from(Joint3DSW *p_joint) {
+		set_self(p_joint->get_self());
+		set_priority(p_joint->get_priority());
+		disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies());
+	}
+
+	virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_MAX; }
 	_FORCE_INLINE_ Joint3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) :
 			Constraint3DSW(p_body_ptr, p_body_count) {
 	}

+ 182 - 135
servers/physics_3d/physics_server_3d_sw.cpp

@@ -43,47 +43,60 @@
 #define FLUSH_QUERY_CHECK(m_object) \
 	ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
 
-RID PhysicsServer3DSW::shape_create(ShapeType p_shape) {
-	Shape3DSW *shape = nullptr;
-	switch (p_shape) {
-		case SHAPE_PLANE: {
-			shape = memnew(PlaneShape3DSW);
-		} break;
-		case SHAPE_RAY: {
-			shape = memnew(RayShape3DSW);
-		} break;
-		case SHAPE_SPHERE: {
-			shape = memnew(SphereShape3DSW);
-		} break;
-		case SHAPE_BOX: {
-			shape = memnew(BoxShape3DSW);
-		} break;
-		case SHAPE_CAPSULE: {
-			shape = memnew(CapsuleShape3DSW);
-		} break;
-		case SHAPE_CYLINDER: {
-			ERR_FAIL_V_MSG(RID(), "CylinderShape3D is not supported in GodotPhysics3D. Please switch to Bullet in the Project Settings.");
-		} break;
-		case SHAPE_CONVEX_POLYGON: {
-			shape = memnew(ConvexPolygonShape3DSW);
-		} break;
-		case SHAPE_CONCAVE_POLYGON: {
-			shape = memnew(ConcavePolygonShape3DSW);
-		} break;
-		case SHAPE_HEIGHTMAP: {
-			shape = memnew(HeightMapShape3DSW);
-		} break;
-		case SHAPE_CUSTOM: {
-			ERR_FAIL_V(RID());
-
-		} break;
-	}
-
-	RID id = shape_owner.make_rid(shape);
-	shape->set_self(id);
-
-	return id;
-};
+RID PhysicsServer3DSW::plane_shape_create() {
+	Shape3DSW *shape = memnew(PlaneShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::ray_shape_create() {
+	Shape3DSW *shape = memnew(RayShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::sphere_shape_create() {
+	Shape3DSW *shape = memnew(SphereShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::box_shape_create() {
+	Shape3DSW *shape = memnew(BoxShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::capsule_shape_create() {
+	Shape3DSW *shape = memnew(CapsuleShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::cylinder_shape_create() {
+	ERR_FAIL_V(RID());
+}
+RID PhysicsServer3DSW::convex_polygon_shape_create() {
+	Shape3DSW *shape = memnew(ConvexPolygonShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::concave_polygon_shape_create() {
+	Shape3DSW *shape = memnew(ConcavePolygonShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::heightmap_shape_create() {
+	Shape3DSW *shape = memnew(HeightMapShape3DSW);
+	RID rid = shape_owner.make_rid(shape);
+	shape->set_self(rid);
+	return rid;
+}
+RID PhysicsServer3DSW::custom_shape_create() {
+	ERR_FAIL_V(RID());
+}
 
 void PhysicsServer3DSW::shape_set_data(RID p_shape, const Variant &p_data) {
 	Shape3DSW *shape = shape_owner.getornull(p_shape);
@@ -174,7 +187,7 @@ real_t PhysicsServer3DSW::space_get_param(RID p_space, SpaceParameter p_param) c
 PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space) {
 	Space3DSW *space = space_owner.getornull(p_space);
 	ERR_FAIL_COND_V(!space, nullptr);
-	ERR_FAIL_COND_V_MSG(space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
+	ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
 
 	return space->get_direct_state();
 }
@@ -413,13 +426,6 @@ void PhysicsServer3DSW::area_set_ray_pickable(RID p_area, bool p_enable) {
 	area->set_ray_pickable(p_enable);
 }
 
-bool PhysicsServer3DSW::area_is_ray_pickable(RID p_area) const {
-	Area3DSW *area = area_owner.getornull(p_area);
-	ERR_FAIL_COND_V(!area, false);
-
-	return area->is_ray_pickable();
-}
-
 void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
 	Area3DSW *area = area_owner.getornull(p_area);
 	ERR_FAIL_COND(!area);
@@ -429,14 +435,8 @@ void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_rec
 
 /* BODY API */
 
-RID PhysicsServer3DSW::body_create(BodyMode p_mode, bool p_init_sleeping) {
+RID PhysicsServer3DSW::body_create() {
 	Body3DSW *body = memnew(Body3DSW);
-	if (p_mode != BODY_MODE_RIGID) {
-		body->set_mode(p_mode);
-	}
-	if (p_init_sleeping) {
-		body->set_state(BODY_STATE_SLEEPING, p_init_sleeping);
-	}
 	RID rid = body_owner.make_rid(body);
 	body->set_self(rid);
 	return rid;
@@ -857,12 +857,6 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
 	body->set_ray_pickable(p_enable);
 }
 
-bool PhysicsServer3DSW::body_is_ray_pickable(RID p_body) const {
-	Body3DSW *body = body_owner.getornull(p_body);
-	ERR_FAIL_COND_V(!body, false);
-	return body->is_ray_pickable();
-}
-
 bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
 	Body3DSW *body = body_owner.getornull(p_body);
 	ERR_FAIL_COND_V(!body, false);
@@ -886,6 +880,8 @@ int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform &p_t
 }
 
 PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
+	ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
+
 	Body3DSW *body = body_owner.getornull(p_body);
 	ERR_FAIL_COND_V(!body, nullptr);
 	ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
@@ -896,30 +892,52 @@ PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
 
 /* JOINT API */
 
-RID PhysicsServer3DSW::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
+RID PhysicsServer3DSW::joint_create() {
+	Joint3DSW *joint = memnew(Joint3DSW);
+	RID rid = joint_owner.make_rid(joint);
+	joint->set_self(rid);
+	return rid;
+}
+
+void PhysicsServer3DSW::joint_clear(RID p_joint) {
+	Joint3DSW *joint = joint_owner.getornull(p_joint);
+	if (joint->get_type() != JOINT_TYPE_MAX) {
+		Joint3DSW *empty_joint = memnew(Joint3DSW);
+		empty_joint->copy_settings_from(joint);
+
+		joint_owner.replace(p_joint, empty_joint);
+		memdelete(joint);
+	}
+}
+
+void PhysicsServer3DSW::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
 	Body3DSW *body_A = body_owner.getornull(p_body_A);
-	ERR_FAIL_COND_V(!body_A, RID());
+	ERR_FAIL_COND(!body_A);
 
 	if (!p_body_B.is_valid()) {
-		ERR_FAIL_COND_V(!body_A->get_space(), RID());
+		ERR_FAIL_COND(!body_A->get_space());
 		p_body_B = body_A->get_space()->get_static_global_body();
 	}
 
 	Body3DSW *body_B = body_owner.getornull(p_body_B);
-	ERR_FAIL_COND_V(!body_B, RID());
+	ERR_FAIL_COND(!body_B);
+
+	ERR_FAIL_COND(body_A == body_B);
 
-	ERR_FAIL_COND_V(body_A == body_B, RID());
+	Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint3DSW *joint = memnew(PinJoint3DSW(body_A, p_local_A, body_B, p_local_B));
-	RID rid = joint_owner.make_rid(joint);
-	joint->set_self(rid);
-	return rid;
+
+	joint->copy_settings_from(prev_joint);
+	joint_owner.replace(p_joint, joint);
+	memdelete(prev_joint);
 }
 
 void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
 	PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
 	pin_joint->set_param(p_param, p_value);
 }
@@ -927,7 +945,7 @@ void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param,
 real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, 0);
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0);
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
 	PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
 	return pin_joint->get_param(p_param);
 }
@@ -935,7 +953,7 @@ real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param
 void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
 	PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
 	pin_joint->set_pos_a(p_A);
 }
@@ -943,7 +961,7 @@ void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
 Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, Vector3());
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
 	PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
 	return pin_joint->get_position_a();
 }
@@ -951,7 +969,7 @@ Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const {
 void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
 	PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
 	pin_joint->set_pos_b(p_B);
 }
@@ -959,55 +977,63 @@ void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
 Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, Vector3());
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
 	PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
 	return pin_joint->get_position_b();
 }
 
-RID PhysicsServer3DSW::joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) {
+void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) {
 	Body3DSW *body_A = body_owner.getornull(p_body_A);
-	ERR_FAIL_COND_V(!body_A, RID());
+	ERR_FAIL_COND(!body_A);
 
 	if (!p_body_B.is_valid()) {
-		ERR_FAIL_COND_V(!body_A->get_space(), RID());
+		ERR_FAIL_COND(!body_A->get_space());
 		p_body_B = body_A->get_space()->get_static_global_body();
 	}
 
 	Body3DSW *body_B = body_owner.getornull(p_body_B);
-	ERR_FAIL_COND_V(!body_B, RID());
+	ERR_FAIL_COND(!body_B);
 
-	ERR_FAIL_COND_V(body_A == body_B, RID());
+	ERR_FAIL_COND(body_A == body_B);
+
+	Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_frame_A, p_frame_B));
-	RID rid = joint_owner.make_rid(joint);
-	joint->set_self(rid);
-	return rid;
+
+	joint->copy_settings_from(prev_joint);
+	joint_owner.replace(p_joint, joint);
+	memdelete(prev_joint);
 }
 
-RID PhysicsServer3DSW::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
+void PhysicsServer3DSW::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
 	Body3DSW *body_A = body_owner.getornull(p_body_A);
-	ERR_FAIL_COND_V(!body_A, RID());
+	ERR_FAIL_COND(!body_A);
 
 	if (!p_body_B.is_valid()) {
-		ERR_FAIL_COND_V(!body_A->get_space(), RID());
+		ERR_FAIL_COND(!body_A->get_space());
 		p_body_B = body_A->get_space()->get_static_global_body();
 	}
 
 	Body3DSW *body_B = body_owner.getornull(p_body_B);
-	ERR_FAIL_COND_V(!body_B, RID());
+	ERR_FAIL_COND(!body_B);
+
+	ERR_FAIL_COND(body_A == body_B);
 
-	ERR_FAIL_COND_V(body_A == body_B, RID());
+	Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B));
-	RID rid = joint_owner.make_rid(joint);
-	joint->set_self(rid);
-	return rid;
+
+	joint->copy_settings_from(prev_joint);
+	joint_owner.replace(p_joint, joint);
+	memdelete(prev_joint);
 }
 
 void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_HINGE);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
 	HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
 	hinge_joint->set_param(p_param, p_value);
 }
@@ -1015,7 +1041,7 @@ void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_par
 real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, 0);
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0);
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0);
 	HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
 	return hinge_joint->get_param(p_param);
 }
@@ -1023,7 +1049,7 @@ real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_p
 void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_HINGE);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
 	HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
 	hinge_joint->set_flag(p_flag, p_value);
 }
@@ -1031,7 +1057,7 @@ void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag,
 bool PhysicsServer3DSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, false);
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, false);
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false);
 	HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
 	return hinge_joint->get_flag(p_flag);
 }
@@ -1077,34 +1103,38 @@ bool PhysicsServer3DSW::joint_is_disabled_collisions_between_bodies(RID p_joint)
 
 PhysicsServer3DSW::JointType PhysicsServer3DSW::joint_get_type(RID p_joint) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
-	ERR_FAIL_COND_V(!joint, JOINT_PIN);
+	ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
 	return joint->get_type();
 }
 
-RID PhysicsServer3DSW::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
 	Body3DSW *body_A = body_owner.getornull(p_body_A);
-	ERR_FAIL_COND_V(!body_A, RID());
+	ERR_FAIL_COND(!body_A);
 
 	if (!p_body_B.is_valid()) {
-		ERR_FAIL_COND_V(!body_A->get_space(), RID());
+		ERR_FAIL_COND(!body_A->get_space());
 		p_body_B = body_A->get_space()->get_static_global_body();
 	}
 
 	Body3DSW *body_B = body_owner.getornull(p_body_B);
-	ERR_FAIL_COND_V(!body_B, RID());
+	ERR_FAIL_COND(!body_B);
+
+	ERR_FAIL_COND(body_A == body_B);
 
-	ERR_FAIL_COND_V(body_A == body_B, RID());
+	Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint3DSW *joint = memnew(SliderJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
-	RID rid = joint_owner.make_rid(joint);
-	joint->set_self(rid);
-	return rid;
+
+	joint->copy_settings_from(prev_joint);
+	joint_owner.replace(p_joint, joint);
+	memdelete(prev_joint);
 }
 
 void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER);
 	SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
 	slider_joint->set_param(p_param, p_value);
 }
@@ -1112,35 +1142,39 @@ void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_p
 real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, 0);
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0);
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
 	SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
 	return slider_joint->get_param(p_param);
 }
 
-RID PhysicsServer3DSW::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
 	Body3DSW *body_A = body_owner.getornull(p_body_A);
-	ERR_FAIL_COND_V(!body_A, RID());
+	ERR_FAIL_COND(!body_A);
 
 	if (!p_body_B.is_valid()) {
-		ERR_FAIL_COND_V(!body_A->get_space(), RID());
+		ERR_FAIL_COND(!body_A->get_space());
 		p_body_B = body_A->get_space()->get_static_global_body();
 	}
 
 	Body3DSW *body_B = body_owner.getornull(p_body_B);
-	ERR_FAIL_COND_V(!body_B, RID());
+	ERR_FAIL_COND(!body_B);
+
+	ERR_FAIL_COND(body_A == body_B);
 
-	ERR_FAIL_COND_V(body_A == body_B, RID());
+	Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint3DSW *joint = memnew(ConeTwistJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
-	RID rid = joint_owner.make_rid(joint);
-	joint->set_self(rid);
-	return rid;
+
+	joint->copy_settings_from(prev_joint);
+	joint_owner.replace(p_joint, joint);
+	memdelete(prev_joint);
 }
 
 void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST);
 	ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
 	cone_twist_joint->set_param(p_param, p_value);
 }
@@ -1148,43 +1182,47 @@ void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointPa
 real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, 0);
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0);
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
 	ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
 	return cone_twist_joint->get_param(p_param);
 }
 
-RID PhysicsServer3DSW::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
 	Body3DSW *body_A = body_owner.getornull(p_body_A);
-	ERR_FAIL_COND_V(!body_A, RID());
+	ERR_FAIL_COND(!body_A);
 
 	if (!p_body_B.is_valid()) {
-		ERR_FAIL_COND_V(!body_A->get_space(), RID());
+		ERR_FAIL_COND(!body_A->get_space());
 		p_body_B = body_A->get_space()->get_static_global_body();
 	}
 
 	Body3DSW *body_B = body_owner.getornull(p_body_B);
-	ERR_FAIL_COND_V(!body_B, RID());
+	ERR_FAIL_COND(!body_B);
+
+	ERR_FAIL_COND(body_A == body_B);
 
-	ERR_FAIL_COND_V(body_A == body_B, RID());
+	Joint3DSW *prev_joint = joint_owner.getornull(p_joint);
+	ERR_FAIL_COND(prev_joint == nullptr);
 
 	Joint3DSW *joint = memnew(Generic6DOFJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B, true));
-	RID rid = joint_owner.make_rid(joint);
-	joint->set_self(rid);
-	return rid;
+
+	joint->copy_settings_from(prev_joint);
+	joint_owner.replace(p_joint, joint);
+	memdelete(prev_joint);
 }
 
 void PhysicsServer3DSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
 	Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
 	generic_6dof_joint->set_param(p_axis, p_param, p_value);
 }
 
-real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) {
+real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, 0);
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0);
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0);
 	Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
 	return generic_6dof_joint->get_param(p_axis, p_param);
 }
@@ -1192,15 +1230,15 @@ real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axi
 void PhysicsServer3DSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND(!joint);
-	ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
+	ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
 	Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
 	generic_6dof_joint->set_flag(p_axis, p_flag, p_enable);
 }
 
-bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) {
+bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const {
 	Joint3DSW *joint = joint_owner.getornull(p_joint);
 	ERR_FAIL_COND_V(!joint, false);
-	ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, false);
+	ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false);
 	Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
 	return generic_6dof_joint->get_flag(p_axis, p_flag);
 }
@@ -1317,6 +1355,10 @@ void PhysicsServer3DSW::step(real_t p_step) {
 #endif
 }
 
+void PhysicsServer3DSW::sync() {
+	doing_sync = true;
+};
+
 void PhysicsServer3DSW::flush_queries() {
 #ifndef _3D_DISABLED
 
@@ -1370,6 +1412,10 @@ void PhysicsServer3DSW::flush_queries() {
 #endif
 };
 
+void PhysicsServer3DSW::end_sync() {
+	doing_sync = false;
+};
+
 void PhysicsServer3DSW::finish() {
 	memdelete(stepper);
 	memdelete(direct_state);
@@ -1431,14 +1477,15 @@ void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &
 	}
 }
 
-PhysicsServer3DSW *PhysicsServer3DSW::singleton = nullptr;
-PhysicsServer3DSW::PhysicsServer3DSW() {
-	singleton = this;
+PhysicsServer3DSW *PhysicsServer3DSW::singletonsw = nullptr;
+PhysicsServer3DSW::PhysicsServer3DSW(bool p_using_threads) {
+	singletonsw = this;
 	BroadPhase3DSW::create_func = BroadPhaseOctree::_create;
 	island_count = 0;
 	active_objects = 0;
 	collision_pairs = 0;
-
+	using_threads = p_using_threads;
 	active = true;
 	flushing_queries = false;
+	doing_sync = false;
 };

+ 49 - 34
servers/physics_3d/physics_server_3d_sw.h

@@ -50,6 +50,8 @@ class PhysicsServer3DSW : public PhysicsServer3D {
 	int active_objects;
 	int collision_pairs;
 
+	bool using_threads;
+	bool doing_sync;
 	bool flushing_queries;
 
 	Step3DSW *stepper;
@@ -57,20 +59,20 @@ class PhysicsServer3DSW : public PhysicsServer3D {
 
 	PhysicsDirectBodyState3DSW *direct_state;
 
-	mutable RID_PtrOwner<Shape3DSW> shape_owner;
-	mutable RID_PtrOwner<Space3DSW> space_owner;
-	mutable RID_PtrOwner<Area3DSW> area_owner;
-	mutable RID_PtrOwner<Body3DSW> body_owner;
-	mutable RID_PtrOwner<Joint3DSW> joint_owner;
+	mutable RID_PtrOwner<Shape3DSW, true> shape_owner;
+	mutable RID_PtrOwner<Space3DSW, true> space_owner;
+	mutable RID_PtrOwner<Area3DSW, true> area_owner;
+	mutable RID_PtrOwner<Body3DSW, true> body_owner;
+	mutable RID_PtrOwner<Joint3DSW, true> joint_owner;
 
 	//void _clear_query(QuerySW *p_query);
 	friend class CollisionObject3DSW;
 	SelfList<CollisionObject3DSW>::List pending_shape_update_list;
 	void _update_shapes();
 
-public:
-	static PhysicsServer3DSW *singleton;
+	static PhysicsServer3DSW *singletonsw;
 
+public:
 	struct CollCbkData {
 		int max;
 		int amount;
@@ -79,7 +81,17 @@ public:
 
 	static void _shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata);
 
-	virtual RID shape_create(ShapeType p_shape) override;
+	virtual RID plane_shape_create() override;
+	virtual RID ray_shape_create() override;
+	virtual RID sphere_shape_create() override;
+	virtual RID box_shape_create() override;
+	virtual RID capsule_shape_create() override;
+	virtual RID cylinder_shape_create() override;
+	virtual RID convex_polygon_shape_create() override;
+	virtual RID concave_polygon_shape_create() override;
+	virtual RID heightmap_shape_create() override;
+	virtual RID custom_shape_create() override;
+
 	virtual void shape_set_data(RID p_shape, const Variant &p_data) override;
 	virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) override;
 
@@ -140,7 +152,6 @@ public:
 	virtual Transform area_get_transform(RID p_area) const override;
 
 	virtual void area_set_ray_pickable(RID p_area, bool p_enable) override;
-	virtual bool area_is_ray_pickable(RID p_area) const override;
 
 	virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
 	virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
@@ -153,7 +164,7 @@ public:
 	/* BODY API */
 
 	// create a body of a given type
-	virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) override;
+	virtual RID body_create() override;
 
 	virtual void body_set_space(RID p_body, RID p_space) override;
 	virtual RID body_get_space(RID p_body) const override;
@@ -232,7 +243,6 @@ public:
 	virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override;
 
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
-	virtual bool body_is_ray_pickable(RID p_body) const override;
 
 	virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
 	virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
@@ -242,7 +252,7 @@ public:
 
 	/* SOFT BODY */
 
-	virtual RID soft_body_create(bool p_init_sleeping = false) override { return RID(); }
+	virtual RID soft_body_create() override { return RID(); }
 
 	virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) override {}
 
@@ -266,49 +276,52 @@ public:
 	virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const override { return Vector3(); }
 
 	virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override {}
-	virtual bool soft_body_is_ray_pickable(RID p_body) const override { return false; }
 
 	virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override {}
-	virtual int soft_body_get_simulation_precision(RID p_body) override { return 0; }
+	virtual int soft_body_get_simulation_precision(RID p_body) const override { return 0; }
 
 	virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override {}
-	virtual real_t soft_body_get_total_mass(RID p_body) override { return 0.; }
+	virtual real_t soft_body_get_total_mass(RID p_body) const override { return 0.; }
 
 	virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override {}
-	virtual real_t soft_body_get_linear_stiffness(RID p_body) override { return 0.; }
+	virtual real_t soft_body_get_linear_stiffness(RID p_body) const override { return 0.; }
 
-	virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) override {}
-	virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) override { return 0.; }
+	virtual void soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) override {}
+	virtual real_t soft_body_get_angular_stiffness(RID p_body) const override { return 0.; }
 
 	virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) override {}
-	virtual real_t soft_body_get_volume_stiffness(RID p_body) override { return 0.; }
+	virtual real_t soft_body_get_volume_stiffness(RID p_body) const override { return 0.; }
 
 	virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override {}
-	virtual real_t soft_body_get_pressure_coefficient(RID p_body) override { return 0.; }
+	virtual real_t soft_body_get_pressure_coefficient(RID p_body) const override { return 0.; }
 
 	virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) override {}
-	virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) override { return 0.; }
+	virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) const override { return 0.; }
 
 	virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override {}
-	virtual real_t soft_body_get_damping_coefficient(RID p_body) override { return 0.; }
+	virtual real_t soft_body_get_damping_coefficient(RID p_body) const override { return 0.; }
 
 	virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override {}
-	virtual real_t soft_body_get_drag_coefficient(RID p_body) override { return 0.; }
+	virtual real_t soft_body_get_drag_coefficient(RID p_body) const override { return 0.; }
 
 	virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) override {}
 
 	virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override {}
-	virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) override { return Vector3(); }
+	virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const override { return Vector3(); }
 
 	virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const override { return Vector3(); }
 
 	virtual void soft_body_remove_all_pinned_points(RID p_body) override {}
 	virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override {}
-	virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) override { return false; }
+	virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const override { return false; }
 
 	/* JOINT API */
 
-	virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) override;
+	virtual RID joint_create() override;
+
+	virtual void joint_clear(RID p_joint) override; //resets type
+
+	virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) override;
 
 	virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) override;
 	virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const override;
@@ -319,8 +332,8 @@ public:
 	virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) override;
 	virtual Vector3 pin_joint_get_local_b(RID p_joint) const override;
 
-	virtual RID joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) override;
-	virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override;
+	virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) override;
+	virtual void joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override;
 
 	virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) override;
 	virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const override;
@@ -328,23 +341,23 @@ public:
 	virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) override;
 	virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const override;
 
-	virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+	virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
 
 	virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) override;
 	virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const override;
 
-	virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+	virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
 
 	virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) override;
 	virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const override;
 
-	virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
+	virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override; //reference frame is A
 
 	virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) override;
-	virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) override;
+	virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) const override;
 
 	virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) override;
-	virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) override;
+	virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) const override;
 
 	virtual JointType joint_get_type(RID p_joint) const override;
 
@@ -361,14 +374,16 @@ public:
 	virtual void set_active(bool p_active) override;
 	virtual void init() override;
 	virtual void step(real_t p_step) override;
+	virtual void sync() override;
 	virtual void flush_queries() override;
+	virtual void end_sync() override;
 	virtual void finish() override;
 
 	virtual bool is_flushing_queries() const override { return flushing_queries; }
 
 	int get_process_info(ProcessInfo p_info) override;
 
-	PhysicsServer3DSW();
+	PhysicsServer3DSW(bool p_using_threads = false);
 	~PhysicsServer3DSW() {}
 };
 

+ 140 - 0
servers/physics_3d/physics_server_3d_wrap_mt.cpp

@@ -0,0 +1,140 @@
+/*************************************************************************/
+/*  physics_server_3d_wrap_mt.cpp                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "physics_server_3d_wrap_mt.h"
+
+#include "core/os/os.h"
+
+void PhysicsServer3DWrapMT::thread_exit() {
+	exit = true;
+}
+
+void PhysicsServer3DWrapMT::thread_step(real_t p_delta) {
+	physics_3d_server->step(p_delta);
+	step_sem.post();
+}
+
+void PhysicsServer3DWrapMT::_thread_callback(void *_instance) {
+	PhysicsServer3DWrapMT *vsmt = reinterpret_cast<PhysicsServer3DWrapMT *>(_instance);
+
+	vsmt->thread_loop();
+}
+
+void PhysicsServer3DWrapMT::thread_loop() {
+	server_thread = Thread::get_caller_id();
+
+	physics_3d_server->init();
+
+	exit = false;
+	step_thread_up = true;
+	while (!exit) {
+		// flush commands one by one, until exit is requested
+		command_queue.wait_and_flush_one();
+	}
+
+	command_queue.flush_all(); // flush all
+
+	physics_3d_server->finish();
+}
+
+/* EVENT QUEUING */
+
+void PhysicsServer3DWrapMT::step(real_t p_step) {
+	if (create_thread) {
+		command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step);
+	} else {
+		command_queue.flush_all(); //flush all pending from other threads
+		physics_3d_server->step(p_step);
+	}
+}
+
+void PhysicsServer3DWrapMT::sync() {
+	if (create_thread) {
+		if (first_frame) {
+			first_frame = false;
+		} else {
+			step_sem.wait(); //must not wait if a step was not issued
+		}
+	}
+	physics_3d_server->sync();
+}
+
+void PhysicsServer3DWrapMT::flush_queries() {
+	physics_3d_server->flush_queries();
+}
+
+void PhysicsServer3DWrapMT::end_sync() {
+	physics_3d_server->end_sync();
+}
+
+void PhysicsServer3DWrapMT::init() {
+	if (create_thread) {
+		//OS::get_singleton()->release_rendering_thread();
+		thread.start(_thread_callback, this);
+		while (!step_thread_up) {
+			OS::get_singleton()->delay_usec(1000);
+		}
+	} else {
+		physics_3d_server->init();
+	}
+}
+
+void PhysicsServer3DWrapMT::finish() {
+	if (thread.is_started()) {
+		command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit);
+		thread.wait_to_finish();
+	} else {
+		physics_3d_server->finish();
+	}
+}
+
+PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) :
+		command_queue(p_create_thread) {
+	physics_3d_server = p_contained;
+	create_thread = p_create_thread;
+	step_pending = 0;
+	step_thread_up = false;
+
+	pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
+
+	if (!p_create_thread) {
+		server_thread = Thread::get_caller_id();
+	} else {
+		server_thread = 0;
+	}
+
+	main_thread = Thread::get_caller_id();
+	first_frame = true;
+}
+
+PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
+	memdelete(physics_3d_server);
+	//finish();
+}

+ 422 - 0
servers/physics_3d/physics_server_3d_wrap_mt.h

@@ -0,0 +1,422 @@
+/*************************************************************************/
+/*  physics_server_3d_wrap_mt.h                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef PHYSICS3DSERVERWRAPMT_H
+#define PHYSICS3DSERVERWRAPMT_H
+
+#include "core/config/project_settings.h"
+#include "core/os/thread.h"
+#include "core/templates/command_queue_mt.h"
+#include "servers/physics_server_3d.h"
+
+#ifdef DEBUG_SYNC
+#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
+#else
+#define SYNC_DEBUG
+#endif
+
+class PhysicsServer3DWrapMT : public PhysicsServer3D {
+	mutable PhysicsServer3D *physics_3d_server;
+
+	mutable CommandQueueMT command_queue;
+
+	static void _thread_callback(void *_instance);
+	void thread_loop();
+
+	Thread::ID server_thread;
+	Thread::ID main_thread;
+	volatile bool exit = false;
+	Thread thread;
+	volatile bool step_thread_up = false;
+	bool create_thread = false;
+
+	Semaphore step_sem;
+	int step_pending;
+	void thread_step(real_t p_delta);
+	void thread_flush();
+
+	void thread_exit();
+
+	bool first_frame = true;
+
+	Mutex alloc_mutex;
+	int pool_max_size = 0;
+
+public:
+#define ServerName PhysicsServer3D
+#define ServerNameWrapMT PhysicsServer3DWrapMT
+#define server_name physics_3d_server
+#define WRITE_ACTION
+
+#include "servers/server_wrap_mt_common.h"
+
+	//FUNC1RID(shape,ShapeType); todo fix
+	FUNCRID(plane_shape)
+	FUNCRID(ray_shape)
+	FUNCRID(sphere_shape)
+	FUNCRID(box_shape)
+	FUNCRID(capsule_shape)
+	FUNCRID(cylinder_shape)
+	FUNCRID(convex_polygon_shape)
+	FUNCRID(concave_polygon_shape)
+	FUNCRID(heightmap_shape)
+	FUNCRID(custom_shape)
+
+	FUNC2(shape_set_data, RID, const Variant &);
+	FUNC2(shape_set_custom_solver_bias, RID, real_t);
+
+	FUNC2(shape_set_margin, RID, real_t)
+	FUNC1RC(real_t, shape_get_margin, RID)
+
+	FUNC1RC(ShapeType, shape_get_type, RID);
+	FUNC1RC(Variant, shape_get_data, RID);
+	FUNC1RC(real_t, shape_get_custom_solver_bias, RID);
+#if 0
+	//these work well, but should be used from the main thread only
+	bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) {
+		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
+		return physics_3d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
+	}
+#endif
+	/* SPACE API */
+
+	FUNCRID(space);
+	FUNC2(space_set_active, RID, bool);
+	FUNC1RC(bool, space_is_active, RID);
+
+	FUNC3(space_set_param, RID, SpaceParameter, real_t);
+	FUNC2RC(real_t, space_get_param, RID, SpaceParameter);
+
+	// this function only works on physics process, errors and returns null otherwise
+	PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override {
+		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
+		return physics_3d_server->space_get_direct_state(p_space);
+	}
+
+	FUNC2(space_set_debug_contacts, RID, int);
+	virtual Vector<Vector3> space_get_contacts(RID p_space) const override {
+		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector3>());
+		return physics_3d_server->space_get_contacts(p_space);
+	}
+
+	virtual int space_get_contact_count(RID p_space) const override {
+		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
+		return physics_3d_server->space_get_contact_count(p_space);
+	}
+
+	/* AREA API */
+
+	//FUNC0RID(area);
+	FUNCRID(area);
+
+	FUNC2(area_set_space, RID, RID);
+	FUNC1RC(RID, area_get_space, RID);
+
+	FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
+	FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
+
+	FUNC4(area_add_shape, RID, RID, const Transform &, bool);
+	FUNC3(area_set_shape, RID, int, RID);
+	FUNC3(area_set_shape_transform, RID, int, const Transform &);
+	FUNC3(area_set_shape_disabled, RID, int, bool);
+
+	FUNC1RC(int, area_get_shape_count, RID);
+	FUNC2RC(RID, area_get_shape, RID, int);
+	FUNC2RC(Transform, area_get_shape_transform, RID, int);
+	FUNC2(area_remove_shape, RID, int);
+	FUNC1(area_clear_shapes, RID);
+
+	FUNC2(area_attach_object_instance_id, RID, ObjectID);
+	FUNC1RC(ObjectID, area_get_object_instance_id, RID);
+
+	FUNC3(area_set_param, RID, AreaParameter, const Variant &);
+	FUNC2(area_set_transform, RID, const Transform &);
+
+	FUNC2RC(Variant, area_get_param, RID, AreaParameter);
+	FUNC1RC(Transform, area_get_transform, RID);
+
+	FUNC2(area_set_collision_mask, RID, uint32_t);
+	FUNC2(area_set_collision_layer, RID, uint32_t);
+
+	FUNC2(area_set_monitorable, RID, bool);
+	FUNC2(area_set_ray_pickable, RID, bool);
+
+	FUNC3(area_set_monitor_callback, RID, Object *, const StringName &);
+	FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &);
+
+	/* BODY API */
+
+	//FUNC2RID(body,BodyMode,bool);
+	FUNCRID(body)
+
+	FUNC2(body_set_space, RID, RID);
+	FUNC1RC(RID, body_get_space, RID);
+
+	FUNC2(body_set_mode, RID, BodyMode);
+	FUNC1RC(BodyMode, body_get_mode, RID);
+
+	FUNC4(body_add_shape, RID, RID, const Transform &, bool);
+	FUNC3(body_set_shape, RID, int, RID);
+	FUNC3(body_set_shape_transform, RID, int, const Transform &);
+
+	FUNC1RC(int, body_get_shape_count, RID);
+	FUNC2RC(Transform, body_get_shape_transform, RID, int);
+	FUNC2RC(RID, body_get_shape, RID, int);
+
+	FUNC3(body_set_shape_disabled, RID, int, bool);
+
+	FUNC2(body_remove_shape, RID, int);
+	FUNC1(body_clear_shapes, RID);
+
+	FUNC2(body_attach_object_instance_id, RID, ObjectID);
+	FUNC1RC(ObjectID, body_get_object_instance_id, RID);
+
+	FUNC2(body_set_enable_continuous_collision_detection, RID, bool);
+	FUNC1RC(bool, body_is_continuous_collision_detection_enabled, RID);
+
+	FUNC2(body_set_collision_layer, RID, uint32_t);
+	FUNC1RC(uint32_t, body_get_collision_layer, RID);
+
+	FUNC2(body_set_collision_mask, RID, uint32_t);
+	FUNC1RC(uint32_t, body_get_collision_mask, RID);
+
+	FUNC2(body_set_user_flags, RID, uint32_t);
+	FUNC1RC(uint32_t, body_get_user_flags, RID);
+
+	FUNC3(body_set_param, RID, BodyParameter, real_t);
+	FUNC2RC(real_t, body_get_param, RID, BodyParameter);
+
+	FUNC2(body_set_kinematic_safe_margin, RID, real_t);
+	FUNC1RC(real_t, body_get_kinematic_safe_margin, RID);
+
+	FUNC3(body_set_state, RID, BodyState, const Variant &);
+	FUNC2RC(Variant, body_get_state, RID, BodyState);
+
+	FUNC2(body_set_applied_force, RID, const Vector3 &);
+	FUNC1RC(Vector3, body_get_applied_force, RID);
+
+	FUNC2(body_set_applied_torque, RID, const Vector3 &);
+	FUNC1RC(Vector3, body_get_applied_torque, RID);
+
+	FUNC2(body_add_central_force, RID, const Vector3 &);
+	FUNC3(body_add_force, RID, const Vector3 &, const Vector3 &);
+	FUNC2(body_add_torque, RID, const Vector3 &);
+	FUNC2(body_apply_torque_impulse, RID, const Vector3 &);
+	FUNC2(body_apply_central_impulse, RID, const Vector3 &);
+	FUNC3(body_apply_impulse, RID, const Vector3 &, const Vector3 &);
+	FUNC2(body_set_axis_velocity, RID, const Vector3 &);
+
+	FUNC3(body_set_axis_lock, RID, BodyAxis, bool);
+	FUNC2RC(bool, body_is_axis_locked, RID, BodyAxis);
+
+	FUNC2(body_add_collision_exception, RID, RID);
+	FUNC2(body_remove_collision_exception, RID, RID);
+	FUNC2S(body_get_collision_exceptions, RID, List<RID> *);
+
+	FUNC2(body_set_max_contacts_reported, RID, int);
+	FUNC1RC(int, body_get_max_contacts_reported, RID);
+
+	FUNC2(body_set_contacts_reported_depth_threshold, RID, real_t);
+	FUNC1RC(real_t, body_get_contacts_reported_depth_threshold, RID);
+
+	FUNC2(body_set_omit_force_integration, RID, bool);
+	FUNC1RC(bool, body_is_omitting_force_integration, RID);
+
+	FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &);
+
+	FUNC2(body_set_ray_pickable, RID, bool);
+
+	bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
+		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
+		return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
+	}
+
+	int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
+		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
+		return physics_3d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
+	}
+
+	// this function only works on physics process, errors and returns null otherwise
+	PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override {
+		ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
+		return physics_3d_server->body_get_direct_state(p_body);
+	}
+
+	/* SOFT BODY API */
+
+	FUNCRID(soft_body)
+
+	FUNC2(soft_body_update_rendering_server, RID, class SoftBodyRenderingServerHandler *)
+
+	FUNC2(soft_body_set_space, RID, RID)
+	FUNC1RC(RID, soft_body_get_space, RID)
+
+	FUNC2(soft_body_set_ray_pickable, RID, bool);
+
+	FUNC2(soft_body_set_collision_layer, RID, uint32_t)
+	FUNC1RC(uint32_t, soft_body_get_collision_layer, RID)
+
+	FUNC2(soft_body_set_collision_mask, RID, uint32_t)
+	FUNC1RC(uint32_t, soft_body_get_collision_mask, RID)
+
+	FUNC2(soft_body_add_collision_exception, RID, RID)
+	FUNC2(soft_body_remove_collision_exception, RID, RID)
+	FUNC2S(soft_body_get_collision_exceptions, RID, List<RID> *)
+
+	FUNC3(soft_body_set_state, RID, BodyState, const Variant &);
+	FUNC2RC(Variant, soft_body_get_state, RID, BodyState);
+
+	FUNC2(soft_body_set_transform, RID, const Transform &);
+	FUNC2RC(Vector3, soft_body_get_vertex_position, RID, int);
+
+	FUNC2(soft_body_set_simulation_precision, RID, int);
+	FUNC1RC(int, soft_body_get_simulation_precision, RID);
+
+	FUNC2(soft_body_set_total_mass, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_total_mass, RID);
+
+	FUNC2(soft_body_set_linear_stiffness, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_linear_stiffness, RID);
+
+	FUNC2(soft_body_set_angular_stiffness, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_angular_stiffness, RID);
+
+	FUNC2(soft_body_set_volume_stiffness, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_volume_stiffness, RID);
+
+	FUNC2(soft_body_set_pressure_coefficient, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_pressure_coefficient, RID);
+
+	FUNC2(soft_body_set_pose_matching_coefficient, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_pose_matching_coefficient, RID);
+
+	FUNC2(soft_body_set_damping_coefficient, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_damping_coefficient, RID);
+
+	FUNC2(soft_body_set_drag_coefficient, RID, real_t);
+	FUNC1RC(real_t, soft_body_get_drag_coefficient, RID);
+
+	FUNC2(soft_body_set_mesh, RID, const REF &);
+
+	FUNC3(soft_body_move_point, RID, int, const Vector3 &);
+	FUNC2RC(Vector3, soft_body_get_point_global_position, RID, int);
+	FUNC2RC(Vector3, soft_body_get_point_offset, RID, int);
+
+	FUNC1(soft_body_remove_all_pinned_points, RID);
+	FUNC3(soft_body_pin_point, RID, int, bool);
+	FUNC2RC(bool, soft_body_is_point_pinned, RID, int);
+
+	/* JOINT API */
+
+	FUNCRID(joint)
+
+	FUNC1(joint_clear, RID)
+
+	FUNC5(joint_make_pin, RID, RID, const Vector3 &, RID, const Vector3 &)
+
+	FUNC3(pin_joint_set_param, RID, PinJointParam, real_t)
+	FUNC2RC(real_t, pin_joint_get_param, RID, PinJointParam)
+
+	FUNC2(pin_joint_set_local_a, RID, const Vector3 &)
+	FUNC1RC(Vector3, pin_joint_get_local_a, RID)
+
+	FUNC2(pin_joint_set_local_b, RID, const Vector3 &)
+	FUNC1RC(Vector3, pin_joint_get_local_b, RID)
+
+	FUNC5(joint_make_hinge, RID, RID, const Transform &, RID, const Transform &)
+	FUNC7(joint_make_hinge_simple, RID, RID, const Vector3 &, const Vector3 &, RID, const Vector3 &, const Vector3 &)
+
+	FUNC3(hinge_joint_set_param, RID, HingeJointParam, real_t)
+	FUNC2RC(real_t, hinge_joint_get_param, RID, HingeJointParam)
+
+	FUNC3(hinge_joint_set_flag, RID, HingeJointFlag, bool)
+	FUNC2RC(bool, hinge_joint_get_flag, RID, HingeJointFlag)
+
+	FUNC5(joint_make_slider, RID, RID, const Transform &, RID, const Transform &)
+
+	FUNC3(slider_joint_set_param, RID, SliderJointParam, real_t)
+	FUNC2RC(real_t, slider_joint_get_param, RID, SliderJointParam)
+
+	FUNC5(joint_make_cone_twist, RID, RID, const Transform &, RID, const Transform &)
+
+	FUNC3(cone_twist_joint_set_param, RID, ConeTwistJointParam, real_t)
+	FUNC2RC(real_t, cone_twist_joint_get_param, RID, ConeTwistJointParam)
+
+	FUNC5(joint_make_generic_6dof, RID, RID, const Transform &, RID, const Transform &)
+
+	FUNC4(generic_6dof_joint_set_param, RID, Vector3::Axis, G6DOFJointAxisParam, real_t)
+	FUNC3RC(real_t, generic_6dof_joint_get_param, RID, Vector3::Axis, G6DOFJointAxisParam)
+
+	FUNC4(generic_6dof_joint_set_flag, RID, Vector3::Axis, G6DOFJointAxisFlag, bool)
+	FUNC3RC(bool, generic_6dof_joint_get_flag, RID, Vector3::Axis, G6DOFJointAxisFlag)
+
+	FUNC1RC(JointType, joint_get_type, RID);
+
+	FUNC2(joint_set_solver_priority, RID, int);
+	FUNC1RC(int, joint_get_solver_priority, RID);
+
+	FUNC2(joint_disable_collisions_between_bodies, RID, const bool);
+	FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID);
+
+	/* MISC */
+
+	FUNC1(free, RID);
+	FUNC1(set_active, bool);
+
+	virtual void init() override;
+	virtual void step(real_t p_step) override;
+	virtual void sync() override;
+	virtual void end_sync() override;
+	virtual void flush_queries() override;
+	virtual void finish() override;
+
+	virtual bool is_flushing_queries() const override {
+		return physics_3d_server->is_flushing_queries();
+	}
+
+	int get_process_info(ProcessInfo p_info) override {
+		return physics_3d_server->get_process_info(p_info);
+	}
+
+	PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread);
+	~PhysicsServer3DWrapMT();
+
+#undef ServerNameWrapMT
+#undef ServerName
+#undef server_name
+#undef WRITE_ACTION
+};
+
+#ifdef DEBUG_SYNC
+#undef DEBUG_SYNC
+#endif
+#undef SYNC_DEBUG
+
+#endif // PHYSICS3DSERVERWRAPMT_H

+ 6 - 6
servers/physics_3d/space_3d_sw.cpp

@@ -181,7 +181,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
 		return 0;
 	}
 
-	Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+	Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
 	ERR_FAIL_COND_V(!shape, 0);
 
 	AABB aabb = p_xform.xform(shape->get_aabb());
@@ -232,7 +232,7 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
 }
 
 bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
-	Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+	Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
 	ERR_FAIL_COND_V(!shape, false);
 
 	AABB aabb = p_xform.xform(shape->get_aabb());
@@ -340,7 +340,7 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform &p_
 		return false;
 	}
 
-	Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+	Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
 	ERR_FAIL_COND_V(!shape, 0);
 
 	AABB aabb = p_shape_xform.xform(shape->get_aabb());
@@ -412,7 +412,7 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B,
 }
 
 bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
-	Shape3DSW *shape = static_cast<PhysicsServer3DSW *>(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape);
+	Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.getornull(p_shape);
 	ERR_FAIL_COND_V(!shape, 0);
 
 	AABB aabb = p_shape_xform.xform(shape->get_aabb());
@@ -468,9 +468,9 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shap
 }
 
 Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const {
-	CollisionObject3DSW *obj = PhysicsServer3DSW::singleton->area_owner.getornull(p_object);
+	CollisionObject3DSW *obj = PhysicsServer3DSW::singletonsw->area_owner.getornull(p_object);
 	if (!obj) {
-		obj = PhysicsServer3DSW::singleton->body_owner.getornull(p_object);
+		obj = PhysicsServer3DSW::singletonsw->body_owner.getornull(p_object);
 	}
 	ERR_FAIL_COND_V(!obj, Vector3());
 

+ 11 - 6
servers/physics_server_2d.cpp

@@ -655,12 +655,16 @@ void PhysicsServer2D::_bind_methods() {
 
 	/* JOINT API */
 
+	ClassDB::bind_method(D_METHOD("joint_create"), &PhysicsServer2D::joint_create);
+
+	ClassDB::bind_method(D_METHOD("joint_clear", "joint"), &PhysicsServer2D::joint_clear);
+
 	ClassDB::bind_method(D_METHOD("joint_set_param", "joint", "param", "value"), &PhysicsServer2D::joint_set_param);
 	ClassDB::bind_method(D_METHOD("joint_get_param", "joint", "param"), &PhysicsServer2D::joint_get_param);
 
-	ClassDB::bind_method(D_METHOD("pin_joint_create", "anchor", "body_a", "body_b"), &PhysicsServer2D::pin_joint_create, DEFVAL(RID()));
-	ClassDB::bind_method(D_METHOD("groove_joint_create", "groove1_a", "groove2_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::groove_joint_create, DEFVAL(RID()), DEFVAL(RID()));
-	ClassDB::bind_method(D_METHOD("damped_spring_joint_create", "anchor_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::damped_spring_joint_create, DEFVAL(RID()));
+	ClassDB::bind_method(D_METHOD("joint_make_pin", "joint", "anchor", "body_a", "body_b"), &PhysicsServer2D::joint_make_pin, DEFVAL(RID()));
+	ClassDB::bind_method(D_METHOD("joint_make_groove", "joint", "groove1_a", "groove2_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::joint_make_groove, DEFVAL(RID()), DEFVAL(RID()));
+	ClassDB::bind_method(D_METHOD("joint_make_damped_spring", "joint", "anchor_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::joint_make_damped_spring, DEFVAL(RID()));
 
 	ClassDB::bind_method(D_METHOD("damped_spring_joint_set_param", "joint", "param", "value"), &PhysicsServer2D::damped_spring_joint_set_param);
 	ClassDB::bind_method(D_METHOD("damped_spring_joint_get_param", "joint", "param"), &PhysicsServer2D::damped_spring_joint_get_param);
@@ -727,9 +731,10 @@ void PhysicsServer2D::_bind_methods() {
 	BIND_ENUM_CONSTANT(BODY_STATE_SLEEPING);
 	BIND_ENUM_CONSTANT(BODY_STATE_CAN_SLEEP);
 
-	BIND_ENUM_CONSTANT(JOINT_PIN);
-	BIND_ENUM_CONSTANT(JOINT_GROOVE);
-	BIND_ENUM_CONSTANT(JOINT_DAMPED_SPRING);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_GROOVE);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_DAMPED_SPRING);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_MAX);
 
 	BIND_ENUM_CONSTANT(JOINT_PARAM_BIAS);
 	BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_BIAS);

+ 11 - 6
servers/physics_server_2d.h

@@ -524,10 +524,15 @@ public:
 
 	/* JOINT API */
 
+	virtual RID joint_create() = 0;
+
+	virtual void joint_clear(RID p_joint) = 0;
+
 	enum JointType {
-		JOINT_PIN,
-		JOINT_GROOVE,
-		JOINT_DAMPED_SPRING
+		JOINT_TYPE_PIN,
+		JOINT_TYPE_GROOVE,
+		JOINT_TYPE_DAMPED_SPRING,
+		JOINT_TYPE_MAX
 	};
 
 	enum JointParam {
@@ -542,9 +547,9 @@ public:
 	virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0;
 	virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0;
 
-	virtual RID pin_joint_create(const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) = 0;
-	virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) = 0;
-	virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0;
+	virtual void joint_make_pin(RID p_joint, const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) = 0;
+	virtual void joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) = 0;
+	virtual void joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0;
 
 	enum PinJointParam {
 		PIN_JOINT_SOFTNESS

+ 53 - 15
servers/physics_server_3d.cpp

@@ -398,10 +398,47 @@ void PhysicsShapeQueryResult3D::_bind_methods() {
 
 ///////////////////////////////////////
 
+RID PhysicsServer3D::shape_create(ShapeType p_shape) {
+	switch (p_shape) {
+		case SHAPE_PLANE:
+			return plane_shape_create();
+		case SHAPE_RAY:
+			return ray_shape_create();
+		case SHAPE_SPHERE:
+			return sphere_shape_create();
+		case SHAPE_BOX:
+			return box_shape_create();
+		case SHAPE_CAPSULE:
+			return capsule_shape_create();
+		case SHAPE_CYLINDER:
+			return cylinder_shape_create();
+		case SHAPE_CONVEX_POLYGON:
+			return convex_polygon_shape_create();
+		case SHAPE_CONCAVE_POLYGON:
+			return concave_polygon_shape_create();
+		case SHAPE_HEIGHTMAP:
+			return heightmap_shape_create();
+		case SHAPE_CUSTOM:
+			return custom_shape_create();
+		default:
+			return RID();
+	}
+}
+
 void PhysicsServer3D::_bind_methods() {
 #ifndef _3D_DISABLED
 
-	ClassDB::bind_method(D_METHOD("shape_create", "type"), &PhysicsServer3D::shape_create);
+	ClassDB::bind_method(D_METHOD("plane_shape_create"), &PhysicsServer3D::plane_shape_create);
+	ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer3D::ray_shape_create);
+	ClassDB::bind_method(D_METHOD("sphere_shape_create"), &PhysicsServer3D::sphere_shape_create);
+	ClassDB::bind_method(D_METHOD("box_shape_create"), &PhysicsServer3D::box_shape_create);
+	ClassDB::bind_method(D_METHOD("capsule_shape_create"), &PhysicsServer3D::capsule_shape_create);
+	ClassDB::bind_method(D_METHOD("cylinder_shape_create"), &PhysicsServer3D::cylinder_shape_create);
+	ClassDB::bind_method(D_METHOD("convex_polygon_shape_create"), &PhysicsServer3D::convex_polygon_shape_create);
+	ClassDB::bind_method(D_METHOD("concave_polygon_shape_create"), &PhysicsServer3D::concave_polygon_shape_create);
+	ClassDB::bind_method(D_METHOD("heightmap_shape_create"), &PhysicsServer3D::heightmap_shape_create);
+	ClassDB::bind_method(D_METHOD("custom_shape_create"), &PhysicsServer3D::custom_shape_create);
+
 	ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &PhysicsServer3D::shape_set_data);
 
 	ClassDB::bind_method(D_METHOD("shape_get_type", "shape"), &PhysicsServer3D::shape_get_type);
@@ -450,9 +487,8 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer3D::area_set_monitorable);
 
 	ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer3D::area_set_ray_pickable);
-	ClassDB::bind_method(D_METHOD("area_is_ray_pickable", "area"), &PhysicsServer3D::area_is_ray_pickable);
 
-	ClassDB::bind_method(D_METHOD("body_create", "mode", "init_sleeping"), &PhysicsServer3D::body_create, DEFVAL(BODY_MODE_RIGID), DEFVAL(false));
+	ClassDB::bind_method(D_METHOD("body_create"), &PhysicsServer3D::body_create);
 
 	ClassDB::bind_method(D_METHOD("body_set_space", "body", "space"), &PhysicsServer3D::body_set_space);
 	ClassDB::bind_method(D_METHOD("body_get_space", "body"), &PhysicsServer3D::body_get_space);
@@ -517,19 +553,22 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer3D::body_set_force_integration_callback, DEFVAL(Variant()));
 
 	ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
-	ClassDB::bind_method(D_METHOD("body_is_ray_pickable", "body"), &PhysicsServer3D::body_is_ray_pickable);
 
 	ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state);
 
 	/* JOINT API */
 
-	BIND_ENUM_CONSTANT(JOINT_PIN);
-	BIND_ENUM_CONSTANT(JOINT_HINGE);
-	BIND_ENUM_CONSTANT(JOINT_SLIDER);
-	BIND_ENUM_CONSTANT(JOINT_CONE_TWIST);
-	BIND_ENUM_CONSTANT(JOINT_6DOF);
+	ClassDB::bind_method(D_METHOD("joint_create"), &PhysicsServer3D::joint_create);
+	ClassDB::bind_method(D_METHOD("joint_clear", "joint"), &PhysicsServer3D::joint_clear);
+
+	BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_HINGE);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_SLIDER);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_CONE_TWIST);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_6DOF);
+	BIND_ENUM_CONSTANT(JOINT_TYPE_MAX);
 
-	ClassDB::bind_method(D_METHOD("joint_create_pin", "body_A", "local_A", "body_B", "local_B"), &PhysicsServer3D::joint_create_pin);
+	ClassDB::bind_method(D_METHOD("joint_make_pin", "joint", "body_A", "local_A", "body_B", "local_B"), &PhysicsServer3D::joint_make_pin);
 	ClassDB::bind_method(D_METHOD("pin_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::pin_joint_set_param);
 	ClassDB::bind_method(D_METHOD("pin_joint_get_param", "joint", "param"), &PhysicsServer3D::pin_joint_get_param);
 
@@ -555,7 +594,7 @@ void PhysicsServer3D::_bind_methods() {
 	BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_USE_LIMIT);
 	BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_ENABLE_MOTOR);
 
-	ClassDB::bind_method(D_METHOD("joint_create_hinge", "body_A", "hinge_A", "body_B", "hinge_B"), &PhysicsServer3D::joint_create_hinge);
+	ClassDB::bind_method(D_METHOD("joint_make_hinge", "joint", "body_A", "hinge_A", "body_B", "hinge_B"), &PhysicsServer3D::joint_make_hinge);
 
 	ClassDB::bind_method(D_METHOD("hinge_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::hinge_joint_set_param);
 	ClassDB::bind_method(D_METHOD("hinge_joint_get_param", "joint", "param"), &PhysicsServer3D::hinge_joint_get_param);
@@ -563,7 +602,7 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("hinge_joint_set_flag", "joint", "flag", "enabled"), &PhysicsServer3D::hinge_joint_set_flag);
 	ClassDB::bind_method(D_METHOD("hinge_joint_get_flag", "joint", "flag"), &PhysicsServer3D::hinge_joint_get_flag);
 
-	ClassDB::bind_method(D_METHOD("joint_create_slider", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_slider);
+	ClassDB::bind_method(D_METHOD("joint_make_slider", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_make_slider);
 
 	ClassDB::bind_method(D_METHOD("slider_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::slider_joint_set_param);
 	ClassDB::bind_method(D_METHOD("slider_joint_get_param", "joint", "param"), &PhysicsServer3D::slider_joint_get_param);
@@ -593,7 +632,7 @@ void PhysicsServer3D::_bind_methods() {
 	BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING);
 	BIND_ENUM_CONSTANT(SLIDER_JOINT_MAX);
 
-	ClassDB::bind_method(D_METHOD("joint_create_cone_twist", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_cone_twist);
+	ClassDB::bind_method(D_METHOD("joint_make_cone_twist", "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_make_cone_twist);
 
 	ClassDB::bind_method(D_METHOD("cone_twist_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::cone_twist_joint_set_param);
 	ClassDB::bind_method(D_METHOD("cone_twist_joint_get_param", "joint", "param"), &PhysicsServer3D::cone_twist_joint_get_param);
@@ -631,7 +670,7 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("joint_set_solver_priority", "joint", "priority"), &PhysicsServer3D::joint_set_solver_priority);
 	ClassDB::bind_method(D_METHOD("joint_get_solver_priority", "joint"), &PhysicsServer3D::joint_get_solver_priority);
 
-	ClassDB::bind_method(D_METHOD("joint_create_generic_6dof", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_generic_6dof);
+	ClassDB::bind_method(D_METHOD("joint_make_generic_6dof", "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_make_generic_6dof);
 
 	ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_param", "joint", "axis", "param", "value"), &PhysicsServer3D::generic_6dof_joint_set_param);
 	ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_param", "joint", "axis", "param"), &PhysicsServer3D::generic_6dof_joint_get_param);
@@ -718,7 +757,6 @@ void PhysicsServer3D::_bind_methods() {
 }
 
 PhysicsServer3D::PhysicsServer3D() {
-	ERR_FAIL_COND(singleton != nullptr);
 	singleton = this;
 }
 

+ 47 - 31
servers/physics_server_3d.h

@@ -240,7 +240,19 @@ public:
 		SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
 	};
 
-	virtual RID shape_create(ShapeType p_shape) = 0;
+	RID shape_create(ShapeType p_shape);
+
+	virtual RID plane_shape_create() = 0;
+	virtual RID ray_shape_create() = 0;
+	virtual RID sphere_shape_create() = 0;
+	virtual RID box_shape_create() = 0;
+	virtual RID capsule_shape_create() = 0;
+	virtual RID cylinder_shape_create() = 0;
+	virtual RID convex_polygon_shape_create() = 0;
+	virtual RID concave_polygon_shape_create() = 0;
+	virtual RID heightmap_shape_create() = 0;
+	virtual RID custom_shape_create() = 0;
+
 	virtual void shape_set_data(RID p_shape, const Variant &p_data) = 0;
 	virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) = 0;
 
@@ -344,7 +356,6 @@ public:
 	virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
 
 	virtual void area_set_ray_pickable(RID p_area, bool p_enable) = 0;
-	virtual bool area_is_ray_pickable(RID p_area) const = 0;
 
 	/* BODY API */
 
@@ -357,7 +368,7 @@ public:
 		BODY_MODE_CHARACTER
 	};
 
-	virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) = 0;
+	virtual RID body_create() = 0;
 
 	virtual void body_set_space(RID p_body, RID p_space) = 0;
 	virtual RID body_get_space(RID p_body) const = 0;
@@ -468,7 +479,6 @@ public:
 	virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0;
 
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0;
-	virtual bool body_is_ray_pickable(RID p_body) const = 0;
 
 	// this function only works on physics process, errors and returns null otherwise
 	virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) = 0;
@@ -510,7 +520,7 @@ public:
 
 	/* SOFT BODY */
 
-	virtual RID soft_body_create(bool p_init_sleeping = false) = 0;
+	virtual RID soft_body_create() = 0;
 
 	virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) = 0;
 
@@ -536,55 +546,59 @@ public:
 	virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const = 0;
 
 	virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) = 0;
-	virtual bool soft_body_is_ray_pickable(RID p_body) const = 0;
 
 	virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) = 0;
-	virtual int soft_body_get_simulation_precision(RID p_body) = 0;
+	virtual int soft_body_get_simulation_precision(RID p_body) const = 0;
 
 	virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) = 0;
-	virtual real_t soft_body_get_total_mass(RID p_body) = 0;
+	virtual real_t soft_body_get_total_mass(RID p_body) const = 0;
 
 	virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) = 0;
-	virtual real_t soft_body_get_linear_stiffness(RID p_body) = 0;
+	virtual real_t soft_body_get_linear_stiffness(RID p_body) const = 0;
 
-	virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) = 0;
-	virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) = 0;
+	virtual void soft_body_set_angular_stiffness(RID p_body, real_t p_stiffness) = 0;
+	virtual real_t soft_body_get_angular_stiffness(RID p_body) const = 0;
 
 	virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) = 0;
-	virtual real_t soft_body_get_volume_stiffness(RID p_body) = 0;
+	virtual real_t soft_body_get_volume_stiffness(RID p_body) const = 0;
 
 	virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) = 0;
-	virtual real_t soft_body_get_pressure_coefficient(RID p_body) = 0;
+	virtual real_t soft_body_get_pressure_coefficient(RID p_body) const = 0;
 
 	virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) = 0;
-	virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) = 0;
+	virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) const = 0;
 
 	virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) = 0;
-	virtual real_t soft_body_get_damping_coefficient(RID p_body) = 0;
+	virtual real_t soft_body_get_damping_coefficient(RID p_body) const = 0;
 
 	virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) = 0;
-	virtual real_t soft_body_get_drag_coefficient(RID p_body) = 0;
+	virtual real_t soft_body_get_drag_coefficient(RID p_body) const = 0;
 
 	virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) = 0;
-	virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) = 0;
+	virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const = 0;
 
 	virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const = 0;
 
 	virtual void soft_body_remove_all_pinned_points(RID p_body) = 0;
 	virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) = 0;
-	virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) = 0;
+	virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const = 0;
 
 	/* JOINT API */
 
 	enum JointType {
-		JOINT_PIN,
-		JOINT_HINGE,
-		JOINT_SLIDER,
-		JOINT_CONE_TWIST,
-		JOINT_6DOF
+		JOINT_TYPE_PIN,
+		JOINT_TYPE_HINGE,
+		JOINT_TYPE_SLIDER,
+		JOINT_TYPE_CONE_TWIST,
+		JOINT_TYPE_6DOF,
+		JOINT_TYPE_MAX,
 
 	};
 
+	virtual RID joint_create() = 0;
+
+	virtual void joint_clear(RID p_joint) = 0;
+
 	virtual JointType joint_get_type(RID p_joint) const = 0;
 
 	virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0;
@@ -593,7 +607,7 @@ public:
 	virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0;
 	virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0;
 
-	virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0;
+	virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0;
 
 	enum PinJointParam {
 		PIN_JOINT_BIAS,
@@ -628,8 +642,8 @@ public:
 		HINGE_JOINT_FLAG_MAX
 	};
 
-	virtual RID joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0;
-	virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0;
+	virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0;
+	virtual void joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0;
 
 	virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) = 0;
 	virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const = 0;
@@ -665,7 +679,7 @@ public:
 
 	};
 
-	virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+	virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
 
 	virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) = 0;
 	virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const = 0;
@@ -679,7 +693,7 @@ public:
 		CONE_TWIST_MAX
 	};
 
-	virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+	virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
 
 	virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) = 0;
 	virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const = 0;
@@ -720,13 +734,13 @@ public:
 		G6DOF_JOINT_FLAG_MAX
 	};
 
-	virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
+	virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
 
 	virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) = 0;
-	virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) = 0;
+	virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) const = 0;
 
 	virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) = 0;
-	virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) = 0;
+	virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) const = 0;
 
 	/* QUERY API */
 
@@ -742,7 +756,9 @@ public:
 	virtual void set_active(bool p_active) = 0;
 	virtual void init() = 0;
 	virtual void step(real_t p_step) = 0;
+	virtual void sync() = 0;
 	virtual void flush_queries() = 0;
+	virtual void end_sync() = 0;
 	virtual void finish() = 0;
 
 	virtual bool is_flushing_queries() const = 0;

+ 11 - 2
servers/register_server_types.cpp

@@ -61,6 +61,7 @@
 #include "physics_2d/physics_server_2d_sw.h"
 #include "physics_2d/physics_server_2d_wrap_mt.h"
 #include "physics_3d/physics_server_3d_sw.h"
+#include "physics_3d/physics_server_3d_wrap_mt.h"
 #include "physics_server_2d.h"
 #include "physics_server_3d.h"
 #include "rendering/renderer_compositor.h"
@@ -76,11 +77,19 @@
 ShaderTypes *shader_types = nullptr;
 
 PhysicsServer3D *_createGodotPhysics3DCallback() {
-	return memnew(PhysicsServer3DSW);
+	bool using_threads = GLOBAL_GET("physics/3d/run_on_thread");
+
+	PhysicsServer3D *physics_server = memnew(PhysicsServer3DSW(using_threads));
+
+	return memnew(PhysicsServer3DWrapMT(physics_server, using_threads));
 }
 
 PhysicsServer2D *_createGodotPhysics2DCallback() {
-	return PhysicsServer2DWrapMT::init_server<PhysicsServer2DSW>();
+	bool using_threads = GLOBAL_GET("physics/2d/run_on_thread");
+
+	PhysicsServer2D *physics_server = memnew(PhysicsServer2DSW(using_threads));
+
+	return memnew(PhysicsServer2DWrapMT(physics_server, using_threads));
 }
 
 static bool has_server_feature_callback(const String &p_feature) {

+ 31 - 18
servers/rendering/renderer_canvas_cull.cpp

@@ -97,7 +97,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
 	}
 }
 
-void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<RendererCanvasCull::Item> &canvas_item_owner) {
+void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<RendererCanvasCull::Item, true> &canvas_item_owner) {
 	do {
 		ysort_owner->ysort_children_count = -1;
 		ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : nullptr;
@@ -356,12 +356,12 @@ bool RendererCanvasCull::was_sdf_used() {
 	return sdf_used;
 }
 
-RID RendererCanvasCull::canvas_create() {
+RID RendererCanvasCull::canvas_allocate() {
+	return canvas_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_initialize(RID p_rid) {
 	Canvas *canvas = memnew(Canvas);
-	ERR_FAIL_COND_V(!canvas, RID());
-	RID rid = canvas_owner.make_rid(canvas);
-
-	return rid;
+	canvas_owner.initialize_rid(p_rid, canvas);
 }
 
 void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) {
@@ -393,11 +393,12 @@ void RendererCanvasCull::canvas_set_parent(RID p_canvas, RID p_parent, float p_s
 	canvas->parent_scale = p_scale;
 }
 
-RID RendererCanvasCull::canvas_item_create() {
+RID RendererCanvasCull::canvas_item_allocate() {
+	return canvas_item_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_item_initialize(RID p_rid) {
 	Item *canvas_item = memnew(Item);
-	ERR_FAIL_COND_V(!canvas_item, RID());
-
-	return canvas_item_owner.make_rid(canvas_item);
+	canvas_item_owner.initialize_rid(p_rid, canvas_item);
 }
 
 void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
@@ -1075,10 +1076,13 @@ void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::Canva
 	}
 }
 
-RID RendererCanvasCull::canvas_light_create() {
+RID RendererCanvasCull::canvas_light_allocate() {
+	return canvas_light_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_light_initialize(RID p_rid) {
 	RendererCanvasRender::Light *clight = memnew(RendererCanvasRender::Light);
 	clight->light_internal = RSG::canvas_render->light_create();
-	return canvas_light_owner.make_rid(clight);
+	return canvas_light_owner.initialize_rid(p_rid, clight);
 }
 
 void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
@@ -1268,10 +1272,13 @@ void RendererCanvasCull::canvas_light_set_shadow_smooth(RID p_light, float p_smo
 	clight->shadow_smooth = p_smooth;
 }
 
-RID RendererCanvasCull::canvas_light_occluder_create() {
+RID RendererCanvasCull::canvas_light_occluder_allocate() {
+	return canvas_light_occluder_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_light_occluder_initialize(RID p_rid) {
 	RendererCanvasRender::LightOccluderInstance *occluder = memnew(RendererCanvasRender::LightOccluderInstance);
 
-	return canvas_light_occluder_owner.make_rid(occluder);
+	return canvas_light_occluder_owner.initialize_rid(p_rid, occluder);
 }
 
 void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
@@ -1349,10 +1356,13 @@ void RendererCanvasCull::canvas_light_occluder_set_light_mask(RID p_occluder, in
 	occluder->light_mask = p_mask;
 }
 
-RID RendererCanvasCull::canvas_occluder_polygon_create() {
+RID RendererCanvasCull::canvas_occluder_polygon_allocate() {
+	return canvas_light_occluder_polygon_owner.allocate_rid();
+}
+void RendererCanvasCull::canvas_occluder_polygon_initialize(RID p_rid) {
 	LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon);
 	occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create();
-	return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
+	return canvas_light_occluder_polygon_owner.initialize_rid(p_rid, occluder_poly);
 }
 
 void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
@@ -1393,8 +1403,11 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) {
 	RSG::canvas_render->set_shadow_texture_size(p_size);
 }
 
-RID RendererCanvasCull::canvas_texture_create() {
-	return RSG::storage->canvas_texture_create();
+RID RendererCanvasCull::canvas_texture_allocate() {
+	return RSG::storage->canvas_texture_allocate();
+}
+void RendererCanvasCull::canvas_texture_initialize(RID p_rid) {
+	RSG::storage->canvas_texture_initialize(p_rid);
 }
 
 void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {

+ 23 - 11
servers/rendering/renderer_canvas_cull.h

@@ -101,9 +101,9 @@ public:
 		}
 	};
 
-	RID_PtrOwner<LightOccluderPolygon> canvas_light_occluder_polygon_owner;
+	RID_PtrOwner<LightOccluderPolygon, true> canvas_light_occluder_polygon_owner;
 
-	RID_PtrOwner<RendererCanvasRender::LightOccluderInstance> canvas_light_occluder_owner;
+	RID_PtrOwner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner;
 
 	struct Canvas : public RendererViewport::CanvasBase {
 		Set<RID> viewports;
@@ -148,9 +148,9 @@ public:
 		}
 	};
 
-	mutable RID_PtrOwner<Canvas> canvas_owner;
-	RID_PtrOwner<Item> canvas_item_owner;
-	RID_PtrOwner<RendererCanvasRender::Light> canvas_light_owner;
+	mutable RID_PtrOwner<Canvas, true> canvas_owner;
+	RID_PtrOwner<Item, true> canvas_item_owner;
+	RID_PtrOwner<RendererCanvasRender::Light, true> canvas_light_owner;
 
 	bool disable_scale;
 	bool sdf_used = false;
@@ -168,13 +168,17 @@ public:
 
 	bool was_sdf_used();
 
-	RID canvas_create();
+	RID canvas_allocate();
+	void canvas_initialize(RID p_rid);
+
 	void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
 	void canvas_set_modulate(RID p_canvas, const Color &p_color);
 	void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale);
 	void canvas_set_disable_scale(bool p_disable);
 
-	RID canvas_item_create();
+	RID canvas_item_allocate();
+	void canvas_item_initialize(RID p_rid);
+
 	void canvas_item_set_parent(RID p_item, RID p_parent);
 
 	void canvas_item_set_visible(RID p_item, bool p_visible);
@@ -222,7 +226,9 @@ public:
 
 	void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);
 
-	RID canvas_light_create();
+	RID canvas_light_allocate();
+	void canvas_light_initialize(RID p_rid);
+
 	void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode);
 	void canvas_light_attach_to_canvas(RID p_light, RID p_canvas);
 	void canvas_light_set_enabled(RID p_light, bool p_enabled);
@@ -246,7 +252,9 @@ public:
 	void canvas_light_set_shadow_color(RID p_light, const Color &p_color);
 	void canvas_light_set_shadow_smooth(RID p_light, float p_smooth);
 
-	RID canvas_light_occluder_create();
+	RID canvas_light_occluder_allocate();
+	void canvas_light_occluder_initialize(RID p_rid);
+
 	void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas);
 	void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled);
 	void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon);
@@ -254,14 +262,18 @@ public:
 	void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform);
 	void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask);
 
-	RID canvas_occluder_polygon_create();
+	RID canvas_occluder_polygon_allocate();
+	void canvas_occluder_polygon_initialize(RID p_rid);
+
 	void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed);
 
 	void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode);
 
 	void canvas_set_shadow_texture_size(int p_size);
 
-	RID canvas_texture_create();
+	RID canvas_texture_allocate();
+	void canvas_texture_initialize(RID p_rid);
+
 	void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture);
 	void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess);
 

+ 9 - 3
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -2695,7 +2695,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
 		state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
 	}
 
-	default_canvas_texture = storage->canvas_texture_create();
+	default_canvas_texture = storage->canvas_texture_allocate();
+	storage->canvas_texture_initialize(default_canvas_texture);
 
 	state.shadow_texture_size = GLOBAL_GET("rendering/quality/2d_shadow_atlas/size");
 
@@ -2706,9 +2707,14 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
 	state.time = 0;
 
 	{
-		default_canvas_group_shader = storage->shader_create();
+		default_canvas_group_shader = storage->shader_allocate();
+		storage->shader_initialize(default_canvas_group_shader);
+
 		storage->shader_set_code(default_canvas_group_shader, "shader_type canvas_item; \nvoid fragment() {\n\tvec4 c = textureLod(SCREEN_TEXTURE,SCREEN_UV,0.0); if (c.a > 0.0001) c.rgb/=c.a; COLOR *= c; \n}\n");
-		default_canvas_group_material = storage->material_create();
+
+		default_canvas_group_material = storage->material_allocate();
+		storage->material_initialize(default_canvas_group_material);
+
 		storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
 	}
 

+ 12 - 6
servers/rendering/renderer_rd/renderer_scene_render_forward.cpp

@@ -3574,9 +3574,11 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
 
 	{
 		//default material and shader
-		default_shader = storage->shader_create();
+		default_shader = storage->shader_allocate();
+		storage->shader_initialize(default_shader);
 		storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n");
-		default_material = storage->material_create();
+		default_material = storage->material_allocate();
+		storage->material_initialize(default_material);
 		storage->material_set_shader(default_material, default_shader);
 
 		MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
@@ -3587,14 +3589,18 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
 	}
 
 	{
-		overdraw_material_shader = storage->shader_create();
+		overdraw_material_shader = storage->shader_allocate();
+		storage->shader_initialize(overdraw_material_shader);
 		storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
-		overdraw_material = storage->material_create();
+		overdraw_material = storage->material_allocate();
+		storage->material_initialize(overdraw_material);
 		storage->material_set_shader(overdraw_material, overdraw_material_shader);
 
-		wireframe_material_shader = storage->shader_create();
+		wireframe_material_shader = storage->shader_allocate();
+		storage->shader_initialize(wireframe_material_shader);
 		storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }");
-		wireframe_material = storage->material_create();
+		wireframe_material = storage->material_allocate();
+		storage->material_initialize(wireframe_material);
 		storage->material_set_shader(wireframe_material, wireframe_material_shader);
 	}
 

+ 28 - 10
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -1881,8 +1881,11 @@ void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_rough
 	RD::get_singleton()->draw_command_end_label();
 }
 
-RID RendererSceneRenderRD::sky_create() {
-	return sky_owner.make_rid(Sky());
+RID RendererSceneRenderRD::sky_allocate() {
+	return sky_owner.allocate_rid();
+}
+void RendererSceneRenderRD::sky_initialize(RID p_rid) {
+	sky_owner.initialize_rid(p_rid, Sky());
 }
 
 void RendererSceneRenderRD::_sky_invalidate(Sky *p_sky) {
@@ -2906,8 +2909,11 @@ RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_sky_material_fun
 	return material_data;
 }
 
-RID RendererSceneRenderRD::environment_create() {
-	return environment_owner.make_rid(Environment());
+RID RendererSceneRenderRD::environment_allocate() {
+	return environment_owner.allocate_rid();
+}
+void RendererSceneRenderRD::environment_initialize(RID p_rid) {
+	environment_owner.initialize_rid(p_rid, Environment());
 }
 
 void RendererSceneRenderRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
@@ -3991,8 +3997,11 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
 
 //////////////////////////////////////////////////
 
-RID RendererSceneRenderRD::camera_effects_create() {
-	return camera_effects_owner.make_rid(CameraEffects());
+RID RendererSceneRenderRD::camera_effects_allocate() {
+	return camera_effects_owner.allocate_rid();
+}
+void RendererSceneRenderRD::camera_effects_initialize(RID p_rid) {
+	camera_effects_owner.initialize_rid(p_rid, CameraEffects());
 }
 
 void RendererSceneRenderRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
@@ -8589,9 +8598,14 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
 
 	{
 		// default material and shader for sky shader
-		sky_shader.default_shader = storage->shader_create();
+		sky_shader.default_shader = storage->shader_allocate();
+		storage->shader_initialize(sky_shader.default_shader);
+
 		storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = vec3(0.0); } \n");
-		sky_shader.default_material = storage->material_create();
+
+		sky_shader.default_material = storage->material_allocate();
+		storage->material_initialize(sky_shader.default_material);
+
 		storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
 
 		SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
@@ -8665,9 +8679,13 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
 
 	{
 		// Need defaults for using fog with clear color
-		sky_scene_state.fog_shader = storage->shader_create();
+		sky_scene_state.fog_shader = storage->shader_allocate();
+		storage->shader_initialize(sky_scene_state.fog_shader);
+
 		storage->shader_set_code(sky_scene_state.fog_shader, "shader_type sky; uniform vec4 clear_color; void fragment() { COLOR = clear_color.rgb; } \n");
-		sky_scene_state.fog_material = storage->material_create();
+		sky_scene_state.fog_material = storage->material_allocate();
+		storage->material_initialize(sky_scene_state.fog_material);
+
 		storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
 
 		Vector<RD::Uniform> uniforms;

+ 10 - 6
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -333,7 +333,7 @@ private:
 	uint32_t sky_ggx_samples_quality;
 	bool sky_use_cubemap_array;
 
-	mutable RID_Owner<Sky> sky_owner;
+	mutable RID_Owner<Sky, true> sky_owner;
 
 	/* REFLECTION ATLAS */
 
@@ -809,7 +809,7 @@ private:
 
 	static uint64_t auto_exposure_counter;
 
-	mutable RID_Owner<Environment> environment_owner;
+	mutable RID_Owner<Environment, true> environment_owner;
 
 	/* CAMERA EFFECTS */
 
@@ -835,7 +835,7 @@ private:
 	float sss_scale = 0.05;
 	float sss_depth_scale = 0.01;
 
-	mutable RID_Owner<CameraEffects> camera_effects_owner;
+	mutable RID_Owner<CameraEffects, true> camera_effects_owner;
 
 	/* RENDER BUFFERS */
 
@@ -1654,7 +1654,9 @@ public:
 	RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
 	/* SKY API */
 
-	RID sky_create();
+	virtual RID sky_allocate();
+	virtual void sky_initialize(RID p_rid);
+
 	void sky_set_radiance_size(RID p_sky, int p_radiance_size);
 	void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
 	void sky_set_material(RID p_sky, RID p_material);
@@ -1666,7 +1668,8 @@ public:
 
 	/* ENVIRONMENT API */
 
-	RID environment_create();
+	virtual RID environment_allocate();
+	virtual void environment_initialize(RID p_rid);
 
 	void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
 	void environment_set_sky(RID p_env, RID p_sky);
@@ -1734,7 +1737,8 @@ public:
 
 	virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size);
 
-	virtual RID camera_effects_create();
+	virtual RID camera_effects_allocate();
+	virtual void camera_effects_initialize(RID p_rid);
 
 	virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter);
 	virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape);

+ 139 - 76
servers/rendering/renderer_rd/renderer_storage_rd.cpp

@@ -36,6 +36,10 @@
 #include "renderer_compositor_rd.h"
 #include "servers/rendering/shader_language.h"
 
+bool RendererStorageRD::can_create_resources_async() const {
+	return true;
+}
+
 Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) {
 	Ref<Image> image = p_image->duplicate();
 
@@ -535,9 +539,13 @@ Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image
 	return image;
 }
 
-RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) {
-	ERR_FAIL_COND_V(p_image.is_null(), RID());
-	ERR_FAIL_COND_V(p_image->is_empty(), RID());
+RID RendererStorageRD::texture_allocate() {
+	return texture_owner.allocate_rid();
+}
+
+void RendererStorageRD::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+	ERR_FAIL_COND(p_image.is_null());
+	ERR_FAIL_COND(p_image->is_empty());
 
 	TextureToRDFormat ret_format;
 	Ref<Image> image = _validate_texture_format(p_image, ret_format);
@@ -585,13 +593,13 @@ RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) {
 	Vector<Vector<uint8_t>> data_slices;
 	data_slices.push_back(data);
 	texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
-	ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID());
+	ERR_FAIL_COND(texture.rd_texture.is_null());
 	if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
 		rd_view.format_override = texture.rd_format_srgb;
 		texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
 		if (texture.rd_texture_srgb.is_null()) {
 			RD::get_singleton()->free(texture.rd_texture);
-			ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID());
+			ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
 		}
 	}
 
@@ -602,14 +610,14 @@ RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) {
 	texture.rd_view = rd_view;
 	texture.is_proxy = false;
 
-	return texture_owner.make_rid(texture);
+	texture_owner.initialize_rid(p_texture, texture);
 }
 
-RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
-	ERR_FAIL_COND_V(p_layers.size() == 0, RID());
+void RendererStorageRD::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+	ERR_FAIL_COND(p_layers.size() == 0);
 
-	ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6, RID());
-	ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0), RID());
+	ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
+	ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0));
 
 	TextureToRDFormat ret_format;
 	Vector<Ref<Image>> images;
@@ -620,7 +628,7 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
 		Image::Format valid_format = Image::FORMAT_MAX;
 
 		for (int i = 0; i < p_layers.size(); i++) {
-			ERR_FAIL_COND_V(p_layers[i]->is_empty(), RID());
+			ERR_FAIL_COND(p_layers[i]->is_empty());
 
 			if (i == 0) {
 				valid_width = p_layers[i]->get_width();
@@ -628,10 +636,10 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
 				valid_format = p_layers[i]->get_format();
 				valid_mipmaps = p_layers[i]->has_mipmaps();
 			} else {
-				ERR_FAIL_COND_V(p_layers[i]->get_width() != valid_width, RID());
-				ERR_FAIL_COND_V(p_layers[i]->get_height() != valid_height, RID());
-				ERR_FAIL_COND_V(p_layers[i]->get_format() != valid_format, RID());
-				ERR_FAIL_COND_V(p_layers[i]->has_mipmaps() != valid_mipmaps, RID());
+				ERR_FAIL_COND(p_layers[i]->get_width() != valid_width);
+				ERR_FAIL_COND(p_layers[i]->get_height() != valid_height);
+				ERR_FAIL_COND(p_layers[i]->get_format() != valid_format);
+				ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps);
 			}
 
 			images.push_back(_validate_texture_format(p_layers[i], ret_format));
@@ -695,13 +703,13 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
 		data_slices.push_back(data);
 	}
 	texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
-	ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID());
+	ERR_FAIL_COND(texture.rd_texture.is_null());
 	if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
 		rd_view.format_override = texture.rd_format_srgb;
 		texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
 		if (texture.rd_texture_srgb.is_null()) {
 			RD::get_singleton()->free(texture.rd_texture);
-			ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID());
+			ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
 		}
 	}
 
@@ -712,14 +720,14 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
 	texture.rd_view = rd_view;
 	texture.is_proxy = false;
 
-	return texture_owner.make_rid(texture);
+	texture_owner.initialize_rid(p_texture, texture);
 }
 
-RID RendererStorageRD::texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
-	ERR_FAIL_COND_V(p_data.size() == 0, RID());
+void RendererStorageRD::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
+	ERR_FAIL_COND(p_data.size() == 0);
 	Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data);
 	if (verr != Image::VALIDATE_3D_OK) {
-		ERR_FAIL_V_MSG(RID(), Image::get_3d_image_validation_error_text(verr));
+		ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
 	}
 
 	TextureToRDFormat ret_format;
@@ -811,13 +819,13 @@ RID RendererStorageRD::texture_3d_create(Image::Format p_format, int p_width, in
 	data_slices.push_back(all_data); //one slice
 
 	texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
-	ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID());
+	ERR_FAIL_COND(texture.rd_texture.is_null());
 	if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
 		rd_view.format_override = texture.rd_format_srgb;
 		texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
 		if (texture.rd_texture_srgb.is_null()) {
 			RD::get_singleton()->free(texture.rd_texture);
-			ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID());
+			ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
 		}
 	}
 
@@ -828,12 +836,12 @@ RID RendererStorageRD::texture_3d_create(Image::Format p_format, int p_width, in
 	texture.rd_view = rd_view;
 	texture.is_proxy = false;
 
-	return texture_owner.make_rid(texture);
+	texture_owner.initialize_rid(p_texture, texture);
 }
 
-RID RendererStorageRD::texture_proxy_create(RID p_base) {
+void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) {
 	Texture *tex = texture_owner.getornull(p_base);
-	ERR_FAIL_COND_V(!tex, RID());
+	ERR_FAIL_COND(!tex);
 	Texture proxy_tex = *tex;
 
 	proxy_tex.rd_view.format_override = tex->rd_format;
@@ -847,11 +855,9 @@ RID RendererStorageRD::texture_proxy_create(RID p_base) {
 	proxy_tex.is_proxy = true;
 	proxy_tex.proxies.clear();
 
-	RID rid = texture_owner.make_rid(proxy_tex);
-
-	tex->proxies.push_back(rid);
+	texture_owner.initialize_rid(p_texture, proxy_tex);
 
-	return rid;
+	tex->proxies.push_back(p_texture);
 }
 
 void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
@@ -961,7 +967,7 @@ void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
 }
 
 //these two APIs can be used together or in combination with the others.
-RID RendererStorageRD::texture_2d_placeholder_create() {
+void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) {
 	//this could be better optimized to reuse an existing image , done this way
 	//for now to get it working
 	Ref<Image> image;
@@ -974,10 +980,10 @@ RID RendererStorageRD::texture_2d_placeholder_create() {
 		}
 	}
 
-	return texture_2d_create(image);
+	texture_2d_initialize(p_texture, image);
 }
 
-RID RendererStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredType p_layered_type) {
+void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
 	//this could be better optimized to reuse an existing image , done this way
 	//for now to get it working
 	Ref<Image> image;
@@ -1000,10 +1006,10 @@ RID RendererStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredT
 		}
 	}
 
-	return texture_2d_layered_create(images, p_layered_type);
+	texture_2d_layered_initialize(p_texture, images, p_layered_type);
 }
 
-RID RendererStorageRD::texture_3d_placeholder_create() {
+void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) {
 	//this could be better optimized to reuse an existing image , done this way
 	//for now to get it working
 	Ref<Image> image;
@@ -1022,7 +1028,7 @@ RID RendererStorageRD::texture_3d_placeholder_create() {
 		images.push_back(image);
 	}
 
-	return texture_3d_create(Image::FORMAT_RGBA8, 4, 4, 4, false, images);
+	texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
 }
 
 Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
@@ -1223,8 +1229,11 @@ RendererStorageRD::CanvasTexture::~CanvasTexture() {
 	clear_sets();
 }
 
-RID RendererStorageRD::canvas_texture_create() {
-	return canvas_texture_owner.make_rid(memnew(CanvasTexture));
+RID RendererStorageRD::canvas_texture_allocate() {
+	return canvas_texture_owner.allocate_rid();
+}
+void RendererStorageRD::canvas_texture_initialize(RID p_rid) {
+	canvas_texture_owner.initialize_rid(p_rid, memnew(CanvasTexture));
 }
 
 void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
@@ -1365,12 +1374,15 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
 
 /* SHADER API */
 
-RID RendererStorageRD::shader_create() {
+RID RendererStorageRD::shader_allocate() {
+	return shader_owner.allocate_rid();
+}
+void RendererStorageRD::shader_initialize(RID p_rid) {
 	Shader shader;
 	shader.data = nullptr;
 	shader.type = SHADER_TYPE_MAX;
 
-	return shader_owner.make_rid(shader);
+	shader_owner.initialize_rid(p_rid, shader);
 }
 
 void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
@@ -1510,7 +1522,10 @@ RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID
 
 /* COMMON MATERIAL API */
 
-RID RendererStorageRD::material_create() {
+RID RendererStorageRD::material_allocate() {
+	return material_owner.allocate_rid();
+}
+void RendererStorageRD::material_initialize(RID p_rid) {
 	Material material;
 	material.data = nullptr;
 	material.shader = nullptr;
@@ -1520,12 +1535,8 @@ RID RendererStorageRD::material_create() {
 	material.uniform_dirty = false;
 	material.texture_dirty = false;
 	material.priority = 0;
-	RID id = material_owner.make_rid(material);
-	{
-		Material *material_ptr = material_owner.getornull(id);
-		material_ptr->self = id;
-	}
-	return id;
+	material.self = p_rid;
+	material_owner.initialize_rid(p_rid, material);
 }
 
 void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
@@ -2399,8 +2410,11 @@ void RendererStorageRD::_update_queued_materials() {
 
 /* MESH API */
 
-RID RendererStorageRD::mesh_create() {
-	return mesh_owner.make_rid(Mesh());
+RID RendererStorageRD::mesh_allocate() {
+	return mesh_owner.allocate_rid();
+}
+void RendererStorageRD::mesh_initialize(RID p_rid) {
+	mesh_owner.initialize_rid(p_rid, Mesh());
 }
 
 void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
@@ -3298,11 +3312,14 @@ void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surf
 
 ////////////////// MULTIMESH
 
-RID RendererStorageRD::multimesh_create() {
-	return multimesh_owner.make_rid(MultiMesh());
+RID RendererStorageRD::multimesh_allocate() {
+	return multimesh_owner.allocate_rid();
+}
+void RendererStorageRD::multimesh_initialize(RID p_rid) {
+	multimesh_owner.initialize_rid(p_rid, MultiMesh());
 }
 
-void RendererStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
 	MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
 	ERR_FAIL_COND(!multimesh);
 
@@ -3849,8 +3866,11 @@ void RendererStorageRD::_update_dirty_multimeshes() {
 
 /* PARTICLES */
 
-RID RendererStorageRD::particles_create() {
-	return particles_owner.make_rid(Particles());
+RID RendererStorageRD::particles_allocate() {
+	return particles_owner.allocate_rid();
+}
+void RendererStorageRD::particles_initialize(RID p_rid) {
+	particles_owner.initialize_rid(p_rid, Particles());
 }
 
 void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) {
@@ -4984,8 +5004,11 @@ RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_f
 
 /* PARTICLES COLLISION API */
 
-RID RendererStorageRD::particles_collision_create() {
-	return particles_collision_owner.make_rid(ParticlesCollision());
+RID RendererStorageRD::particles_collision_allocate() {
+	return particles_collision_owner.allocate_rid();
+}
+void RendererStorageRD::particles_collision_initialize(RID p_rid) {
+	particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
 }
 
 RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
@@ -5164,8 +5187,11 @@ void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_
 
 /* SKELETON API */
 
-RID RendererStorageRD::skeleton_create() {
-	return skeleton_owner.make_rid(Skeleton());
+RID RendererStorageRD::skeleton_allocate() {
+	return skeleton_owner.allocate_rid();
+}
+void RendererStorageRD::skeleton_initialize(RID p_rid) {
+	skeleton_owner.initialize_rid(p_rid, Skeleton());
 }
 
 void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
@@ -5176,7 +5202,7 @@ void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
 	}
 }
 
-void RendererStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
+void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
 	Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
 	ERR_FAIL_COND(!skeleton);
 	ERR_FAIL_COND(p_bones < 0);
@@ -5350,7 +5376,7 @@ void RendererStorageRD::_update_dirty_skeletons() {
 
 /* LIGHT */
 
-RID RendererStorageRD::light_create(RS::LightType p_type) {
+void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) {
 	Light light;
 	light.type = p_type;
 
@@ -5374,7 +5400,28 @@ RID RendererStorageRD::light_create(RS::LightType p_type) {
 	light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
 	light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
 
-	return light_owner.make_rid(light);
+	light_owner.initialize_rid(p_light, light);
+}
+
+RID RendererStorageRD::directional_light_allocate() {
+	return light_owner.allocate_rid();
+}
+void RendererStorageRD::directional_light_initialize(RID p_light) {
+	_light_initialize(p_light, RS::LIGHT_DIRECTIONAL);
+}
+
+RID RendererStorageRD::omni_light_allocate() {
+	return light_owner.allocate_rid();
+}
+void RendererStorageRD::omni_light_initialize(RID p_light) {
+	_light_initialize(p_light, RS::LIGHT_OMNI);
+}
+
+RID RendererStorageRD::spot_light_allocate() {
+	return light_owner.allocate_rid();
+}
+void RendererStorageRD::spot_light_initialize(RID p_light) {
+	_light_initialize(p_light, RS::LIGHT_SPOT);
 }
 
 void RendererStorageRD::light_set_color(RID p_light, const Color &p_color) {
@@ -5612,8 +5659,11 @@ AABB RendererStorageRD::light_get_aabb(RID p_light) const {
 
 /* REFLECTION PROBE */
 
-RID RendererStorageRD::reflection_probe_create() {
-	return reflection_probe_owner.make_rid(ReflectionProbe());
+RID RendererStorageRD::reflection_probe_allocate() {
+	return reflection_probe_owner.allocate_rid();
+}
+void RendererStorageRD::reflection_probe_initialize(RID p_reflection_probe) {
+	reflection_probe_owner.initialize_rid(p_reflection_probe, ReflectionProbe());
 }
 
 void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
@@ -5835,8 +5885,11 @@ float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe)
 	return reflection_probe->ambient_color_energy;
 }
 
-RID RendererStorageRD::decal_create() {
-	return decal_owner.make_rid(Decal());
+RID RendererStorageRD::decal_allocate() {
+	return decal_owner.allocate_rid();
+}
+void RendererStorageRD::decal_initialize(RID p_decal) {
+	decal_owner.initialize_rid(p_decal, Decal());
 }
 
 void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
@@ -5923,11 +5976,14 @@ AABB RendererStorageRD::decal_get_aabb(RID p_decal) const {
 	return AABB(-decal->extents, decal->extents * 2.0);
 }
 
-RID RendererStorageRD::gi_probe_create() {
-	return gi_probe_owner.make_rid(GIProbe());
+RID RendererStorageRD::gi_probe_allocate() {
+	return gi_probe_owner.allocate_rid();
+}
+void RendererStorageRD::gi_probe_initialize(RID p_gi_probe) {
+	gi_probe_owner.initialize_rid(p_gi_probe, GIProbe());
 }
 
-void RendererStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
+void RendererStorageRD::gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
 	GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
 	ERR_FAIL_COND(!gi_probe);
 
@@ -6276,8 +6332,12 @@ RID RendererStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) {
 
 /* LIGHTMAP API */
 
-RID RendererStorageRD::lightmap_create() {
-	return lightmap_owner.make_rid(Lightmap());
+RID RendererStorageRD::lightmap_allocate() {
+	return lightmap_owner.allocate_rid();
+}
+
+void RendererStorageRD::lightmap_initialize(RID p_lightmap) {
+	lightmap_owner.initialize_rid(p_lightmap, Lightmap());
 }
 
 void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
@@ -6480,7 +6540,8 @@ void RendererStorageRD::_clear_render_target(RenderTarget *rt) {
 void RendererStorageRD::_update_render_target(RenderTarget *rt) {
 	if (rt->texture.is_null()) {
 		//create a placeholder until updated
-		rt->texture = texture_2d_placeholder_create();
+		rt->texture = texture_allocate();
+		texture_2d_placeholder_initialize(rt->texture);
 		Texture *tex = texture_owner.getornull(rt->texture);
 		tex->is_render_target = true;
 	}
@@ -8217,13 +8278,13 @@ bool RendererStorageRD::free(RID p_rid) {
 
 	} else if (multimesh_owner.owns(p_rid)) {
 		_update_dirty_multimeshes();
-		multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
+		multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
 		MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
 		multimesh->dependency.deleted_notify(p_rid);
 		multimesh_owner.free(p_rid);
 	} else if (skeleton_owner.owns(p_rid)) {
 		_update_dirty_skeletons();
-		skeleton_allocate(p_rid, 0);
+		skeleton_allocate_data(p_rid, 0);
 		Skeleton *skeleton = skeleton_owner.getornull(p_rid);
 		skeleton->dependency.deleted_notify(p_rid);
 		skeleton_owner.free(p_rid);
@@ -8241,7 +8302,7 @@ bool RendererStorageRD::free(RID p_rid) {
 		decal->dependency.deleted_notify(p_rid);
 		decal_owner.free(p_rid);
 	} else if (gi_probe_owner.owns(p_rid)) {
-		gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
+		gi_probe_allocate_data(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
 		GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
 		gi_probe->dependency.deleted_notify(p_rid);
 		gi_probe_owner.free(p_rid);
@@ -8847,9 +8908,11 @@ RendererStorageRD::RendererStorageRD() {
 
 	{
 		// default material and shader for particles shader
-		particles_shader.default_shader = shader_create();
+		particles_shader.default_shader = shader_allocate();
+		shader_initialize(particles_shader.default_shader);
 		shader_set_code(particles_shader.default_shader, "shader_type particles; void compute() { COLOR = vec4(1.0); } \n");
-		particles_shader.default_material = material_create();
+		particles_shader.default_material = material_allocate();
+		material_initialize(particles_shader.default_material);
 		material_set_shader(particles_shader.default_material, particles_shader.default_shader);
 
 		ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RendererStorageRD::SHADER_TYPE_PARTICLES);

+ 78 - 52
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -221,7 +221,7 @@ private:
 		~CanvasTexture();
 	};
 
-	RID_PtrOwner<CanvasTexture> canvas_texture_owner;
+	RID_PtrOwner<CanvasTexture, true> canvas_texture_owner;
 
 	/* TEXTURE API */
 	struct Texture {
@@ -367,7 +367,7 @@ private:
 	};
 
 	ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
-	mutable RID_Owner<Shader> shader_owner;
+	mutable RID_Owner<Shader, true> shader_owner;
 
 	/* Material */
 
@@ -389,7 +389,7 @@ private:
 	};
 
 	MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
-	mutable RID_Owner<Material> material_owner;
+	mutable RID_Owner<Material, true> material_owner;
 
 	Material *material_update_list;
 	void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
@@ -484,7 +484,7 @@ private:
 		Dependency dependency;
 	};
 
-	mutable RID_Owner<Mesh> mesh_owner;
+	mutable RID_Owner<Mesh, true> mesh_owner;
 
 	struct MeshInstance {
 		Mesh *mesh;
@@ -587,7 +587,7 @@ private:
 		Dependency dependency;
 	};
 
-	mutable RID_Owner<MultiMesh> multimesh_owner;
+	mutable RID_Owner<MultiMesh, true> multimesh_owner;
 
 	MultiMesh *multimesh_dirty_list = nullptr;
 
@@ -893,7 +893,7 @@ private:
 
 	void update_particles();
 
-	mutable RID_Owner<Particles> particles_owner;
+	mutable RID_Owner<Particles, true> particles_owner;
 
 	/* Particles Collision */
 
@@ -915,7 +915,7 @@ private:
 		Dependency dependency;
 	};
 
-	mutable RID_Owner<ParticlesCollision> particles_collision_owner;
+	mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
 
 	struct ParticlesCollisionInstance {
 		RID collision;
@@ -945,7 +945,7 @@ private:
 		Dependency dependency;
 	};
 
-	mutable RID_Owner<Skeleton> skeleton_owner;
+	mutable RID_Owner<Skeleton, true> skeleton_owner;
 
 	_FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
 
@@ -977,7 +977,7 @@ private:
 		Dependency dependency;
 	};
 
-	mutable RID_Owner<Light> light_owner;
+	mutable RID_Owner<Light, true> light_owner;
 
 	/* REFLECTION PROBE */
 
@@ -1000,7 +1000,7 @@ private:
 		Dependency dependency;
 	};
 
-	mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
+	mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
 
 	/* DECAL */
 
@@ -1021,7 +1021,7 @@ private:
 		Dependency dependency;
 	};
 
-	mutable RID_Owner<Decal> decal_owner;
+	mutable RID_Owner<Decal, true> decal_owner;
 
 	/* GI PROBE */
 
@@ -1064,7 +1064,7 @@ private:
 	RID giprobe_sdf_shader_version_shader;
 	RID giprobe_sdf_shader_pipeline;
 
-	mutable RID_Owner<GIProbe> gi_probe_owner;
+	mutable RID_Owner<GIProbe, true> gi_probe_owner;
 
 	/* REFLECTION PROBE */
 
@@ -1095,7 +1095,7 @@ private:
 
 	uint64_t lightmap_array_version = 0;
 
-	mutable RID_Owner<Lightmap> lightmap_owner;
+	mutable RID_Owner<Lightmap, true> lightmap_owner;
 
 	float lightmap_probe_capture_update_speed = 4;
 
@@ -1249,12 +1249,16 @@ private:
 	EffectsRD effects;
 
 public:
+	virtual bool can_create_resources_async() const;
+
 	/* TEXTURE API */
 
-	virtual RID texture_2d_create(const Ref<Image> &p_image);
-	virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type);
-	virtual RID texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent
-	virtual RID texture_proxy_create(RID p_base);
+	virtual RID texture_allocate();
+
+	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image);
+	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type);
+	virtual void texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent
+	virtual void texture_proxy_initialize(RID p_texture, RID p_base);
 
 	virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate);
 
@@ -1264,9 +1268,9 @@ public:
 	virtual void texture_proxy_update(RID p_texture, RID p_proxy_to);
 
 	//these two APIs can be used together or in combination with the others.
-	virtual RID texture_2d_placeholder_create();
-	virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type);
-	virtual RID texture_3d_placeholder_create();
+	virtual void texture_2d_placeholder_initialize(RID p_texture);
+	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type);
+	virtual void texture_3d_placeholder_initialize(RID p_texture);
 
 	virtual Ref<Image> texture_2d_get(RID p_texture) const;
 	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const;
@@ -1338,7 +1342,8 @@ public:
 
 	/* CANVAS TEXTURE API */
 
-	virtual RID canvas_texture_create();
+	RID canvas_texture_allocate();
+	void canvas_texture_initialize(RID p_canvas_texture);
 
 	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture);
 	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess);
@@ -1350,7 +1355,8 @@ public:
 
 	/* SHADER API */
 
-	RID shader_create();
+	RID shader_allocate();
+	void shader_initialize(RID p_shader);
 
 	void shader_set_code(RID p_shader, const String &p_code);
 	String shader_get_code(RID p_shader) const;
@@ -1365,7 +1371,8 @@ public:
 
 	/* COMMON MATERIAL API */
 
-	RID material_create();
+	RID material_allocate();
+	void material_initialize(RID p_material);
 
 	void material_set_shader(RID p_material, RID p_shader);
 
@@ -1401,7 +1408,8 @@ public:
 
 	/* MESH API */
 
-	virtual RID mesh_create();
+	RID mesh_allocate();
+	void mesh_initialize(RID p_mesh);
 
 	virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count);
 
@@ -1622,9 +1630,10 @@ public:
 
 	/* MULTIMESH API */
 
-	RID multimesh_create();
+	RID multimesh_allocate();
+	void multimesh_initialize(RID p_multimesh);
 
-	void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
+	void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
 	int multimesh_get_instance_count(RID p_multimesh) const;
 
 	void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
@@ -1688,24 +1697,28 @@ public:
 
 	/* IMMEDIATE API */
 
-	RID immediate_create() { return RID(); }
-	void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {}
-	void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {}
-	void immediate_normal(RID p_immediate, const Vector3 &p_normal) {}
-	void immediate_tangent(RID p_immediate, const Plane &p_tangent) {}
-	void immediate_color(RID p_immediate, const Color &p_color) {}
-	void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {}
-	void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {}
-	void immediate_end(RID p_immediate) {}
-	void immediate_clear(RID p_immediate) {}
-	void immediate_set_material(RID p_immediate, RID p_material) {}
-	RID immediate_get_material(RID p_immediate) const { return RID(); }
-	AABB immediate_get_aabb(RID p_immediate) const { return AABB(); }
+	RID immediate_allocate() { return RID(); }
+	void immediate_initialize(RID p_immediate) {}
+
+	virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {}
+	virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {}
+	virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) {}
+	virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) {}
+	virtual void immediate_color(RID p_immediate, const Color &p_color) {}
+	virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {}
+	virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {}
+	virtual void immediate_end(RID p_immediate) {}
+	virtual void immediate_clear(RID p_immediate) {}
+	virtual void immediate_set_material(RID p_immediate, RID p_material) {}
+	virtual RID immediate_get_material(RID p_immediate) const { return RID(); }
+	virtual AABB immediate_get_aabb(RID p_immediate) const { return AABB(); }
 
 	/* SKELETON API */
 
-	RID skeleton_create();
-	void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
+	RID skeleton_allocate();
+	void skeleton_initialize(RID p_skeleton);
+
+	void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
 	void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
 	void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform);
 	int skeleton_get_bone_count(RID p_skeleton) const;
@@ -1739,11 +1752,16 @@ public:
 	}
 	/* Light API */
 
-	RID light_create(RS::LightType p_type);
+	void _light_initialize(RID p_rid, RS::LightType p_type);
+
+	RID directional_light_allocate();
+	void directional_light_initialize(RID p_light);
 
-	RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); }
-	RID omni_light_create() { return light_create(RS::LIGHT_OMNI); }
-	RID spot_light_create() { return light_create(RS::LIGHT_SPOT); }
+	RID omni_light_allocate();
+	void omni_light_initialize(RID p_light);
+
+	RID spot_light_allocate();
+	void spot_light_initialize(RID p_light);
 
 	void light_set_color(RID p_light, const Color &p_color);
 	void light_set_param(RID p_light, RS::LightParam p_param, float p_value);
@@ -1846,7 +1864,8 @@ public:
 
 	/* PROBE API */
 
-	RID reflection_probe_create();
+	RID reflection_probe_allocate();
+	void reflection_probe_initialize(RID p_reflection_probe);
 
 	void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode);
 	void reflection_probe_set_intensity(RID p_probe, float p_intensity);
@@ -1886,7 +1905,9 @@ public:
 
 	/* DECAL API */
 
-	virtual RID decal_create();
+	RID decal_allocate();
+	void decal_initialize(RID p_decal);
+
 	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents);
 	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture);
 	virtual void decal_set_emission_energy(RID p_decal, float p_energy);
@@ -1961,9 +1982,10 @@ public:
 
 	/* GI PROBE API */
 
-	RID gi_probe_create();
+	RID gi_probe_allocate();
+	void gi_probe_initialize(RID p_gi_probe);
 
-	void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
+	void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
 
 	AABB gi_probe_get_bounds(RID p_gi_probe) const;
 	Vector3i gi_probe_get_octree_size(RID p_gi_probe) const;
@@ -2014,7 +2036,8 @@ public:
 
 	/* LIGHTMAP CAPTURE */
 
-	virtual RID lightmap_create();
+	RID lightmap_allocate();
+	void lightmap_initialize(RID p_lightmap);
 
 	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics);
 	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds);
@@ -2063,7 +2086,8 @@ public:
 
 	/* PARTICLES */
 
-	RID particles_create();
+	RID particles_allocate();
+	void particles_initialize(RID p_particles_collision);
 
 	void particles_set_emitting(RID p_particles, bool p_emitting);
 	void particles_set_amount(RID p_particles, int p_amount);
@@ -2141,7 +2165,9 @@ public:
 
 	/* PARTICLES COLLISION */
 
-	virtual RID particles_collision_create();
+	RID particles_collision_allocate();
+	void particles_collision_initialize(RID p_particles_collision);
+
 	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type);
 	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask);
 	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius); //for spheres

+ 14 - 6
servers/rendering/renderer_scene.h

@@ -36,7 +36,8 @@
 
 class RendererScene {
 public:
-	virtual RID camera_create() = 0;
+	virtual RID camera_allocate() = 0;
+	virtual void camera_initialize(RID p_rid) = 0;
 
 	virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
 	virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
@@ -48,7 +49,8 @@ public:
 	virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
 	virtual bool is_camera(RID p_camera) const = 0;
 
-	virtual RID scenario_create() = 0;
+	virtual RID scenario_allocate() = 0;
+	virtual void scenario_initialize(RID p_rid) = 0;
 
 	virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) = 0;
 	virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
@@ -58,7 +60,8 @@ public:
 	virtual bool is_scenario(RID p_scenario) const = 0;
 	virtual RID scenario_get_environment(RID p_scenario) = 0;
 
-	virtual RID instance_create() = 0;
+	virtual RID instance_allocate() = 0;
+	virtual void instance_initialize(RID p_rid) = 0;
 
 	virtual void instance_set_base(RID p_instance, RID p_base) = 0;
 	virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0;
@@ -99,7 +102,9 @@ public:
 
 	/* SKY API */
 
-	virtual RID sky_create() = 0;
+	virtual RID sky_allocate() = 0;
+	virtual void sky_initialize(RID p_rid) = 0;
+
 	virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
 	virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0;
 	virtual void sky_set_material(RID p_sky, RID p_material) = 0;
@@ -107,7 +112,8 @@ public:
 
 	/* ENVIRONMENT API */
 
-	virtual RID environment_create() = 0;
+	virtual RID environment_allocate() = 0;
+	virtual void environment_initialize(RID p_rid) = 0;
 
 	virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
 	virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
@@ -159,7 +165,8 @@ public:
 
 	/* Camera Effects */
 
-	virtual RID camera_effects_create() = 0;
+	virtual RID camera_effects_allocate() = 0;
+	virtual void camera_effects_initialize(RID p_rid) = 0;
 
 	virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0;
 	virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0;
@@ -177,6 +184,7 @@ public:
 	/* Render Buffers */
 
 	virtual RID render_buffers_create() = 0;
+
 	virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
 
 	virtual void gi_set_use_half_resolution(bool p_enable) = 0;

+ 17 - 14
servers/rendering/renderer_scene_cull.cpp

@@ -39,9 +39,11 @@
 
 /* CAMERA API */
 
-RID RendererSceneCull::camera_create() {
-	Camera *camera = memnew(Camera);
-	return camera_owner.make_rid(camera);
+RID RendererSceneCull::camera_allocate() {
+	return camera_owner.allocate_rid();
+}
+void RendererSceneCull::camera_initialize(RID p_rid) {
+	camera_owner.initialize_rid(p_rid, memnew(Camera));
 }
 
 void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -290,11 +292,12 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
 	}
 }
 
-RID RendererSceneCull::scenario_create() {
+RID RendererSceneCull::scenario_allocate() {
+	return scenario_owner.allocate_rid();
+}
+void RendererSceneCull::scenario_initialize(RID p_rid) {
 	Scenario *scenario = memnew(Scenario);
-	ERR_FAIL_COND_V(!scenario, RID());
-	RID scenario_rid = scenario_owner.make_rid(scenario);
-	scenario->self = scenario_rid;
+	scenario->self = p_rid;
 
 	scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create();
 	scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest
@@ -307,7 +310,7 @@ RID RendererSceneCull::scenario_create() {
 	scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool);
 	scenario->instance_data.set_page_pool(&instance_data_page_pool);
 
-	return scenario_rid;
+	scenario_owner.initialize_rid(p_rid, scenario);
 }
 
 void RendererSceneCull::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) {
@@ -367,14 +370,14 @@ void RendererSceneCull::_instance_queue_update(Instance *p_instance, bool p_upda
 	_instance_update_list.add(&p_instance->update_item);
 }
 
-RID RendererSceneCull::instance_create() {
+RID RendererSceneCull::instance_allocate() {
+	return instance_owner.allocate_rid();
+}
+void RendererSceneCull::instance_initialize(RID p_rid) {
 	Instance *instance = memnew(Instance);
-	ERR_FAIL_COND_V(!instance, RID());
-
-	RID instance_rid = instance_owner.make_rid(instance);
-	instance->self = instance_rid;
+	instance->self = p_rid;
 
-	return instance_rid;
+	instance_owner.initialize_rid(p_rid, instance);
 }
 
 void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {

+ 17 - 9
servers/rendering/renderer_scene_cull.h

@@ -94,9 +94,11 @@ public:
 		}
 	};
 
-	mutable RID_PtrOwner<Camera> camera_owner;
+	mutable RID_PtrOwner<Camera, true> camera_owner;
+
+	virtual RID camera_allocate();
+	virtual void camera_initialize(RID p_rid);
 
-	virtual RID camera_create();
 	virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
 	virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
 	virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
@@ -296,14 +298,15 @@ public:
 
 	int indexer_update_iterations = 0;
 
-	mutable RID_PtrOwner<Scenario> scenario_owner;
+	mutable RID_PtrOwner<Scenario, true> scenario_owner;
 
 	static void _instance_pair(Instance *p_A, Instance *p_B);
 	static void _instance_unpair(Instance *p_A, Instance *p_B);
 
 	void _instance_update_mesh_instance(Instance *p_instance);
 
-	virtual RID scenario_create();
+	virtual RID scenario_allocate();
+	virtual void scenario_initialize(RID p_rid);
 
 	virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
 	virtual void scenario_set_environment(RID p_scenario, RID p_environment);
@@ -824,11 +827,12 @@ public:
 
 	uint32_t thread_cull_threshold = 200;
 
-	RID_PtrOwner<Instance> instance_owner;
+	RID_PtrOwner<Instance, true> instance_owner;
 
 	uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecesary on clustered
 
-	virtual RID instance_create();
+	virtual RID instance_allocate();
+	virtual void instance_initialize(RID p_rid);
 
 	virtual void instance_set_base(RID p_instance, RID p_base);
 	virtual void instance_set_scenario(RID p_instance, RID p_scenario);
@@ -957,13 +961,16 @@ public:
 
 	/* SKY API */
 
-	PASS0R(RID, sky_create)
+	PASS0R(RID, sky_allocate)
+	PASS1(sky_initialize, RID)
+
 	PASS2(sky_set_radiance_size, RID, int)
 	PASS2(sky_set_mode, RID, RS::SkyMode)
 	PASS2(sky_set_material, RID, RID)
 	PASS4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
 
-	PASS0R(RID, environment_create)
+	PASS0R(RID, environment_allocate)
+	PASS1(environment_initialize, RID)
 
 	PASS1RC(bool, is_environment, RID)
 
@@ -1012,7 +1019,8 @@ public:
 
 	/* CAMERA EFFECTS */
 
-	PASS0R(RID, camera_effects_create)
+	PASS0R(RID, camera_effects_allocate)
+	PASS1(camera_effects_initialize, RID)
 
 	PASS2(camera_effects_set_dof_blur_quality, RS::DOFBlurQuality, bool)
 	PASS1(camera_effects_set_dof_blur_bokeh_shape, RS::DOFBokehShape)

+ 8 - 5
servers/rendering/renderer_scene_render.h

@@ -71,8 +71,7 @@ public:
 
 	/* SHADOW ATLAS API */
 
-	virtual RID
-	shadow_atlas_create() = 0;
+	virtual RID shadow_atlas_create() = 0;
 	virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) = 0;
 	virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
 	virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
@@ -90,7 +89,9 @@ public:
 
 	/* SKY API */
 
-	virtual RID sky_create() = 0;
+	virtual RID sky_allocate() = 0;
+	virtual void sky_initialize(RID p_rid) = 0;
+
 	virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
 	virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0;
 	virtual void sky_set_material(RID p_sky, RID p_material) = 0;
@@ -98,7 +99,8 @@ public:
 
 	/* ENVIRONMENT API */
 
-	virtual RID environment_create() = 0;
+	virtual RID environment_allocate() = 0;
+	virtual void environment_initialize(RID p_rid) = 0;
 
 	virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
 	virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
@@ -146,7 +148,8 @@ public:
 	virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0;
 	virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
 
-	virtual RID camera_effects_create() = 0;
+	virtual RID camera_effects_allocate() = 0;
+	virtual void camera_effects_initialize(RID p_rid) = 0;
 
 	virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0;
 	virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0;

+ 52 - 28
servers/rendering/renderer_storage.h

@@ -119,12 +119,15 @@ public:
 		Set<Dependency *> dependencies;
 	};
 
+	virtual bool can_create_resources_async() const = 0;
 	/* TEXTURE API */
 
-	virtual RID texture_2d_create(const Ref<Image> &p_image) = 0;
-	virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
-	virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
-	virtual RID texture_proxy_create(RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
+	virtual RID texture_allocate() = 0;
+
+	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0;
+	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
+	virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
+	virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
 
 	virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming
 	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
@@ -132,9 +135,9 @@ public:
 	virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
 
 	//these two APIs can be used together or in combination with the others.
-	virtual RID texture_2d_placeholder_create() = 0;
-	virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) = 0;
-	virtual RID texture_3d_placeholder_create() = 0;
+	virtual void texture_2d_placeholder_initialize(RID p_texture) = 0;
+	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
+	virtual void texture_3d_placeholder_initialize(RID p_texture) = 0;
 
 	virtual Ref<Image> texture_2d_get(RID p_texture) const = 0;
 	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0;
@@ -161,7 +164,9 @@ public:
 
 	/* CANVAS TEXTURE API */
 
-	virtual RID canvas_texture_create() = 0;
+	virtual RID canvas_texture_allocate() = 0;
+	virtual void canvas_texture_initialize(RID p_rid) = 0;
+
 	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0;
 	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
 
@@ -170,7 +175,8 @@ public:
 
 	/* SHADER API */
 
-	virtual RID shader_create() = 0;
+	virtual RID shader_allocate() = 0;
+	virtual void shader_initialize(RID p_rid) = 0;
 
 	virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
 	virtual String shader_get_code(RID p_shader) const = 0;
@@ -184,7 +190,8 @@ public:
 
 	/* COMMON MATERIAL API */
 
-	virtual RID material_create() = 0;
+	virtual RID material_allocate() = 0;
+	virtual void material_initialize(RID p_rid) = 0;
 
 	virtual void material_set_render_priority(RID p_material, int priority) = 0;
 	virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
@@ -209,7 +216,8 @@ public:
 
 	/* MESH API */
 
-	virtual RID mesh_create() = 0;
+	virtual RID mesh_allocate() = 0;
+	virtual void mesh_initialize(RID p_rid) = 0;
 
 	virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0;
 
@@ -251,9 +259,10 @@ public:
 
 	/* MULTIMESH API */
 
-	virtual RID multimesh_create() = 0;
+	virtual RID multimesh_allocate() = 0;
+	virtual void multimesh_initialize(RID p_rid) = 0;
 
-	virtual void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+	virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
 
 	virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
 
@@ -280,7 +289,9 @@ public:
 
 	/* IMMEDIATE API */
 
-	virtual RID immediate_create() = 0;
+	virtual RID immediate_allocate() = 0;
+	virtual void immediate_initialize(RID p_rid) = 0;
+
 	virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0;
 	virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0;
 	virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0;
@@ -296,8 +307,10 @@ public:
 
 	/* SKELETON API */
 
-	virtual RID skeleton_create() = 0;
-	virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
+	virtual RID skeleton_allocate() = 0;
+	virtual void skeleton_initialize(RID p_rid) = 0;
+
+	virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
 	virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
 	virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0;
 	virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
@@ -307,11 +320,14 @@ public:
 
 	/* Light API */
 
-	virtual RID light_create(RS::LightType p_type) = 0;
+	virtual RID directional_light_allocate() = 0;
+	virtual void directional_light_initialize(RID p_rid) = 0;
 
-	RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); }
-	RID omni_light_create() { return light_create(RS::LIGHT_OMNI); }
-	RID spot_light_create() { return light_create(RS::LIGHT_SPOT); }
+	virtual RID omni_light_allocate() = 0;
+	virtual void omni_light_initialize(RID p_rid) = 0;
+
+	virtual RID spot_light_allocate() = 0;
+	virtual void spot_light_initialize(RID p_rid) = 0;
 
 	virtual void light_set_color(RID p_light, const Color &p_color) = 0;
 	virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
@@ -349,7 +365,8 @@ public:
 
 	/* PROBE API */
 
-	virtual RID reflection_probe_create() = 0;
+	virtual RID reflection_probe_allocate() = 0;
+	virtual void reflection_probe_initialize(RID p_rid) = 0;
 
 	virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
 	virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
@@ -380,7 +397,9 @@ public:
 
 	/* DECAL API */
 
-	virtual RID decal_create() = 0;
+	virtual RID decal_allocate() = 0;
+	virtual void decal_initialize(RID p_rid) = 0;
+
 	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
 	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
 	virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
@@ -395,9 +414,10 @@ public:
 
 	/* GI PROBE API */
 
-	virtual RID gi_probe_create() = 0;
+	virtual RID gi_probe_allocate() = 0;
+	virtual void gi_probe_initialize(RID p_rid) = 0;
 
-	virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
+	virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
 
 	virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
 	virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
@@ -440,9 +460,10 @@ public:
 
 	virtual uint32_t gi_probe_get_version(RID p_probe) = 0;
 
-	/* LIGHTMAP CAPTURE */
+	/* LIGHTMAP  */
 
-	virtual RID lightmap_create() = 0;
+	virtual RID lightmap_allocate() = 0;
+	virtual void lightmap_initialize(RID p_rid) = 0;
 
 	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
 	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
@@ -460,7 +481,8 @@ public:
 
 	/* PARTICLES */
 
-	virtual RID particles_create() = 0;
+	virtual RID particles_allocate() = 0;
+	virtual void particles_initialize(RID p_rid) = 0;
 
 	virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0;
 	virtual bool particles_get_emitting(RID p_particles) = 0;
@@ -507,7 +529,9 @@ public:
 
 	/* PARTICLES COLLISION */
 
-	virtual RID particles_collision_create() = 0;
+	virtual RID particles_collision_allocate() = 0;
+	virtual void particles_collision_initialize(RID p_rid) = 0;
+
 	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
 	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
 	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) = 0; //for spheres

+ 12 - 6
servers/rendering/renderer_viewport.cpp

@@ -608,19 +608,20 @@ void RendererViewport::draw_viewports() {
 	}
 }
 
-RID RendererViewport::viewport_create() {
-	Viewport *viewport = memnew(Viewport);
-
-	RID rid = viewport_owner.make_rid(viewport);
+RID RendererViewport::viewport_allocate() {
+	return viewport_owner.allocate_rid();
+}
 
-	viewport->self = rid;
+void RendererViewport::viewport_initialize(RID p_rid) {
+	Viewport *viewport = memnew(Viewport);
+	viewport->self = p_rid;
 	viewport->hide_scenario = false;
 	viewport->hide_canvas = false;
 	viewport->render_target = RSG::storage->render_target_create();
 	viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
 	viewport->viewport_render_direct_to_screen = false;
 
-	return rid;
+	viewport_owner.initialize_rid(p_rid, viewport);
 }
 
 void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
@@ -1019,5 +1020,10 @@ void RendererViewport::set_default_clear_color(const Color &p_color) {
 	RSG::storage->set_default_clear_color(p_color);
 }
 
+//workaround for setting this on thread
+void RendererViewport::call_set_use_vsync(bool p_enable) {
+	DisplayServer::get_singleton()->_set_use_vsync(p_enable);
+}
+
 RendererViewport::RendererViewport() {
 }

+ 6 - 2
servers/rendering/renderer_viewport.h

@@ -165,7 +165,7 @@ public:
 
 	uint64_t draw_viewports_pass = 0;
 
-	mutable RID_PtrOwner<Viewport> viewport_owner;
+	mutable RID_PtrOwner<Viewport, true> viewport_owner;
 
 	struct ViewportSort {
 		_FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
@@ -186,7 +186,8 @@ private:
 	void _draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye = XRInterface::EYE_MONO);
 
 public:
-	RID viewport_create();
+	RID viewport_allocate();
+	void viewport_initialize(RID p_rid);
 
 	void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
 
@@ -249,6 +250,9 @@ public:
 
 	bool free(RID p_rid);
 
+	//workaround for setting this on thread
+	void call_set_use_vsync(bool p_enable);
+
 	RendererViewport();
 	virtual ~RendererViewport() {}
 };

+ 101 - 12
servers/rendering/rendering_server_default.cpp

@@ -64,7 +64,7 @@ void RenderingServerDefault::_draw_margins() {
 
 /* FREE */
 
-void RenderingServerDefault::free(RID p_rid) {
+void RenderingServerDefault::_free(RID p_rid) {
 	if (RSG::storage->free(p_rid)) {
 		return;
 	}
@@ -91,7 +91,7 @@ void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const
 	frame_drawn_callbacks.push_back(fdc);
 }
 
-void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
+void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
 	//needs to be done before changes is reset to 0, to not force the editor to redraw
 	RS::get_singleton()->emit_signal("frame_pre_draw");
 
@@ -213,18 +213,15 @@ float RenderingServerDefault::get_frame_setup_time_cpu() const {
 	return frame_setup_time;
 }
 
-void RenderingServerDefault::sync() {
-}
-
 bool RenderingServerDefault::has_changed() const {
 	return changes > 0;
 }
 
-void RenderingServerDefault::init() {
+void RenderingServerDefault::_init() {
 	RSG::rasterizer->initialize();
 }
 
-void RenderingServerDefault::finish() {
+void RenderingServerDefault::_finish() {
 	if (test_cube.is_valid()) {
 		free(test_cube);
 	}
@@ -232,6 +229,32 @@ void RenderingServerDefault::finish() {
 	RSG::rasterizer->finalize();
 }
 
+void RenderingServerDefault::init() {
+	if (create_thread) {
+		print_verbose("RenderingServerWrapMT: Creating render thread");
+		DisplayServer::get_singleton()->release_rendering_thread();
+		if (create_thread) {
+			thread.start(_thread_callback, this);
+			print_verbose("RenderingServerWrapMT: Starting render thread");
+		}
+		while (!draw_thread_up) {
+			OS::get_singleton()->delay_usec(1000);
+		}
+		print_verbose("RenderingServerWrapMT: Finished render thread");
+	} else {
+		_init();
+	}
+}
+
+void RenderingServerDefault::finish() {
+	if (create_thread) {
+		command_queue.push(this, &RenderingServerDefault::_thread_exit);
+		thread.wait_to_finish();
+	} else {
+		_finish();
+	}
+}
+
 /* STATUS INFORMATION */
 
 int RenderingServerDefault::get_render_info(RenderInfo p_info) {
@@ -297,10 +320,6 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
 	RSG::storage->set_debug_generate_wireframes(p_generate);
 }
 
-void RenderingServerDefault::call_set_use_vsync(bool p_enable) {
-	DisplayServer::get_singleton()->_set_use_vsync(p_enable);
-}
-
 bool RenderingServerDefault::is_low_end() const {
 	// FIXME: Commented out when rebasing vulkan branch on master,
 	// causes a crash, it seems rasterizer is not initialized yet the
@@ -309,7 +328,77 @@ bool RenderingServerDefault::is_low_end() const {
 	return false;
 }
 
-RenderingServerDefault::RenderingServerDefault() {
+void RenderingServerDefault::_thread_exit() {
+	exit = true;
+}
+
+void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) {
+	if (!atomic_decrement(&draw_pending)) {
+		_draw(p_swap_buffers, frame_step);
+	}
+}
+
+void RenderingServerDefault::_thread_flush() {
+	atomic_decrement(&draw_pending);
+}
+
+void RenderingServerDefault::_thread_callback(void *_instance) {
+	RenderingServerDefault *vsmt = reinterpret_cast<RenderingServerDefault *>(_instance);
+
+	vsmt->_thread_loop();
+}
+
+void RenderingServerDefault::_thread_loop() {
+	server_thread = Thread::get_caller_id();
+
+	DisplayServer::get_singleton()->make_rendering_thread();
+
+	_init();
+
+	exit = false;
+	draw_thread_up = true;
+	while (!exit) {
+		// flush commands one by one, until exit is requested
+		command_queue.wait_and_flush_one();
+	}
+
+	command_queue.flush_all(); // flush all
+
+	_finish();
+}
+
+/* EVENT QUEUING */
+
+void RenderingServerDefault::sync() {
+	if (create_thread) {
+		atomic_increment(&draw_pending);
+		command_queue.push_and_sync(this, &RenderingServerDefault::_thread_flush);
+	} else {
+		command_queue.flush_all(); //flush all pending from other threads
+	}
+}
+
+void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
+	if (create_thread) {
+		atomic_increment(&draw_pending);
+		command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step);
+	} else {
+		_draw(p_swap_buffers, frame_step);
+	}
+}
+
+RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
+		command_queue(p_create_thread) {
+	create_thread = p_create_thread;
+	draw_pending = 0;
+	draw_thread_up = false;
+
+	if (!p_create_thread) {
+		server_thread = Thread::get_caller_id();
+	} else {
+		server_thread = 0;
+	}
+
 	RSG::canvas = memnew(RendererCanvasCull);
 	RSG::viewport = memnew(RendererViewport);
 	RendererSceneCull *sr = memnew(RendererSceneCull);

+ 622 - 589
servers/rendering/rendering_server_default.h

@@ -32,6 +32,7 @@
 #define RENDERING_SERVER_DEFAULT_H
 
 #include "core/math/octree.h"
+#include "core/templates/command_queue_mt.h"
 #include "core/templates/ordered_hash_map.h"
 #include "renderer_canvas_cull.h"
 #include "renderer_scene_cull.h"
@@ -39,6 +40,7 @@
 #include "rendering_server_globals.h"
 #include "servers/rendering/renderer_compositor.h"
 #include "servers/rendering_server.h"
+#include "servers/server_wrap_mt_common.h"
 
 class RenderingServerDefault : public RenderingServer {
 	enum {
@@ -81,6 +83,31 @@ class RenderingServerDefault : public RenderingServer {
 	uint64_t print_frame_profile_ticks_from = 0;
 	uint32_t print_frame_profile_frame_count = 0;
 
+	mutable CommandQueueMT command_queue;
+
+	static void _thread_callback(void *_instance);
+	void _thread_loop();
+
+	Thread::ID server_thread;
+	volatile bool exit;
+	Thread thread;
+	volatile bool draw_thread_up;
+	bool create_thread;
+
+	uint64_t draw_pending;
+	void _thread_draw(bool p_swap_buffers, double frame_step);
+	void _thread_flush();
+
+	void _thread_exit();
+
+	Mutex alloc_mutex;
+
+	void _draw(bool p_swap_buffers, double frame_step);
+	void _init();
+	void _finish();
+
+	void _free(RID p_rid);
+
 public:
 	//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
 	//#define DEBUG_CHANGES
@@ -97,807 +124,813 @@ public:
 
 #else
 	_FORCE_INLINE_ static void redraw_request() { changes++; }
+#endif
 
-#define DISPLAY_CHANGED \
-	changes++;
+#define WRITE_ACTION redraw_request();
+
+#ifdef DEBUG_SYNC
+#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
+#else
+#define SYNC_DEBUG
 #endif
 
-#define BIND0R(m_r, m_name) \
-	m_r m_name() { return BINDBASE->m_name(); }
-#define BIND0RC(m_r, m_name) \
-	m_r m_name() const { return BINDBASE->m_name(); }
-#define BIND1R(m_r, m_name, m_type1) \
-	m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); }
-#define BIND1RC(m_r, m_name, m_type1) \
-	m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); }
-#define BIND2R(m_r, m_name, m_type1, m_type2) \
-	m_r m_name(m_type1 arg1, m_type2 arg2) { return BINDBASE->m_name(arg1, arg2); }
-#define BIND2RC(m_r, m_name, m_type1, m_type2) \
-	m_r m_name(m_type1 arg1, m_type2 arg2) const { return BINDBASE->m_name(arg1, arg2); }
-#define BIND3R(m_r, m_name, m_type1, m_type2, m_type3) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { return BINDBASE->m_name(arg1, arg2, arg3); }
-#define BIND3RC(m_r, m_name, m_type1, m_type2, m_type3) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return BINDBASE->m_name(arg1, arg2, arg3); }
-#define BIND4R(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
-#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
-#define BIND5R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
-#define BIND5RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
-#define BIND6R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
-#define BIND6RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
-	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
-
-#define BIND0(m_name) \
-	void m_name() { DISPLAY_CHANGED BINDBASE->m_name(); }
-#define BIND1(m_name, m_type1) \
-	void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
-#define BIND1C(m_name, m_type1) \
-	void m_name(m_type1 arg1) const { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
-#define BIND2(m_name, m_type1, m_type2) \
-	void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); }
-#define BIND2C(m_name, m_type1, m_type2) \
-	void m_name(m_type1 arg1, m_type2 arg2) const { BINDBASE->m_name(arg1, arg2); }
-#define BIND3(m_name, m_type1, m_type2, m_type3) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3); }
-#define BIND4(m_name, m_type1, m_type2, m_type3, m_type4) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4); }
-#define BIND5(m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
-#define BIND6(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
-#define BIND7(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
-#define BIND8(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
-#define BIND9(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); }
-#define BIND10(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); }
-#define BIND11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); }
-#define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); }
-#define BIND13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); }
-#define BIND14(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); }
-#define BIND15(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14, m_type15) \
-	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14, m_type15 arg15) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); }
+#include "servers/server_wrap_mt_common.h"
 
 //from now on, calls forwarded to this singleton
-#define BINDBASE RSG::storage
+#define ServerName RendererStorage
+#define server_name RSG::storage
 
 	/* TEXTURE API */
 
+#define FUNCRIDTEX0(m_type)                                                                           \
+	virtual RID m_type##_create() override {                                                          \
+		RID ret = RSG::storage->texture_allocate();                                                   \
+		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
+			RSG::storage->m_type##_initialize(ret);                                                   \
+		} else {                                                                                      \
+			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret);             \
+		}                                                                                             \
+		return ret;                                                                                   \
+	}
+
+#define FUNCRIDTEX1(m_type, m_type1)                                                                  \
+	virtual RID m_type##_create(m_type1 p1) override {                                                \
+		RID ret = RSG::storage->texture_allocate();                                                   \
+		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
+			RSG::storage->m_type##_initialize(ret, p1);                                               \
+		} else {                                                                                      \
+			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1);         \
+		}                                                                                             \
+		return ret;                                                                                   \
+	}
+
+#define FUNCRIDTEX2(m_type, m_type1, m_type2)                                                         \
+	virtual RID m_type##_create(m_type1 p1, m_type2 p2) override {                                    \
+		RID ret = RSG::storage->texture_allocate();                                                   \
+		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
+			RSG::storage->m_type##_initialize(ret, p1, p2);                                           \
+		} else {                                                                                      \
+			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2);     \
+		}                                                                                             \
+		return ret;                                                                                   \
+	}
+
+#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6)                                  \
+	virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \
+		RID ret = RSG::storage->texture_allocate();                                                                \
+		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) {              \
+			RSG::storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6);                                        \
+		} else {                                                                                                   \
+			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6);  \
+		}                                                                                                          \
+		return ret;                                                                                                \
+	}
+
 	//these go pass-through, as they can be called from any thread
-	BIND1R(RID, texture_2d_create, const Ref<Image> &)
-	BIND2R(RID, texture_2d_layered_create, const Vector<Ref<Image>> &, TextureLayeredType)
-	BIND6R(RID, texture_3d_create, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
-	BIND1R(RID, texture_proxy_create, RID)
+	FUNCRIDTEX1(texture_2d, const Ref<Image> &)
+	FUNCRIDTEX2(texture_2d_layered, const Vector<Ref<Image>> &, TextureLayeredType)
+	FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
+	FUNCRIDTEX1(texture_proxy, RID)
 
 	//goes pass-through
-	BIND3(texture_2d_update_immediate, RID, const Ref<Image> &, int)
+	FUNC3(texture_2d_update_immediate, RID, const Ref<Image> &, int)
 	//these go through command queue if they are in another thread
-	BIND3(texture_2d_update, RID, const Ref<Image> &, int)
-	BIND2(texture_3d_update, RID, const Vector<Ref<Image>> &)
-	BIND2(texture_proxy_update, RID, RID)
+	FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
+	FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)
+	FUNC2(texture_proxy_update, RID, RID)
 
 	//these also go pass-through
-	BIND0R(RID, texture_2d_placeholder_create)
-	BIND1R(RID, texture_2d_layered_placeholder_create, TextureLayeredType)
-	BIND0R(RID, texture_3d_placeholder_create)
+	FUNCRIDTEX0(texture_2d_placeholder)
+	FUNCRIDTEX1(texture_2d_layered_placeholder, TextureLayeredType)
+	FUNCRIDTEX0(texture_3d_placeholder)
 
-	BIND1RC(Ref<Image>, texture_2d_get, RID)
-	BIND2RC(Ref<Image>, texture_2d_layer_get, RID, int)
-	BIND1RC(Vector<Ref<Image>>, texture_3d_get, RID)
+	FUNC1RC(Ref<Image>, texture_2d_get, RID)
+	FUNC2RC(Ref<Image>, texture_2d_layer_get, RID, int)
+	FUNC1RC(Vector<Ref<Image>>, texture_3d_get, RID)
 
-	BIND2(texture_replace, RID, RID)
+	FUNC2(texture_replace, RID, RID)
 
-	BIND3(texture_set_size_override, RID, int, int)
+	FUNC3(texture_set_size_override, RID, int, int)
 // FIXME: Disabled during Vulkan refactoring, should be ported.
 #if 0
-	BIND2(texture_bind, RID, uint32_t)
+	FUNC2(texture_bind, RID, uint32_t)
 #endif
 
-	BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
-	BIND3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
-	BIND3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
+	FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
+	FUNC3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
+	FUNC3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
 
-	BIND2(texture_set_path, RID, const String &)
-	BIND1RC(String, texture_get_path, RID)
-	BIND1(texture_debug_usage, List<TextureInfo> *)
+	FUNC2(texture_set_path, RID, const String &)
+	FUNC1RC(String, texture_get_path, RID)
+	FUNC1(texture_debug_usage, List<TextureInfo> *)
 
-	BIND2(texture_set_force_redraw_if_visible, RID, bool)
+	FUNC2(texture_set_force_redraw_if_visible, RID, bool)
 
 	/* SHADER API */
 
-	BIND0R(RID, shader_create)
+	FUNCRIDSPLIT(shader)
 
-	BIND2(shader_set_code, RID, const String &)
-	BIND1RC(String, shader_get_code, RID)
+	FUNC2(shader_set_code, RID, const String &)
+	FUNC1RC(String, shader_get_code, RID)
 
-	BIND2C(shader_get_param_list, RID, List<PropertyInfo> *)
+	FUNC2C(shader_get_param_list, RID, List<PropertyInfo> *)
 
-	BIND3(shader_set_default_texture_param, RID, const StringName &, RID)
-	BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &)
-	BIND2RC(Variant, shader_get_param_default, RID, const StringName &)
+	FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
+	FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
+	FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
 
-	BIND1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
+	FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
 
 	/* COMMON MATERIAL API */
 
-	BIND0R(RID, material_create)
+	FUNCRIDSPLIT(material)
 
-	BIND2(material_set_shader, RID, RID)
+	FUNC2(material_set_shader, RID, RID)
 
-	BIND3(material_set_param, RID, const StringName &, const Variant &)
-	BIND2RC(Variant, material_get_param, RID, const StringName &)
+	FUNC3(material_set_param, RID, const StringName &, const Variant &)
+	FUNC2RC(Variant, material_get_param, RID, const StringName &)
 
-	BIND2(material_set_render_priority, RID, int)
-	BIND2(material_set_next_pass, RID, RID)
+	FUNC2(material_set_render_priority, RID, int)
+	FUNC2(material_set_next_pass, RID, RID)
 
 	/* MESH API */
 
-	virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) {
-		RID mesh = mesh_create();
-		mesh_set_blend_shape_count(mesh, p_blend_shape_count);
-		for (int i = 0; i < p_surfaces.size(); i++) {
-			mesh_add_surface(mesh, p_surfaces[i]);
+	virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override {
+		RID mesh = RSG::storage->mesh_allocate();
+
+		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) {
+			if (Thread::get_caller_id() == server_thread) {
+				command_queue.flush_if_pending();
+			}
+			RSG::storage->mesh_initialize(mesh);
+			RSG::storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
+			for (int i = 0; i < p_surfaces.size(); i++) {
+				RSG::storage->mesh_add_surface(mesh, p_surfaces[i]);
+			}
+		} else {
+			command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh);
+			command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
+			for (int i = 0; i < p_surfaces.size(); i++) {
+				RSG::storage->mesh_add_surface(mesh, p_surfaces[i]);
+				command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]);
+			}
 		}
+
 		return mesh;
 	}
 
-	BIND2(mesh_set_blend_shape_count, RID, int)
+	FUNC2(mesh_set_blend_shape_count, RID, int)
 
-	BIND0R(RID, mesh_create)
+	FUNCRIDSPLIT(mesh)
 
-	BIND2(mesh_add_surface, RID, const SurfaceData &)
+	FUNC2(mesh_add_surface, RID, const SurfaceData &)
 
-	BIND1RC(int, mesh_get_blend_shape_count, RID)
+	FUNC1RC(int, mesh_get_blend_shape_count, RID)
 
-	BIND2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
-	BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
+	FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
+	FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
 
-	BIND4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
+	FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
 
-	BIND3(mesh_surface_set_material, RID, int, RID)
-	BIND2RC(RID, mesh_surface_get_material, RID, int)
+	FUNC3(mesh_surface_set_material, RID, int, RID)
+	FUNC2RC(RID, mesh_surface_get_material, RID, int)
 
-	BIND2RC(SurfaceData, mesh_get_surface, RID, int)
+	FUNC2RC(SurfaceData, mesh_get_surface, RID, int)
 
-	BIND1RC(int, mesh_get_surface_count, RID)
+	FUNC1RC(int, mesh_get_surface_count, RID)
 
-	BIND2(mesh_set_custom_aabb, RID, const AABB &)
-	BIND1RC(AABB, mesh_get_custom_aabb, RID)
+	FUNC2(mesh_set_custom_aabb, RID, const AABB &)
+	FUNC1RC(AABB, mesh_get_custom_aabb, RID)
 
-	BIND2(mesh_set_shadow_mesh, RID, RID)
+	FUNC2(mesh_set_shadow_mesh, RID, RID)
 
-	BIND1(mesh_clear, RID)
+	FUNC1(mesh_clear, RID)
 
 	/* MULTIMESH API */
 
-	BIND0R(RID, multimesh_create)
+	FUNCRIDSPLIT(multimesh)
 
-	BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
-	BIND1RC(int, multimesh_get_instance_count, RID)
+	FUNC5(multimesh_allocate_data, RID, int, MultimeshTransformFormat, bool, bool)
+	FUNC1RC(int, multimesh_get_instance_count, RID)
 
-	BIND2(multimesh_set_mesh, RID, RID)
-	BIND3(multimesh_instance_set_transform, RID, int, const Transform &)
-	BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
-	BIND3(multimesh_instance_set_color, RID, int, const Color &)
-	BIND3(multimesh_instance_set_custom_data, RID, int, const Color &)
+	FUNC2(multimesh_set_mesh, RID, RID)
+	FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
+	FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
+	FUNC3(multimesh_instance_set_color, RID, int, const Color &)
+	FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &)
 
-	BIND1RC(RID, multimesh_get_mesh, RID)
-	BIND1RC(AABB, multimesh_get_aabb, RID)
+	FUNC1RC(RID, multimesh_get_mesh, RID)
+	FUNC1RC(AABB, multimesh_get_aabb, RID)
 
-	BIND2RC(Transform, multimesh_instance_get_transform, RID, int)
-	BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
-	BIND2RC(Color, multimesh_instance_get_color, RID, int)
-	BIND2RC(Color, multimesh_instance_get_custom_data, RID, int)
+	FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
+	FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
+	FUNC2RC(Color, multimesh_instance_get_color, RID, int)
+	FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
 
-	BIND2(multimesh_set_buffer, RID, const Vector<float> &)
-	BIND1RC(Vector<float>, multimesh_get_buffer, RID)
+	FUNC2(multimesh_set_buffer, RID, const Vector<float> &)
+	FUNC1RC(Vector<float>, multimesh_get_buffer, RID)
 
-	BIND2(multimesh_set_visible_instances, RID, int)
-	BIND1RC(int, multimesh_get_visible_instances, RID)
+	FUNC2(multimesh_set_visible_instances, RID, int)
+	FUNC1RC(int, multimesh_get_visible_instances, RID)
 
 	/* IMMEDIATE API */
 
-	BIND0R(RID, immediate_create)
-	BIND3(immediate_begin, RID, PrimitiveType, RID)
-	BIND2(immediate_vertex, RID, const Vector3 &)
-	BIND2(immediate_normal, RID, const Vector3 &)
-	BIND2(immediate_tangent, RID, const Plane &)
-	BIND2(immediate_color, RID, const Color &)
-	BIND2(immediate_uv, RID, const Vector2 &)
-	BIND2(immediate_uv2, RID, const Vector2 &)
-	BIND1(immediate_end, RID)
-	BIND1(immediate_clear, RID)
-	BIND2(immediate_set_material, RID, RID)
-	BIND1RC(RID, immediate_get_material, RID)
+	FUNCRIDSPLIT(immediate)
+	FUNC3(immediate_begin, RID, PrimitiveType, RID)
+	FUNC2(immediate_vertex, RID, const Vector3 &)
+	FUNC2(immediate_normal, RID, const Vector3 &)
+	FUNC2(immediate_tangent, RID, const Plane &)
+	FUNC2(immediate_color, RID, const Color &)
+	FUNC2(immediate_uv, RID, const Vector2 &)
+	FUNC2(immediate_uv2, RID, const Vector2 &)
+	FUNC1(immediate_end, RID)
+	FUNC1(immediate_clear, RID)
+	FUNC2(immediate_set_material, RID, RID)
+	FUNC1RC(RID, immediate_get_material, RID)
 
 	/* SKELETON API */
 
-	BIND0R(RID, skeleton_create)
-	BIND3(skeleton_allocate, RID, int, bool)
-	BIND1RC(int, skeleton_get_bone_count, RID)
-	BIND3(skeleton_bone_set_transform, RID, int, const Transform &)
-	BIND2RC(Transform, skeleton_bone_get_transform, RID, int)
-	BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
-	BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
-	BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &)
+	FUNCRIDSPLIT(skeleton)
+	FUNC3(skeleton_allocate_data, RID, int, bool)
+	FUNC1RC(int, skeleton_get_bone_count, RID)
+	FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
+	FUNC2RC(Transform, skeleton_bone_get_transform, RID, int)
+	FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
+	FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
+	FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
 
 	/* Light API */
 
-	BIND0R(RID, directional_light_create)
-	BIND0R(RID, omni_light_create)
-	BIND0R(RID, spot_light_create)
+	FUNCRIDSPLIT(directional_light)
+	FUNCRIDSPLIT(omni_light)
+	FUNCRIDSPLIT(spot_light)
 
-	BIND2(light_set_color, RID, const Color &)
-	BIND3(light_set_param, RID, LightParam, float)
-	BIND2(light_set_shadow, RID, bool)
-	BIND2(light_set_shadow_color, RID, const Color &)
-	BIND2(light_set_projector, RID, RID)
-	BIND2(light_set_negative, RID, bool)
-	BIND2(light_set_cull_mask, RID, uint32_t)
-	BIND2(light_set_reverse_cull_face_mode, RID, bool)
-	BIND2(light_set_bake_mode, RID, LightBakeMode)
-	BIND2(light_set_max_sdfgi_cascade, RID, uint32_t)
+	FUNC2(light_set_color, RID, const Color &)
+	FUNC3(light_set_param, RID, LightParam, float)
+	FUNC2(light_set_shadow, RID, bool)
+	FUNC2(light_set_shadow_color, RID, const Color &)
+	FUNC2(light_set_projector, RID, RID)
+	FUNC2(light_set_negative, RID, bool)
+	FUNC2(light_set_cull_mask, RID, uint32_t)
+	FUNC2(light_set_reverse_cull_face_mode, RID, bool)
+	FUNC2(light_set_bake_mode, RID, LightBakeMode)
+	FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
 
-	BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
+	FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
 
-	BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
-	BIND2(light_directional_set_blend_splits, RID, bool)
-	BIND2(light_directional_set_sky_only, RID, bool)
-	BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
+	FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
+	FUNC2(light_directional_set_blend_splits, RID, bool)
+	FUNC2(light_directional_set_sky_only, RID, bool)
+	FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
 
 	/* PROBE API */
 
-	BIND0R(RID, reflection_probe_create)
-
-	BIND2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
-	BIND2(reflection_probe_set_intensity, RID, float)
-	BIND2(reflection_probe_set_ambient_color, RID, const Color &)
-	BIND2(reflection_probe_set_ambient_energy, RID, float)
-	BIND2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
-	BIND2(reflection_probe_set_max_distance, RID, float)
-	BIND2(reflection_probe_set_extents, RID, const Vector3 &)
-	BIND2(reflection_probe_set_origin_offset, RID, const Vector3 &)
-	BIND2(reflection_probe_set_as_interior, RID, bool)
-	BIND2(reflection_probe_set_enable_box_projection, RID, bool)
-	BIND2(reflection_probe_set_enable_shadows, RID, bool)
-	BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
-	BIND2(reflection_probe_set_resolution, RID, int)
-	BIND2(reflection_probe_set_lod_threshold, RID, float)
+	FUNCRIDSPLIT(reflection_probe)
+
+	FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
+	FUNC2(reflection_probe_set_intensity, RID, float)
+	FUNC2(reflection_probe_set_ambient_color, RID, const Color &)
+	FUNC2(reflection_probe_set_ambient_energy, RID, float)
+	FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
+	FUNC2(reflection_probe_set_max_distance, RID, float)
+	FUNC2(reflection_probe_set_extents, RID, const Vector3 &)
+	FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &)
+	FUNC2(reflection_probe_set_as_interior, RID, bool)
+	FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
+	FUNC2(reflection_probe_set_enable_shadows, RID, bool)
+	FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
+	FUNC2(reflection_probe_set_resolution, RID, int)
+	FUNC2(reflection_probe_set_lod_threshold, RID, float)
 
 	/* DECAL API */
 
-	BIND0R(RID, decal_create)
+	FUNCRIDSPLIT(decal)
 
-	BIND2(decal_set_extents, RID, const Vector3 &)
-	BIND3(decal_set_texture, RID, DecalTexture, RID)
-	BIND2(decal_set_emission_energy, RID, float)
-	BIND2(decal_set_albedo_mix, RID, float)
-	BIND2(decal_set_modulate, RID, const Color &)
-	BIND2(decal_set_cull_mask, RID, uint32_t)
-	BIND4(decal_set_distance_fade, RID, bool, float, float)
-	BIND3(decal_set_fade, RID, float, float)
-	BIND2(decal_set_normal_fade, RID, float)
+	FUNC2(decal_set_extents, RID, const Vector3 &)
+	FUNC3(decal_set_texture, RID, DecalTexture, RID)
+	FUNC2(decal_set_emission_energy, RID, float)
+	FUNC2(decal_set_albedo_mix, RID, float)
+	FUNC2(decal_set_modulate, RID, const Color &)
+	FUNC2(decal_set_cull_mask, RID, uint32_t)
+	FUNC4(decal_set_distance_fade, RID, bool, float, float)
+	FUNC3(decal_set_fade, RID, float, float)
+	FUNC2(decal_set_normal_fade, RID, float)
 
 	/* BAKED LIGHT API */
 
-	BIND0R(RID, gi_probe_create)
+	FUNCRIDSPLIT(gi_probe)
 
-	BIND8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
+	FUNC8(gi_probe_allocate_data, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
 
-	BIND1RC(AABB, gi_probe_get_bounds, RID)
-	BIND1RC(Vector3i, gi_probe_get_octree_size, RID)
-	BIND1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
-	BIND1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
-	BIND1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
-	BIND1RC(Vector<int>, gi_probe_get_level_counts, RID)
-	BIND1RC(Transform, gi_probe_get_to_cell_xform, RID)
+	FUNC1RC(AABB, gi_probe_get_bounds, RID)
+	FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
+	FUNC1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
+	FUNC1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
+	FUNC1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
+	FUNC1RC(Vector<int>, gi_probe_get_level_counts, RID)
+	FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
 
-	BIND2(gi_probe_set_dynamic_range, RID, float)
-	BIND1RC(float, gi_probe_get_dynamic_range, RID)
+	FUNC2(gi_probe_set_dynamic_range, RID, float)
+	FUNC1RC(float, gi_probe_get_dynamic_range, RID)
 
-	BIND2(gi_probe_set_propagation, RID, float)
-	BIND1RC(float, gi_probe_get_propagation, RID)
+	FUNC2(gi_probe_set_propagation, RID, float)
+	FUNC1RC(float, gi_probe_get_propagation, RID)
 
-	BIND2(gi_probe_set_energy, RID, float)
-	BIND1RC(float, gi_probe_get_energy, RID)
+	FUNC2(gi_probe_set_energy, RID, float)
+	FUNC1RC(float, gi_probe_get_energy, RID)
 
-	BIND2(gi_probe_set_ao, RID, float)
-	BIND1RC(float, gi_probe_get_ao, RID)
+	FUNC2(gi_probe_set_ao, RID, float)
+	FUNC1RC(float, gi_probe_get_ao, RID)
 
-	BIND2(gi_probe_set_ao_size, RID, float)
-	BIND1RC(float, gi_probe_get_ao_size, RID)
+	FUNC2(gi_probe_set_ao_size, RID, float)
+	FUNC1RC(float, gi_probe_get_ao_size, RID)
 
-	BIND2(gi_probe_set_bias, RID, float)
-	BIND1RC(float, gi_probe_get_bias, RID)
+	FUNC2(gi_probe_set_bias, RID, float)
+	FUNC1RC(float, gi_probe_get_bias, RID)
 
-	BIND2(gi_probe_set_normal_bias, RID, float)
-	BIND1RC(float, gi_probe_get_normal_bias, RID)
+	FUNC2(gi_probe_set_normal_bias, RID, float)
+	FUNC1RC(float, gi_probe_get_normal_bias, RID)
 
-	BIND2(gi_probe_set_interior, RID, bool)
-	BIND1RC(bool, gi_probe_is_interior, RID)
+	FUNC2(gi_probe_set_interior, RID, bool)
+	FUNC1RC(bool, gi_probe_is_interior, RID)
 
-	BIND2(gi_probe_set_use_two_bounces, RID, bool)
-	BIND1RC(bool, gi_probe_is_using_two_bounces, RID)
+	FUNC2(gi_probe_set_use_two_bounces, RID, bool)
+	FUNC1RC(bool, gi_probe_is_using_two_bounces, RID)
 
-	BIND2(gi_probe_set_anisotropy_strength, RID, float)
-	BIND1RC(float, gi_probe_get_anisotropy_strength, RID)
+	FUNC2(gi_probe_set_anisotropy_strength, RID, float)
+	FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
 
 	/* LIGHTMAP */
 
-	BIND0R(RID, lightmap_create)
+	FUNCRIDSPLIT(lightmap)
 
-	BIND3(lightmap_set_textures, RID, RID, bool)
-	BIND2(lightmap_set_probe_bounds, RID, const AABB &)
-	BIND2(lightmap_set_probe_interior, RID, bool)
-	BIND5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
-	BIND1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
-	BIND1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
-	BIND1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
-	BIND1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
-	BIND1(lightmap_set_probe_capture_update_speed, float)
+	FUNC3(lightmap_set_textures, RID, RID, bool)
+	FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
+	FUNC2(lightmap_set_probe_interior, RID, bool)
+	FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+	FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
+	FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
+	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
+	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
+	FUNC1(lightmap_set_probe_capture_update_speed, float)
 
 	/* PARTICLES */
 
-	BIND0R(RID, particles_create)
-
-	BIND2(particles_set_emitting, RID, bool)
-	BIND1R(bool, particles_get_emitting, RID)
-	BIND2(particles_set_amount, RID, int)
-	BIND2(particles_set_lifetime, RID, float)
-	BIND2(particles_set_one_shot, RID, bool)
-	BIND2(particles_set_pre_process_time, RID, float)
-	BIND2(particles_set_explosiveness_ratio, RID, float)
-	BIND2(particles_set_randomness_ratio, RID, float)
-	BIND2(particles_set_custom_aabb, RID, const AABB &)
-	BIND2(particles_set_speed_scale, RID, float)
-	BIND2(particles_set_use_local_coordinates, RID, bool)
-	BIND2(particles_set_process_material, RID, RID)
-	BIND2(particles_set_fixed_fps, RID, int)
-	BIND2(particles_set_fractional_delta, RID, bool)
-	BIND1R(bool, particles_is_inactive, RID)
-	BIND1(particles_request_process, RID)
-	BIND1(particles_restart, RID)
-	BIND6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t)
-	BIND2(particles_set_subemitter, RID, RID)
-	BIND2(particles_set_collision_base_size, RID, float)
-
-	BIND2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
-
-	BIND2(particles_set_draw_passes, RID, int)
-	BIND3(particles_set_draw_pass_mesh, RID, int, RID)
-
-	BIND1R(AABB, particles_get_current_aabb, RID)
-	BIND2(particles_set_emission_transform, RID, const Transform &)
+	FUNCRIDSPLIT(particles)
+
+	FUNC2(particles_set_emitting, RID, bool)
+	FUNC1R(bool, particles_get_emitting, RID)
+	FUNC2(particles_set_amount, RID, int)
+	FUNC2(particles_set_lifetime, RID, float)
+	FUNC2(particles_set_one_shot, RID, bool)
+	FUNC2(particles_set_pre_process_time, RID, float)
+	FUNC2(particles_set_explosiveness_ratio, RID, float)
+	FUNC2(particles_set_randomness_ratio, RID, float)
+	FUNC2(particles_set_custom_aabb, RID, const AABB &)
+	FUNC2(particles_set_speed_scale, RID, float)
+	FUNC2(particles_set_use_local_coordinates, RID, bool)
+	FUNC2(particles_set_process_material, RID, RID)
+	FUNC2(particles_set_fixed_fps, RID, int)
+	FUNC2(particles_set_fractional_delta, RID, bool)
+	FUNC1R(bool, particles_is_inactive, RID)
+	FUNC1(particles_request_process, RID)
+	FUNC1(particles_restart, RID)
+	FUNC6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t)
+	FUNC2(particles_set_subemitter, RID, RID)
+	FUNC2(particles_set_collision_base_size, RID, float)
+
+	FUNC2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
+
+	FUNC2(particles_set_draw_passes, RID, int)
+	FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
+
+	FUNC1R(AABB, particles_get_current_aabb, RID)
+	FUNC2(particles_set_emission_transform, RID, const Transform &)
 
 	/* PARTICLES COLLISION */
 
-	BIND0R(RID, particles_collision_create)
-
-	BIND2(particles_collision_set_collision_type, RID, ParticlesCollisionType)
-	BIND2(particles_collision_set_cull_mask, RID, uint32_t)
-	BIND2(particles_collision_set_sphere_radius, RID, float)
-	BIND2(particles_collision_set_box_extents, RID, const Vector3 &)
-	BIND2(particles_collision_set_attractor_strength, RID, float)
-	BIND2(particles_collision_set_attractor_directionality, RID, float)
-	BIND2(particles_collision_set_attractor_attenuation, RID, float)
-	BIND2(particles_collision_set_field_texture, RID, RID)
-	BIND1(particles_collision_height_field_update, RID)
-	BIND2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
-
-#undef BINDBASE
+	FUNCRIDSPLIT(particles_collision)
+
+	FUNC2(particles_collision_set_collision_type, RID, ParticlesCollisionType)
+	FUNC2(particles_collision_set_cull_mask, RID, uint32_t)
+	FUNC2(particles_collision_set_sphere_radius, RID, float)
+	FUNC2(particles_collision_set_box_extents, RID, const Vector3 &)
+	FUNC2(particles_collision_set_attractor_strength, RID, float)
+	FUNC2(particles_collision_set_attractor_directionality, RID, float)
+	FUNC2(particles_collision_set_attractor_attenuation, RID, float)
+	FUNC2(particles_collision_set_field_texture, RID, RID)
+	FUNC1(particles_collision_height_field_update, RID)
+	FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
+
+#undef server_name
+#undef ServerName
 //from now on, calls forwarded to this singleton
-#define BINDBASE RSG::scene
+#define ServerName RendererScene
+#define server_name RSG::scene
 
 	/* CAMERA API */
 
-	BIND0R(RID, camera_create)
-	BIND4(camera_set_perspective, RID, float, float, float)
-	BIND4(camera_set_orthogonal, RID, float, float, float)
-	BIND5(camera_set_frustum, RID, float, Vector2, float, float)
-	BIND2(camera_set_transform, RID, const Transform &)
-	BIND2(camera_set_cull_mask, RID, uint32_t)
-	BIND2(camera_set_environment, RID, RID)
-	BIND2(camera_set_camera_effects, RID, RID)
-	BIND2(camera_set_use_vertical_aspect, RID, bool)
-
-#undef BINDBASE
+	FUNCRIDSPLIT(camera)
+	FUNC4(camera_set_perspective, RID, float, float, float)
+	FUNC4(camera_set_orthogonal, RID, float, float, float)
+	FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
+	FUNC2(camera_set_transform, RID, const Transform &)
+	FUNC2(camera_set_cull_mask, RID, uint32_t)
+	FUNC2(camera_set_environment, RID, RID)
+	FUNC2(camera_set_camera_effects, RID, RID)
+	FUNC2(camera_set_use_vertical_aspect, RID, bool)
+
+#undef server_name
+#undef ServerName
 //from now on, calls forwarded to this singleton
-#define BINDBASE RSG::viewport
+#define ServerName RendererViewport
+#define server_name RSG::viewport
 
 	/* VIEWPORT TARGET API */
 
-	BIND0R(RID, viewport_create)
+	FUNCRIDSPLIT(viewport)
 
-	BIND2(viewport_set_use_xr, RID, bool)
-	BIND3(viewport_set_size, RID, int, int)
+	FUNC2(viewport_set_use_xr, RID, bool)
+	FUNC3(viewport_set_size, RID, int, int)
 
-	BIND2(viewport_set_active, RID, bool)
-	BIND2(viewport_set_parent_viewport, RID, RID)
+	FUNC2(viewport_set_active, RID, bool)
+	FUNC2(viewport_set_parent_viewport, RID, RID)
 
-	BIND2(viewport_set_clear_mode, RID, ViewportClearMode)
+	FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
 
-	BIND3(viewport_attach_to_screen, RID, const Rect2 &, int)
-	BIND2(viewport_set_render_direct_to_screen, RID, bool)
+	FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
+	FUNC2(viewport_set_render_direct_to_screen, RID, bool)
 
-	BIND2(viewport_set_update_mode, RID, ViewportUpdateMode)
-	BIND2(viewport_set_vflip, RID, bool)
+	FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
 
-	BIND1RC(RID, viewport_get_texture, RID)
+	FUNC1RC(RID, viewport_get_texture, RID)
 
-	BIND2(viewport_set_hide_scenario, RID, bool)
-	BIND2(viewport_set_hide_canvas, RID, bool)
-	BIND2(viewport_set_disable_environment, RID, bool)
+	FUNC2(viewport_set_hide_scenario, RID, bool)
+	FUNC2(viewport_set_hide_canvas, RID, bool)
+	FUNC2(viewport_set_disable_environment, RID, bool)
 
-	BIND2(viewport_attach_camera, RID, RID)
-	BIND2(viewport_set_scenario, RID, RID)
-	BIND2(viewport_attach_canvas, RID, RID)
+	FUNC2(viewport_attach_camera, RID, RID)
+	FUNC2(viewport_set_scenario, RID, RID)
+	FUNC2(viewport_attach_canvas, RID, RID)
 
-	BIND2(viewport_remove_canvas, RID, RID)
-	BIND3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
-	BIND2(viewport_set_transparent_background, RID, bool)
-	BIND2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
-	BIND2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
+	FUNC2(viewport_remove_canvas, RID, RID)
+	FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
+	FUNC2(viewport_set_transparent_background, RID, bool)
+	FUNC2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
+	FUNC2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
 
-	BIND2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
-	BIND2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
+	FUNC2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
+	FUNC2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
 
-	BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
-	BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
-	BIND3(viewport_set_shadow_atlas_size, RID, int, bool)
-	BIND3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
-	BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
-	BIND2(viewport_set_msaa, RID, ViewportMSAA)
-	BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
-	BIND2(viewport_set_use_debanding, RID, bool)
-	BIND2(viewport_set_lod_threshold, RID, float)
+	FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
+	FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
+	FUNC3(viewport_set_shadow_atlas_size, RID, int, bool)
+	FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
+	FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
+	FUNC2(viewport_set_msaa, RID, ViewportMSAA)
+	FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
+	FUNC2(viewport_set_use_debanding, RID, bool)
+	FUNC2(viewport_set_lod_threshold, RID, float)
 
-	BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
-	BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
+	FUNC2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
+	FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
 
-	BIND2(viewport_set_measure_render_time, RID, bool)
-	BIND1RC(float, viewport_get_measured_render_time_cpu, RID)
-	BIND1RC(float, viewport_get_measured_render_time_gpu, RID)
+	FUNC2(viewport_set_measure_render_time, RID, bool)
+	FUNC1RC(float, viewport_get_measured_render_time_cpu, RID)
+	FUNC1RC(float, viewport_get_measured_render_time_gpu, RID)
+
+	FUNC1(call_set_use_vsync, bool)
 
 	/* ENVIRONMENT API */
 
-#undef BINDBASE
+#undef server_name
+#undef ServerName
 //from now on, calls forwarded to this singleton
-#define BINDBASE RSG::scene
+#define ServerName RendererScene
+#define server_name RSG::scene
 
-	BIND2(directional_shadow_atlas_set_size, int, bool)
-	BIND1(gi_probe_set_quality, GIProbeQuality)
+	FUNC2(directional_shadow_atlas_set_size, int, bool)
+	FUNC1(gi_probe_set_quality, GIProbeQuality)
 
 	/* SKY API */
 
-	BIND0R(RID, sky_create)
-	BIND2(sky_set_radiance_size, RID, int)
-	BIND2(sky_set_mode, RID, SkyMode)
-	BIND2(sky_set_material, RID, RID)
-	BIND4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
+	FUNCRIDSPLIT(sky)
+	FUNC2(sky_set_radiance_size, RID, int)
+	FUNC2(sky_set_mode, RID, SkyMode)
+	FUNC2(sky_set_material, RID, RID)
+	FUNC4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
 
-	BIND0R(RID, environment_create)
+	FUNCRIDSPLIT(environment)
 
-	BIND2(environment_set_background, RID, EnvironmentBG)
-	BIND2(environment_set_sky, RID, RID)
-	BIND2(environment_set_sky_custom_fov, RID, float)
-	BIND2(environment_set_sky_orientation, RID, const Basis &)
-	BIND2(environment_set_bg_color, RID, const Color &)
-	BIND2(environment_set_bg_energy, RID, float)
-	BIND2(environment_set_canvas_max_layer, RID, int)
-	BIND7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
+	FUNC2(environment_set_background, RID, EnvironmentBG)
+	FUNC2(environment_set_sky, RID, RID)
+	FUNC2(environment_set_sky_custom_fov, RID, float)
+	FUNC2(environment_set_sky_orientation, RID, const Basis &)
+	FUNC2(environment_set_bg_color, RID, const Color &)
+	FUNC2(environment_set_bg_energy, RID, float)
+	FUNC2(environment_set_canvas_max_layer, RID, int)
+	FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
 
 // FIXME: Disabled during Vulkan refactoring, should be ported.
 #if 0
-	BIND2(environment_set_camera_feed_id, RID, int)
+	FUNC2(environment_set_camera_feed_id, RID, int)
 #endif
-	BIND6(environment_set_ssr, RID, bool, int, float, float, float)
-	BIND1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
+	FUNC6(environment_set_ssr, RID, bool, int, float, float, float)
+	FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
 
-	BIND10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
-	BIND6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
+	FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
+	FUNC6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
 
-	BIND11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
-	BIND1(environment_glow_set_use_bicubic_upscale, bool)
-	BIND1(environment_glow_set_use_high_quality, bool)
+	FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
+	FUNC1(environment_glow_set_use_bicubic_upscale, bool)
+	FUNC1(environment_glow_set_use_high_quality, bool)
 
-	BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
+	FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
 
-	BIND7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
+	FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
 
-	BIND9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
-	BIND10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
+	FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
+	FUNC10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
 
-	BIND2(environment_set_volumetric_fog_volume_size, int, int)
-	BIND1(environment_set_volumetric_fog_filter_active, bool)
+	FUNC2(environment_set_volumetric_fog_volume_size, int, int)
+	FUNC1(environment_set_volumetric_fog_filter_active, bool)
 
-	BIND11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
-	BIND1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
-	BIND1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
-	BIND1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
+	FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
+	FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
+	FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
+	FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
 
-	BIND3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
+	FUNC3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
 
-	BIND3(screen_space_roughness_limiter_set_active, bool, float, float)
-	BIND1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
-	BIND2(sub_surface_scattering_set_scale, float, float)
+	FUNC3(screen_space_roughness_limiter_set_active, bool, float, float)
+	FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
+	FUNC2(sub_surface_scattering_set_scale, float, float)
 
 	/* CAMERA EFFECTS */
 
-	BIND0R(RID, camera_effects_create)
+	FUNCRIDSPLIT(camera_effects)
 
-	BIND2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
-	BIND1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
+	FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
+	FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
 
-	BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
-	BIND3(camera_effects_set_custom_exposure, RID, bool, float)
+	FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
+	FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
 
-	BIND1(shadows_quality_set, ShadowQuality);
-	BIND1(directional_shadow_quality_set, ShadowQuality);
+	FUNC1(shadows_quality_set, ShadowQuality);
+	FUNC1(directional_shadow_quality_set, ShadowQuality);
 
 	/* SCENARIO API */
 
-#undef BINDBASE
-#define BINDBASE RSG::scene
+#undef server_name
+#undef ServerName
+
+#define ServerName RendererScene
+#define server_name RSG::scene
 
-	BIND0R(RID, scenario_create)
+	FUNCRIDSPLIT(scenario)
 
-	BIND2(scenario_set_debug, RID, ScenarioDebugMode)
-	BIND2(scenario_set_environment, RID, RID)
-	BIND2(scenario_set_camera_effects, RID, RID)
-	BIND2(scenario_set_fallback_environment, RID, RID)
+	FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
+	FUNC2(scenario_set_environment, RID, RID)
+	FUNC2(scenario_set_camera_effects, RID, RID)
+	FUNC2(scenario_set_fallback_environment, RID, RID)
 
 	/* INSTANCING API */
-	BIND0R(RID, instance_create)
+	FUNCRIDSPLIT(instance)
 
-	BIND2(instance_set_base, RID, RID)
-	BIND2(instance_set_scenario, RID, RID)
-	BIND2(instance_set_layer_mask, RID, uint32_t)
-	BIND2(instance_set_transform, RID, const Transform &)
-	BIND2(instance_attach_object_instance_id, RID, ObjectID)
-	BIND3(instance_set_blend_shape_weight, RID, int, float)
-	BIND3(instance_set_surface_material, RID, int, RID)
-	BIND2(instance_set_visible, RID, bool)
+	FUNC2(instance_set_base, RID, RID)
+	FUNC2(instance_set_scenario, RID, RID)
+	FUNC2(instance_set_layer_mask, RID, uint32_t)
+	FUNC2(instance_set_transform, RID, const Transform &)
+	FUNC2(instance_attach_object_instance_id, RID, ObjectID)
+	FUNC3(instance_set_blend_shape_weight, RID, int, float)
+	FUNC3(instance_set_surface_material, RID, int, RID)
+	FUNC2(instance_set_visible, RID, bool)
 
-	BIND2(instance_set_custom_aabb, RID, AABB)
+	FUNC2(instance_set_custom_aabb, RID, AABB)
 
-	BIND2(instance_attach_skeleton, RID, RID)
-	BIND2(instance_set_exterior, RID, bool)
+	FUNC2(instance_attach_skeleton, RID, RID)
+	FUNC2(instance_set_exterior, RID, bool)
 
-	BIND2(instance_set_extra_visibility_margin, RID, real_t)
+	FUNC2(instance_set_extra_visibility_margin, RID, real_t)
 
 	// don't use these in a game!
-	BIND2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
-	BIND3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
-	BIND2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
+	FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
+	FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
+	FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
 
-	BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool)
-	BIND2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
-	BIND2(instance_geometry_set_material_override, RID, RID)
+	FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
+	FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
+	FUNC2(instance_geometry_set_material_override, RID, RID)
 
-	BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
-	BIND2(instance_geometry_set_as_instance_lod, RID, RID)
-	BIND4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
-	BIND2(instance_geometry_set_lod_bias, RID, float)
+	FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
+	FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
+	FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
+	FUNC2(instance_geometry_set_lod_bias, RID, float)
 
-	BIND3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
-	BIND2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
-	BIND2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
-	BIND2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
+	FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
+	FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
+	FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
+	FUNC2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
 
-	BIND3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
+	FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
 
-	BIND1(gi_set_use_half_resolution, bool)
+	FUNC1(gi_set_use_half_resolution, bool)
 
-#undef BINDBASE
+#undef server_name
+#undef ServerName
 //from now on, calls forwarded to this singleton
-#define BINDBASE RSG::canvas
+#define ServerName RendererCanvasCull
+#define server_name RSG::canvas
 
 	/* CANVAS (2D) */
 
-	BIND0R(RID, canvas_create)
-	BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &)
-	BIND2(canvas_set_modulate, RID, const Color &)
-	BIND3(canvas_set_parent, RID, RID, float)
-	BIND1(canvas_set_disable_scale, bool)
-
-	BIND0R(RID, canvas_texture_create)
-	BIND3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID)
-	BIND3(canvas_texture_set_shading_parameters, RID, const Color &, float)
-
-	BIND2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter)
-	BIND2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat)
-
-	BIND0R(RID, canvas_item_create)
-	BIND2(canvas_item_set_parent, RID, RID)
-
-	BIND2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
-	BIND2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
-
-	BIND2(canvas_item_set_visible, RID, bool)
-	BIND2(canvas_item_set_light_mask, RID, int)
-
-	BIND2(canvas_item_set_update_when_visible, RID, bool)
-
-	BIND2(canvas_item_set_transform, RID, const Transform2D &)
-	BIND2(canvas_item_set_clip, RID, bool)
-	BIND2(canvas_item_set_distance_field_mode, RID, bool)
-	BIND3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
-	BIND2(canvas_item_set_modulate, RID, const Color &)
-	BIND2(canvas_item_set_self_modulate, RID, const Color &)
-
-	BIND2(canvas_item_set_draw_behind_parent, RID, bool)
-
-	BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
-	BIND5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
-	BIND4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
-	BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
-	BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
-	BIND6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
-	BIND7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
-	BIND10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
-	BIND6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
-	BIND5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
-	BIND9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int)
-	BIND5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID)
-	BIND3(canvas_item_add_multimesh, RID, RID, RID)
-	BIND3(canvas_item_add_particles, RID, RID, RID)
-	BIND2(canvas_item_add_set_transform, RID, const Transform2D &)
-	BIND2(canvas_item_add_clip_ignore, RID, bool)
-	BIND2(canvas_item_set_sort_children_by_y, RID, bool)
-	BIND2(canvas_item_set_z_index, RID, int)
-	BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool)
-	BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
-	BIND2(canvas_item_attach_skeleton, RID, RID)
-
-	BIND1(canvas_item_clear, RID)
-	BIND2(canvas_item_set_draw_index, RID, int)
-
-	BIND2(canvas_item_set_material, RID, RID)
-
-	BIND2(canvas_item_set_use_parent_material, RID, bool)
-
-	BIND6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
-
-	BIND0R(RID, canvas_light_create)
-
-	BIND2(canvas_light_set_mode, RID, CanvasLightMode)
-
-	BIND2(canvas_light_attach_to_canvas, RID, RID)
-	BIND2(canvas_light_set_enabled, RID, bool)
-	BIND2(canvas_light_set_texture_scale, RID, float)
-	BIND2(canvas_light_set_transform, RID, const Transform2D &)
-	BIND2(canvas_light_set_texture, RID, RID)
-	BIND2(canvas_light_set_texture_offset, RID, const Vector2 &)
-	BIND2(canvas_light_set_color, RID, const Color &)
-	BIND2(canvas_light_set_height, RID, float)
-	BIND2(canvas_light_set_energy, RID, float)
-	BIND3(canvas_light_set_z_range, RID, int, int)
-	BIND3(canvas_light_set_layer_range, RID, int, int)
-	BIND2(canvas_light_set_item_cull_mask, RID, int)
-	BIND2(canvas_light_set_item_shadow_cull_mask, RID, int)
-	BIND2(canvas_light_set_directional_distance, RID, float)
-
-	BIND2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
-
-	BIND2(canvas_light_set_shadow_enabled, RID, bool)
-	BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
-	BIND2(canvas_light_set_shadow_color, RID, const Color &)
-	BIND2(canvas_light_set_shadow_smooth, RID, float)
-
-	BIND0R(RID, canvas_light_occluder_create)
-	BIND2(canvas_light_occluder_attach_to_canvas, RID, RID)
-	BIND2(canvas_light_occluder_set_enabled, RID, bool)
-	BIND2(canvas_light_occluder_set_polygon, RID, RID)
-	BIND2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
-	BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &)
-	BIND2(canvas_light_occluder_set_light_mask, RID, int)
-
-	BIND0R(RID, canvas_occluder_polygon_create)
-	BIND3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
-
-	BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
-
-	BIND1(canvas_set_shadow_texture_size, int)
+	FUNCRIDSPLIT(canvas)
+	FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
+	FUNC2(canvas_set_modulate, RID, const Color &)
+	FUNC3(canvas_set_parent, RID, RID, float)
+	FUNC1(canvas_set_disable_scale, bool)
+
+	FUNCRIDSPLIT(canvas_texture)
+	FUNC3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID)
+	FUNC3(canvas_texture_set_shading_parameters, RID, const Color &, float)
+
+	FUNC2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter)
+	FUNC2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat)
+
+	FUNCRIDSPLIT(canvas_item)
+	FUNC2(canvas_item_set_parent, RID, RID)
+
+	FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
+	FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
+
+	FUNC2(canvas_item_set_visible, RID, bool)
+	FUNC2(canvas_item_set_light_mask, RID, int)
+
+	FUNC2(canvas_item_set_update_when_visible, RID, bool)
+
+	FUNC2(canvas_item_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_item_set_clip, RID, bool)
+	FUNC2(canvas_item_set_distance_field_mode, RID, bool)
+	FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
+	FUNC2(canvas_item_set_modulate, RID, const Color &)
+	FUNC2(canvas_item_set_self_modulate, RID, const Color &)
+
+	FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
+
+	FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
+	FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
+	FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
+	FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
+	FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
+	FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
+	FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
+	FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
+	FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
+	FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
+	FUNC9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int)
+	FUNC5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID)
+	FUNC3(canvas_item_add_multimesh, RID, RID, RID)
+	FUNC3(canvas_item_add_particles, RID, RID, RID)
+	FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_item_add_clip_ignore, RID, bool)
+	FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
+	FUNC2(canvas_item_set_z_index, RID, int)
+	FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
+	FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
+	FUNC2(canvas_item_attach_skeleton, RID, RID)
+
+	FUNC1(canvas_item_clear, RID)
+	FUNC2(canvas_item_set_draw_index, RID, int)
+
+	FUNC2(canvas_item_set_material, RID, RID)
+
+	FUNC2(canvas_item_set_use_parent_material, RID, bool)
+
+	FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
+
+	FUNCRIDSPLIT(canvas_light)
+
+	FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
+
+	FUNC2(canvas_light_attach_to_canvas, RID, RID)
+	FUNC2(canvas_light_set_enabled, RID, bool)
+	FUNC2(canvas_light_set_texture_scale, RID, float)
+	FUNC2(canvas_light_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_light_set_texture, RID, RID)
+	FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
+	FUNC2(canvas_light_set_color, RID, const Color &)
+	FUNC2(canvas_light_set_height, RID, float)
+	FUNC2(canvas_light_set_energy, RID, float)
+	FUNC3(canvas_light_set_z_range, RID, int, int)
+	FUNC3(canvas_light_set_layer_range, RID, int, int)
+	FUNC2(canvas_light_set_item_cull_mask, RID, int)
+	FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
+	FUNC2(canvas_light_set_directional_distance, RID, float)
+
+	FUNC2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
+
+	FUNC2(canvas_light_set_shadow_enabled, RID, bool)
+	FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
+	FUNC2(canvas_light_set_shadow_color, RID, const Color &)
+	FUNC2(canvas_light_set_shadow_smooth, RID, float)
+
+	FUNCRIDSPLIT(canvas_light_occluder)
+	FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
+	FUNC2(canvas_light_occluder_set_enabled, RID, bool)
+	FUNC2(canvas_light_occluder_set_polygon, RID, RID)
+	FUNC2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
+	FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_light_occluder_set_light_mask, RID, int)
+
+	FUNCRIDSPLIT(canvas_occluder_polygon)
+	FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
+
+	FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
+
+	FUNC1(canvas_set_shadow_texture_size, int)
 
 	/* GLOBAL VARIABLES */
 
-#undef BINDBASE
+#undef server_name
+#undef ServerName
 //from now on, calls forwarded to this singleton
-#define BINDBASE RSG::storage
+#define ServerName RendererStorage
+#define server_name RSG::storage
 
-	BIND3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
-	BIND1(global_variable_remove, const StringName &)
-	BIND0RC(Vector<StringName>, global_variable_get_list)
-	BIND2(global_variable_set, const StringName &, const Variant &)
-	BIND2(global_variable_set_override, const StringName &, const Variant &)
-	BIND1RC(GlobalVariableType, global_variable_get_type, const StringName &)
-	BIND1RC(Variant, global_variable_get, const StringName &)
+	FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
+	FUNC1(global_variable_remove, const StringName &)
+	FUNC0RC(Vector<StringName>, global_variable_get_list)
+	FUNC2(global_variable_set, const StringName &, const Variant &)
+	FUNC2(global_variable_set_override, const StringName &, const Variant &)
+	FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
+	FUNC1RC(Variant, global_variable_get, const StringName &)
 
-	BIND1(global_variables_load_settings, bool)
-	BIND0(global_variables_clear)
+	FUNC1(global_variables_load_settings, bool)
+	FUNC0(global_variables_clear)
+
+#undef server_name
+#undef ServerName
+#undef WRITE_ACTION
+#undef SYNC_DEBUG
 
 	/* BLACK BARS */
 
-	virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
-	virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom);
+	virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) override;
+	virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) override;
 
 	/* FREE */
 
-	virtual void free(RID p_rid); ///< free RIDs associated with the visual server
+	virtual void free(RID p_rid) override {
+		if (Thread::get_caller_id() == server_thread) {
+			command_queue.flush_if_pending();
+			_free(p_rid);
+		} else {
+			command_queue.push(this, &RenderingServerDefault::_free, p_rid);
+		}
+	}
 
 	/* EVENT QUEUING */
 
-	virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata);
+	virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) override;
 
-	virtual void draw(bool p_swap_buffers, double frame_step);
-	virtual void sync();
-	virtual bool has_changed() const;
-	virtual void init();
-	virtual void finish();
+	virtual void draw(bool p_swap_buffers, double frame_step) override;
+	virtual void sync() override;
+	virtual bool has_changed() const override;
+	virtual void init() override;
+	virtual void finish() override;
 
 	/* STATUS INFORMATION */
 
-	virtual int get_render_info(RenderInfo p_info);
-	virtual String get_video_adapter_name() const;
-	virtual String get_video_adapter_vendor() const;
+	virtual int get_render_info(RenderInfo p_info) override;
+	virtual String get_video_adapter_name() const override;
+	virtual String get_video_adapter_vendor() const override;
 
-	virtual void set_frame_profiling_enabled(bool p_enable);
-	virtual Vector<FrameProfileArea> get_frame_profile();
-	virtual uint64_t get_frame_profile_frame();
+	virtual void set_frame_profiling_enabled(bool p_enable) override;
+	virtual Vector<FrameProfileArea> get_frame_profile() override;
+	virtual uint64_t get_frame_profile_frame() override;
 
-	virtual RID get_test_cube();
+	virtual RID get_test_cube() override;
 
 	/* TESTING */
 
-	virtual float get_frame_setup_time_cpu() const;
-
-	virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true);
-	virtual void set_default_clear_color(const Color &p_color);
+	virtual float get_frame_setup_time_cpu() const override;
 
-	virtual bool has_feature(Features p_feature) const;
+	virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override;
+	virtual void set_default_clear_color(const Color &p_color) override;
 
-	virtual bool has_os_feature(const String &p_feature) const;
-	virtual void set_debug_generate_wireframes(bool p_generate);
+	virtual bool has_feature(Features p_feature) const override;
 
-	virtual void call_set_use_vsync(bool p_enable);
+	virtual bool has_os_feature(const String &p_feature) const override;
+	virtual void set_debug_generate_wireframes(bool p_generate) override;
 
-	virtual bool is_low_end() const;
+	virtual bool is_low_end() const override;
 
-	virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
+	virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
 
-	virtual void set_print_gpu_profile(bool p_enable);
+	virtual void set_print_gpu_profile(bool p_enable) override;
 
-	RenderingServerDefault();
+	RenderingServerDefault(bool p_create_thread = false);
 	~RenderingServerDefault();
-
-#undef DISPLAY_CHANGED
-
-#undef BIND0R
-#undef BIND1RC
-#undef BIND2RC
-#undef BIND3RC
-#undef BIND4RC
-
-#undef BIND1
-#undef BIND2
-#undef BIND3
-#undef BIND4
-#undef BIND5
-#undef BIND6
-#undef BIND7
-#undef BIND8
-#undef BIND9
-#undef BIND10
 };
 
 #endif

+ 0 - 174
servers/rendering/rendering_server_wrap_mt.cpp

@@ -1,174 +0,0 @@
-/*************************************************************************/
-/*  rendering_server_wrap_mt.cpp                                         */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#include "rendering_server_wrap_mt.h"
-#include "core/config/project_settings.h"
-#include "core/os/os.h"
-#include "servers/display_server.h"
-
-void RenderingServerWrapMT::thread_exit() {
-	exit = true;
-}
-
-void RenderingServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) {
-	if (!atomic_decrement(&draw_pending)) {
-		rendering_server->draw(p_swap_buffers, frame_step);
-	}
-}
-
-void RenderingServerWrapMT::thread_flush() {
-	atomic_decrement(&draw_pending);
-}
-
-void RenderingServerWrapMT::_thread_callback(void *_instance) {
-	RenderingServerWrapMT *vsmt = reinterpret_cast<RenderingServerWrapMT *>(_instance);
-
-	vsmt->thread_loop();
-}
-
-void RenderingServerWrapMT::thread_loop() {
-	server_thread = Thread::get_caller_id();
-
-	DisplayServer::get_singleton()->make_rendering_thread();
-
-	rendering_server->init();
-
-	exit = false;
-	draw_thread_up = true;
-	while (!exit) {
-		// flush commands one by one, until exit is requested
-		command_queue.wait_and_flush_one();
-	}
-
-	command_queue.flush_all(); // flush all
-
-	rendering_server->finish();
-}
-
-/* EVENT QUEUING */
-
-void RenderingServerWrapMT::sync() {
-	if (create_thread) {
-		atomic_increment(&draw_pending);
-		command_queue.push_and_sync(this, &RenderingServerWrapMT::thread_flush);
-	} else {
-		command_queue.flush_all(); //flush all pending from other threads
-	}
-}
-
-void RenderingServerWrapMT::draw(bool p_swap_buffers, double frame_step) {
-	if (create_thread) {
-		atomic_increment(&draw_pending);
-		command_queue.push(this, &RenderingServerWrapMT::thread_draw, p_swap_buffers, frame_step);
-	} else {
-		rendering_server->draw(p_swap_buffers, frame_step);
-	}
-}
-
-void RenderingServerWrapMT::init() {
-	if (create_thread) {
-		print_verbose("RenderingServerWrapMT: Creating render thread");
-		DisplayServer::get_singleton()->release_rendering_thread();
-		if (create_thread) {
-			thread.start(_thread_callback, this);
-			print_verbose("RenderingServerWrapMT: Starting render thread");
-		}
-		while (!draw_thread_up) {
-			OS::get_singleton()->delay_usec(1000);
-		}
-		print_verbose("RenderingServerWrapMT: Finished render thread");
-	} else {
-		rendering_server->init();
-	}
-}
-
-void RenderingServerWrapMT::finish() {
-	sky_free_cached_ids();
-	shader_free_cached_ids();
-	material_free_cached_ids();
-	mesh_free_cached_ids();
-	multimesh_free_cached_ids();
-	immediate_free_cached_ids();
-	skeleton_free_cached_ids();
-	directional_light_free_cached_ids();
-	omni_light_free_cached_ids();
-	spot_light_free_cached_ids();
-	reflection_probe_free_cached_ids();
-	gi_probe_free_cached_ids();
-	lightmap_free_cached_ids();
-	particles_free_cached_ids();
-	particles_collision_free_cached_ids();
-	camera_free_cached_ids();
-	viewport_free_cached_ids();
-	environment_free_cached_ids();
-	camera_effects_free_cached_ids();
-	scenario_free_cached_ids();
-	instance_free_cached_ids();
-	canvas_free_cached_ids();
-	canvas_item_free_cached_ids();
-	canvas_light_occluder_free_cached_ids();
-	canvas_occluder_polygon_free_cached_ids();
-
-	if (create_thread) {
-		command_queue.push(this, &RenderingServerWrapMT::thread_exit);
-		thread.wait_to_finish();
-	} else {
-		rendering_server->finish();
-	}
-}
-
-void RenderingServerWrapMT::set_use_vsync_callback(bool p_enable) {
-	singleton_mt->call_set_use_vsync(p_enable);
-}
-
-RenderingServerWrapMT *RenderingServerWrapMT::singleton_mt = nullptr;
-
-RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread) :
-		command_queue(p_create_thread) {
-	singleton_mt = this;
-	DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly
-
-	rendering_server = p_contained;
-	create_thread = p_create_thread;
-	draw_pending = 0;
-	draw_thread_up = false;
-	pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
-
-	if (!p_create_thread) {
-		server_thread = Thread::get_caller_id();
-	} else {
-		server_thread = 0;
-	}
-}
-
-RenderingServerWrapMT::~RenderingServerWrapMT() {
-	memdelete(rendering_server);
-	//finish();
-}

+ 0 - 808
servers/rendering/rendering_server_wrap_mt.h

@@ -1,808 +0,0 @@
-/*************************************************************************/
-/*  rendering_server_wrap_mt.h                                           */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#ifndef RENDERING_SERVER_WRAP_MT_H
-#define RENDERING_SERVER_WRAP_MT_H
-
-#include "core/os/thread.h"
-#include "core/templates/command_queue_mt.h"
-#include "servers/rendering_server.h"
-
-class RenderingServerWrapMT : public RenderingServer {
-	// the real visual server
-	mutable RenderingServer *rendering_server;
-
-	mutable CommandQueueMT command_queue;
-
-	static void _thread_callback(void *_instance);
-	void thread_loop();
-
-	Thread::ID server_thread;
-	volatile bool exit;
-	Thread thread;
-	volatile bool draw_thread_up;
-	bool create_thread;
-
-	uint64_t draw_pending;
-	void thread_draw(bool p_swap_buffers, double frame_step);
-	void thread_flush();
-
-	void thread_exit();
-
-	Mutex alloc_mutex;
-
-	int pool_max_size;
-
-	//#define DEBUG_SYNC
-
-	static RenderingServerWrapMT *singleton_mt;
-
-#ifdef DEBUG_SYNC
-#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
-#else
-#define SYNC_DEBUG
-#endif
-
-public:
-#define ServerName RenderingServer
-#define ServerNameWrapMT RenderingServerWrapMT
-#define server_name rendering_server
-#include "servers/server_wrap_mt_common.h"
-
-	//these go pass-through, as they can be called from any thread
-	virtual RID texture_2d_create(const Ref<Image> &p_image) { return rendering_server->texture_2d_create(p_image); }
-	virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, TextureLayeredType p_layered_type) { return rendering_server->texture_2d_layered_create(p_layers, p_layered_type); }
-	virtual RID texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { return rendering_server->texture_3d_create(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); }
-	virtual RID texture_proxy_create(RID p_base) { return rendering_server->texture_proxy_create(p_base); }
-
-	//goes pass-through
-	virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) { rendering_server->texture_2d_update_immediate(p_texture, p_image, p_layer); }
-	//these go through command queue if they are in another thread
-	FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
-	FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)
-	FUNC2(texture_proxy_update, RID, RID)
-
-	//these also go pass-through
-	virtual RID texture_2d_placeholder_create() { return rendering_server->texture_2d_placeholder_create(); }
-	virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_type) { return rendering_server->texture_2d_layered_placeholder_create(p_type); }
-	virtual RID texture_3d_placeholder_create() { return rendering_server->texture_3d_placeholder_create(); }
-
-	FUNC1RC(Ref<Image>, texture_2d_get, RID)
-	FUNC2RC(Ref<Image>, texture_2d_layer_get, RID, int)
-	FUNC1RC(Vector<Ref<Image>>, texture_3d_get, RID)
-
-	FUNC2(texture_replace, RID, RID)
-
-	FUNC3(texture_set_size_override, RID, int, int)
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
-	FUNC2(texture_bind, RID, uint32_t)
-#endif
-
-	FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
-	FUNC3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
-	FUNC3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
-
-	FUNC2(texture_set_path, RID, const String &)
-	FUNC1RC(String, texture_get_path, RID)
-	FUNC1S(texture_debug_usage, List<TextureInfo> *)
-
-	FUNC2(texture_set_force_redraw_if_visible, RID, bool)
-
-	/* SHADER API */
-
-	FUNCRID(shader)
-
-	FUNC2(shader_set_code, RID, const String &)
-	FUNC1RC(String, shader_get_code, RID)
-
-	FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
-
-	FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
-	FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
-	FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
-
-	FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
-
-	/* COMMON MATERIAL API */
-
-	FUNCRID(material)
-
-	FUNC2(material_set_shader, RID, RID)
-
-	FUNC3(material_set_param, RID, const StringName &, const Variant &)
-	FUNC2RC(Variant, material_get_param, RID, const StringName &)
-
-	FUNC2(material_set_render_priority, RID, int)
-	FUNC2(material_set_next_pass, RID, RID)
-
-	/* MESH API */
-
-	virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) {
-		return rendering_server->mesh_create_from_surfaces(p_surfaces, p_blend_shape_count);
-	}
-
-	FUNC2(mesh_set_blend_shape_count, RID, int)
-
-	FUNCRID(mesh)
-
-	FUNC2(mesh_add_surface, RID, const SurfaceData &)
-
-	FUNC1RC(int, mesh_get_blend_shape_count, RID)
-
-	FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
-	FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
-
-	FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
-
-	FUNC3(mesh_surface_set_material, RID, int, RID)
-	FUNC2RC(RID, mesh_surface_get_material, RID, int)
-
-	FUNC2RC(SurfaceData, mesh_get_surface, RID, int)
-
-	FUNC1RC(int, mesh_get_surface_count, RID)
-
-	FUNC2(mesh_set_custom_aabb, RID, const AABB &)
-	FUNC1RC(AABB, mesh_get_custom_aabb, RID)
-
-	FUNC2(mesh_set_shadow_mesh, RID, RID)
-	FUNC1(mesh_clear, RID)
-
-	/* MULTIMESH API */
-
-	FUNCRID(multimesh)
-
-	FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
-	FUNC1RC(int, multimesh_get_instance_count, RID)
-
-	FUNC2(multimesh_set_mesh, RID, RID)
-	FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
-	FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
-	FUNC3(multimesh_instance_set_color, RID, int, const Color &)
-	FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &)
-
-	FUNC1RC(RID, multimesh_get_mesh, RID)
-	FUNC1RC(AABB, multimesh_get_aabb, RID)
-
-	FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
-	FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
-	FUNC2RC(Color, multimesh_instance_get_color, RID, int)
-	FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
-
-	FUNC2(multimesh_set_buffer, RID, const Vector<float> &)
-	FUNC1RC(Vector<float>, multimesh_get_buffer, RID)
-
-	FUNC2(multimesh_set_visible_instances, RID, int)
-	FUNC1RC(int, multimesh_get_visible_instances, RID)
-
-	/* IMMEDIATE API */
-
-	FUNCRID(immediate)
-	FUNC3(immediate_begin, RID, PrimitiveType, RID)
-	FUNC2(immediate_vertex, RID, const Vector3 &)
-	FUNC2(immediate_normal, RID, const Vector3 &)
-	FUNC2(immediate_tangent, RID, const Plane &)
-	FUNC2(immediate_color, RID, const Color &)
-	FUNC2(immediate_uv, RID, const Vector2 &)
-	FUNC2(immediate_uv2, RID, const Vector2 &)
-	FUNC1(immediate_end, RID)
-	FUNC1(immediate_clear, RID)
-	FUNC2(immediate_set_material, RID, RID)
-	FUNC1RC(RID, immediate_get_material, RID)
-
-	/* SKELETON API */
-
-	FUNCRID(skeleton)
-	FUNC3(skeleton_allocate, RID, int, bool)
-	FUNC1RC(int, skeleton_get_bone_count, RID)
-	FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
-	FUNC2RC(Transform, skeleton_bone_get_transform, RID, int)
-	FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
-	FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
-	FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
-
-	/* Light API */
-
-	FUNCRID(directional_light)
-	FUNCRID(omni_light)
-	FUNCRID(spot_light)
-
-	FUNC2(light_set_color, RID, const Color &)
-	FUNC3(light_set_param, RID, LightParam, float)
-	FUNC2(light_set_shadow, RID, bool)
-	FUNC2(light_set_shadow_color, RID, const Color &)
-	FUNC2(light_set_projector, RID, RID)
-	FUNC2(light_set_negative, RID, bool)
-	FUNC2(light_set_cull_mask, RID, uint32_t)
-	FUNC2(light_set_reverse_cull_face_mode, RID, bool)
-	FUNC2(light_set_bake_mode, RID, LightBakeMode)
-	FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
-
-	FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
-
-	FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
-	FUNC2(light_directional_set_blend_splits, RID, bool)
-	FUNC2(light_directional_set_sky_only, RID, bool)
-	FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
-
-	/* PROBE API */
-
-	FUNCRID(reflection_probe)
-
-	FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
-	FUNC2(reflection_probe_set_intensity, RID, float)
-	FUNC2(reflection_probe_set_ambient_color, RID, const Color &)
-	FUNC2(reflection_probe_set_ambient_energy, RID, float)
-	FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode)
-	FUNC2(reflection_probe_set_max_distance, RID, float)
-	FUNC2(reflection_probe_set_extents, RID, const Vector3 &)
-	FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &)
-	FUNC2(reflection_probe_set_as_interior, RID, bool)
-	FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
-	FUNC2(reflection_probe_set_enable_shadows, RID, bool)
-	FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
-	FUNC2(reflection_probe_set_resolution, RID, int)
-	FUNC2(reflection_probe_set_lod_threshold, RID, float)
-
-	/* DECAL API */
-
-	FUNCRID(decal)
-
-	FUNC2(decal_set_extents, RID, const Vector3 &)
-	FUNC3(decal_set_texture, RID, DecalTexture, RID)
-	FUNC2(decal_set_emission_energy, RID, float)
-	FUNC2(decal_set_albedo_mix, RID, float)
-	FUNC2(decal_set_modulate, RID, const Color &)
-	FUNC2(decal_set_cull_mask, RID, uint32_t)
-	FUNC4(decal_set_distance_fade, RID, bool, float, float)
-	FUNC3(decal_set_fade, RID, float, float)
-	FUNC2(decal_set_normal_fade, RID, float)
-
-	/* BAKED LIGHT API */
-
-	FUNCRID(gi_probe)
-
-	FUNC8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
-
-	FUNC1RC(AABB, gi_probe_get_bounds, RID)
-	FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
-	FUNC1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
-	FUNC1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
-	FUNC1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
-	FUNC1RC(Vector<int>, gi_probe_get_level_counts, RID)
-	FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
-
-	FUNC2(gi_probe_set_dynamic_range, RID, float)
-	FUNC1RC(float, gi_probe_get_dynamic_range, RID)
-
-	FUNC2(gi_probe_set_propagation, RID, float)
-	FUNC1RC(float, gi_probe_get_propagation, RID)
-
-	FUNC2(gi_probe_set_energy, RID, float)
-	FUNC1RC(float, gi_probe_get_energy, RID)
-
-	FUNC2(gi_probe_set_ao, RID, float)
-	FUNC1RC(float, gi_probe_get_ao, RID)
-
-	FUNC2(gi_probe_set_ao_size, RID, float)
-	FUNC1RC(float, gi_probe_get_ao_size, RID)
-
-	FUNC2(gi_probe_set_bias, RID, float)
-	FUNC1RC(float, gi_probe_get_bias, RID)
-
-	FUNC2(gi_probe_set_normal_bias, RID, float)
-	FUNC1RC(float, gi_probe_get_normal_bias, RID)
-
-	FUNC2(gi_probe_set_interior, RID, bool)
-	FUNC1RC(bool, gi_probe_is_interior, RID)
-
-	FUNC2(gi_probe_set_use_two_bounces, RID, bool)
-	FUNC1RC(bool, gi_probe_is_using_two_bounces, RID)
-
-	FUNC2(gi_probe_set_anisotropy_strength, RID, float)
-	FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
-
-	FUNC1(gi_probe_set_quality, GIProbeQuality)
-
-	/* LIGHTMAP CAPTURE */
-
-	FUNCRID(lightmap)
-	FUNC3(lightmap_set_textures, RID, RID, bool)
-	FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
-	FUNC2(lightmap_set_probe_interior, RID, bool)
-	FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
-	FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
-	FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
-	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
-	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
-
-	FUNC1(lightmap_set_probe_capture_update_speed, float)
-
-	/* PARTICLES */
-
-	FUNCRID(particles)
-
-	FUNC2(particles_set_emitting, RID, bool)
-	FUNC1R(bool, particles_get_emitting, RID)
-	FUNC2(particles_set_amount, RID, int)
-	FUNC2(particles_set_lifetime, RID, float)
-	FUNC2(particles_set_one_shot, RID, bool)
-	FUNC2(particles_set_pre_process_time, RID, float)
-	FUNC2(particles_set_explosiveness_ratio, RID, float)
-	FUNC2(particles_set_randomness_ratio, RID, float)
-	FUNC2(particles_set_custom_aabb, RID, const AABB &)
-	FUNC2(particles_set_speed_scale, RID, float)
-	FUNC2(particles_set_use_local_coordinates, RID, bool)
-	FUNC2(particles_set_process_material, RID, RID)
-	FUNC2(particles_set_fixed_fps, RID, int)
-	FUNC2(particles_set_fractional_delta, RID, bool)
-	FUNC2(particles_set_collision_base_size, RID, float)
-
-	FUNC1R(bool, particles_is_inactive, RID)
-	FUNC1(particles_request_process, RID)
-	FUNC1(particles_restart, RID)
-
-	FUNC6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t)
-
-	FUNC2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
-
-	FUNC2(particles_set_draw_passes, RID, int)
-	FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
-	FUNC2(particles_set_emission_transform, RID, const Transform &)
-	FUNC2(particles_set_subemitter, RID, RID)
-
-	FUNC1R(AABB, particles_get_current_aabb, RID)
-
-	/* PARTICLES COLLISION */
-
-	FUNCRID(particles_collision)
-
-	FUNC2(particles_collision_set_collision_type, RID, ParticlesCollisionType)
-	FUNC2(particles_collision_set_cull_mask, RID, uint32_t)
-	FUNC2(particles_collision_set_sphere_radius, RID, float)
-	FUNC2(particles_collision_set_box_extents, RID, const Vector3 &)
-	FUNC2(particles_collision_set_attractor_strength, RID, float)
-	FUNC2(particles_collision_set_attractor_directionality, RID, float)
-	FUNC2(particles_collision_set_attractor_attenuation, RID, float)
-	FUNC2(particles_collision_set_field_texture, RID, RID)
-	FUNC1(particles_collision_height_field_update, RID)
-	FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
-
-	/* CAMERA API */
-
-	FUNCRID(camera)
-	FUNC4(camera_set_perspective, RID, float, float, float)
-	FUNC4(camera_set_orthogonal, RID, float, float, float)
-	FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
-	FUNC2(camera_set_transform, RID, const Transform &)
-	FUNC2(camera_set_cull_mask, RID, uint32_t)
-	FUNC2(camera_set_environment, RID, RID)
-	FUNC2(camera_set_camera_effects, RID, RID)
-	FUNC2(camera_set_use_vertical_aspect, RID, bool)
-
-	/* VIEWPORT TARGET API */
-
-	FUNCRID(viewport)
-
-	FUNC2(viewport_set_use_xr, RID, bool)
-
-	FUNC3(viewport_set_size, RID, int, int)
-
-	FUNC2(viewport_set_active, RID, bool)
-	FUNC2(viewport_set_parent_viewport, RID, RID)
-
-	FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
-
-	FUNC3(viewport_attach_to_screen, RID, const Rect2 &, DisplayServer::WindowID)
-	FUNC2(viewport_set_render_direct_to_screen, RID, bool)
-
-	FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
-
-	FUNC1RC(RID, viewport_get_texture, RID)
-
-	FUNC2(viewport_set_hide_scenario, RID, bool)
-	FUNC2(viewport_set_hide_canvas, RID, bool)
-	FUNC2(viewport_set_disable_environment, RID, bool)
-
-	FUNC2(viewport_attach_camera, RID, RID)
-	FUNC2(viewport_set_scenario, RID, RID)
-	FUNC2(viewport_attach_canvas, RID, RID)
-
-	FUNC2(viewport_remove_canvas, RID, RID)
-	FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
-	FUNC2(viewport_set_transparent_background, RID, bool)
-	FUNC2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
-	FUNC2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
-
-	FUNC2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
-	FUNC2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
-
-	FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
-	FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
-	FUNC3(viewport_set_shadow_atlas_size, RID, int, bool)
-	FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
-
-	FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
-	FUNC2(viewport_set_msaa, RID, ViewportMSAA)
-	FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
-	FUNC2(viewport_set_use_debanding, RID, bool)
-
-	FUNC2(viewport_set_lod_threshold, RID, float)
-
-	//this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport
-	virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) {
-		return rendering_server->viewport_get_render_info(p_viewport, p_info);
-	}
-
-	FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
-
-	FUNC2(viewport_set_measure_render_time, RID, bool)
-	virtual float viewport_get_measured_render_time_cpu(RID p_viewport) const {
-		return rendering_server->viewport_get_measured_render_time_cpu(p_viewport);
-	}
-	virtual float viewport_get_measured_render_time_gpu(RID p_viewport) const {
-		return rendering_server->viewport_get_measured_render_time_gpu(p_viewport);
-	}
-
-	FUNC2(directional_shadow_atlas_set_size, int, bool)
-
-	/* SKY API */
-
-	FUNCRID(sky)
-	FUNC2(sky_set_radiance_size, RID, int)
-	FUNC2(sky_set_mode, RID, SkyMode)
-	FUNC2(sky_set_material, RID, RID)
-	FUNC4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
-
-	/* ENVIRONMENT API */
-
-	FUNCRID(environment)
-
-	FUNC2(environment_set_background, RID, EnvironmentBG)
-	FUNC2(environment_set_sky, RID, RID)
-	FUNC2(environment_set_sky_custom_fov, RID, float)
-	FUNC2(environment_set_sky_orientation, RID, const Basis &)
-	FUNC2(environment_set_bg_color, RID, const Color &)
-	FUNC2(environment_set_bg_energy, RID, float)
-	FUNC2(environment_set_canvas_max_layer, RID, int)
-	FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
-
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
-	FUNC2(environment_set_camera_feed_id, RID, int)
-#endif
-	FUNC6(environment_set_ssr, RID, bool, int, float, float, float)
-	FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
-
-	FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
-
-	FUNC6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
-
-	FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
-	FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
-	FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
-	FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
-
-	FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
-	FUNC1(environment_glow_set_use_bicubic_upscale, bool)
-	FUNC1(environment_glow_set_use_high_quality, bool)
-
-	FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
-
-	FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
-
-	FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
-
-	FUNC10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
-
-	FUNC2(environment_set_volumetric_fog_volume_size, int, int)
-	FUNC1(environment_set_volumetric_fog_filter_active, bool)
-
-	FUNC3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
-
-	FUNC3(screen_space_roughness_limiter_set_active, bool, float, float)
-	FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
-	FUNC2(sub_surface_scattering_set_scale, float, float)
-
-	FUNCRID(camera_effects)
-
-	FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
-	FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
-
-	FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
-	FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
-
-	FUNC1(shadows_quality_set, ShadowQuality);
-	FUNC1(directional_shadow_quality_set, ShadowQuality);
-
-	FUNCRID(scenario)
-
-	FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
-	FUNC2(scenario_set_environment, RID, RID)
-	FUNC2(scenario_set_camera_effects, RID, RID)
-	FUNC2(scenario_set_fallback_environment, RID, RID)
-
-	/* INSTANCING API */
-	FUNCRID(instance)
-
-	FUNC2(instance_set_base, RID, RID)
-	FUNC2(instance_set_scenario, RID, RID)
-	FUNC2(instance_set_layer_mask, RID, uint32_t)
-	FUNC2(instance_set_transform, RID, const Transform &)
-	FUNC2(instance_attach_object_instance_id, RID, ObjectID)
-	FUNC3(instance_set_blend_shape_weight, RID, int, float)
-	FUNC3(instance_set_surface_material, RID, int, RID)
-	FUNC2(instance_set_visible, RID, bool)
-
-	FUNC2(instance_set_custom_aabb, RID, AABB)
-
-	FUNC2(instance_attach_skeleton, RID, RID)
-	FUNC2(instance_set_exterior, RID, bool)
-
-	FUNC2(instance_set_extra_visibility_margin, RID, real_t)
-
-	// don't use these in a game!
-	FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
-	FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
-	FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
-
-	FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
-	FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
-	FUNC2(instance_geometry_set_material_override, RID, RID)
-
-	FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
-	FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
-	FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
-	FUNC2(instance_geometry_set_lod_bias, RID, float)
-
-	FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
-	FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
-	FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
-	FUNC2SC(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
-
-	/* BAKE */
-
-	FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
-
-	/* CANVAS (2D) */
-
-	FUNCRID(canvas)
-	FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
-	FUNC2(canvas_set_modulate, RID, const Color &)
-	FUNC3(canvas_set_parent, RID, RID, float)
-	FUNC1(canvas_set_disable_scale, bool)
-
-	FUNCRID(canvas_texture)
-	FUNC3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID)
-	FUNC3(canvas_texture_set_shading_parameters, RID, const Color &, float)
-
-	FUNC2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter)
-	FUNC2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat)
-
-	FUNCRID(canvas_item)
-	FUNC2(canvas_item_set_parent, RID, RID)
-
-	FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
-	FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
-
-	FUNC2(canvas_item_set_visible, RID, bool)
-	FUNC2(canvas_item_set_light_mask, RID, int)
-
-	FUNC2(canvas_item_set_update_when_visible, RID, bool)
-
-	FUNC2(canvas_item_set_transform, RID, const Transform2D &)
-	FUNC2(canvas_item_set_clip, RID, bool)
-	FUNC2(canvas_item_set_distance_field_mode, RID, bool)
-	FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
-	FUNC2(canvas_item_set_modulate, RID, const Color &)
-	FUNC2(canvas_item_set_self_modulate, RID, const Color &)
-
-	FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
-
-	FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
-	FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
-	FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
-	FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
-	FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
-	FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
-	FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
-	FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
-	FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
-	FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
-	FUNC9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int)
-	FUNC5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID)
-	FUNC3(canvas_item_add_multimesh, RID, RID, RID)
-	FUNC3(canvas_item_add_particles, RID, RID, RID)
-	FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
-	FUNC2(canvas_item_add_clip_ignore, RID, bool)
-	FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
-	FUNC2(canvas_item_set_z_index, RID, int)
-	FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
-	FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
-	FUNC2(canvas_item_attach_skeleton, RID, RID)
-
-	FUNC1(canvas_item_clear, RID)
-	FUNC2(canvas_item_set_draw_index, RID, int)
-
-	FUNC2(canvas_item_set_material, RID, RID)
-
-	FUNC2(canvas_item_set_use_parent_material, RID, bool)
-
-	FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
-
-	FUNC0R(RID, canvas_light_create)
-
-	FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
-
-	FUNC2(canvas_light_attach_to_canvas, RID, RID)
-	FUNC2(canvas_light_set_enabled, RID, bool)
-	FUNC2(canvas_light_set_texture_scale, RID, float)
-	FUNC2(canvas_light_set_transform, RID, const Transform2D &)
-	FUNC2(canvas_light_set_texture, RID, RID)
-	FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
-	FUNC2(canvas_light_set_color, RID, const Color &)
-	FUNC2(canvas_light_set_height, RID, float)
-	FUNC2(canvas_light_set_energy, RID, float)
-	FUNC3(canvas_light_set_z_range, RID, int, int)
-	FUNC3(canvas_light_set_layer_range, RID, int, int)
-	FUNC2(canvas_light_set_item_cull_mask, RID, int)
-	FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
-	FUNC2(canvas_light_set_directional_distance, RID, float)
-
-	FUNC2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
-
-	FUNC2(canvas_light_set_shadow_enabled, RID, bool)
-	FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
-	FUNC2(canvas_light_set_shadow_color, RID, const Color &)
-	FUNC2(canvas_light_set_shadow_smooth, RID, float)
-
-	FUNCRID(canvas_light_occluder)
-	FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
-	FUNC2(canvas_light_occluder_set_enabled, RID, bool)
-	FUNC2(canvas_light_occluder_set_polygon, RID, RID)
-	FUNC2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
-	FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
-	FUNC2(canvas_light_occluder_set_light_mask, RID, int)
-
-	FUNCRID(canvas_occluder_polygon)
-	FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
-
-	FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
-
-	FUNC1(canvas_set_shadow_texture_size, int)
-
-	/* GLOBAL VARIABLES */
-
-	FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
-	FUNC1(global_variable_remove, const StringName &)
-	FUNC0RC(Vector<StringName>, global_variable_get_list)
-	FUNC2(global_variable_set, const StringName &, const Variant &)
-	FUNC2(global_variable_set_override, const StringName &, const Variant &)
-	FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
-	FUNC1RC(Variant, global_variable_get, const StringName &)
-	FUNC1(global_variables_load_settings, bool)
-	FUNC0(global_variables_clear)
-
-	/* BLACK BARS */
-
-	FUNC4(black_bars_set_margins, int, int, int, int)
-	FUNC4(black_bars_set_images, RID, RID, RID, RID)
-
-	/* FREE */
-
-	FUNC1(free, RID)
-
-	/* EVENT QUEUING */
-
-	FUNC3(request_frame_drawn_callback, Object *, const StringName &, const Variant &)
-
-	virtual void init();
-	virtual void finish();
-	virtual void draw(bool p_swap_buffers, double frame_step);
-	virtual void sync();
-	FUNC0RC(bool, has_changed)
-
-	/* RENDER INFO */
-
-	//this passes directly to avoid stalling
-	virtual int get_render_info(RenderInfo p_info) {
-		return rendering_server->get_render_info(p_info);
-	}
-
-	virtual String get_video_adapter_name() const {
-		return rendering_server->get_video_adapter_name();
-	}
-
-	virtual String get_video_adapter_vendor() const {
-		return rendering_server->get_video_adapter_vendor();
-	}
-
-	FUNC1(gi_set_use_half_resolution, bool)
-
-	FUNC4(set_boot_image, const Ref<Image> &, const Color &, bool, bool)
-	FUNC1(set_default_clear_color, const Color &)
-
-	FUNC0R(RID, get_test_cube)
-
-	FUNC1(set_debug_generate_wireframes, bool)
-
-	virtual bool has_feature(Features p_feature) const {
-		return rendering_server->has_feature(p_feature);
-	}
-	virtual bool has_os_feature(const String &p_feature) const {
-		return rendering_server->has_os_feature(p_feature);
-	}
-
-	FUNC1(call_set_use_vsync, bool)
-
-	static void set_use_vsync_callback(bool p_enable);
-
-	virtual bool is_low_end() const {
-		return rendering_server->is_low_end();
-	}
-
-	virtual uint64_t get_frame_profile_frame() {
-		return rendering_server->get_frame_profile_frame();
-	}
-
-	virtual void set_frame_profiling_enabled(bool p_enabled) {
-		rendering_server->set_frame_profiling_enabled(p_enabled);
-	}
-
-	virtual Vector<FrameProfileArea> get_frame_profile() {
-		return rendering_server->get_frame_profile();
-	}
-
-	virtual float get_frame_setup_time_cpu() const {
-		return rendering_server->get_frame_setup_time_cpu();
-	}
-
-	virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
-		rendering_server->sdfgi_set_debug_probe_select(p_position, p_dir);
-	}
-
-	virtual void set_print_gpu_profile(bool p_enable) {
-		rendering_server->set_print_gpu_profile(p_enable);
-	}
-
-	RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread);
-	~RenderingServerWrapMT();
-
-#undef ServerName
-#undef ServerNameWrapMT
-#undef server_name
-};
-
-#ifdef DEBUG_SYNC
-#undef DEBUG_SYNC
-#endif
-#undef SYNC_DEBUG
-
-#endif

+ 2 - 2
servers/rendering_server.cpp

@@ -1489,7 +1489,7 @@ void RenderingServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &RenderingServer::mesh_clear);
 
 	ClassDB::bind_method(D_METHOD("multimesh_create"), &RenderingServer::multimesh_create);
-	ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::multimesh_allocate, DEFVAL(false), DEFVAL(false));
+	ClassDB::bind_method(D_METHOD("multimesh_allocate_data", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::multimesh_allocate_data, DEFVAL(false), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &RenderingServer::multimesh_get_instance_count);
 	ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &RenderingServer::multimesh_set_mesh);
 	ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &RenderingServer::multimesh_instance_set_transform);
@@ -1523,7 +1523,7 @@ void RenderingServer::_bind_methods() {
 #endif
 
 	ClassDB::bind_method(D_METHOD("skeleton_create"), &RenderingServer::skeleton_create);
-	ClassDB::bind_method(D_METHOD("skeleton_allocate", "skeleton", "bones", "is_2d_skeleton"), &RenderingServer::skeleton_allocate, DEFVAL(false));
+	ClassDB::bind_method(D_METHOD("skeleton_allocate_data", "skeleton", "bones", "is_2d_skeleton"), &RenderingServer::skeleton_allocate_data, DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("skeleton_get_bone_count", "skeleton"), &RenderingServer::skeleton_get_bone_count);
 	ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform", "skeleton", "bone", "transform"), &RenderingServer::skeleton_bone_set_transform);
 	ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform", "skeleton", "bone"), &RenderingServer::skeleton_bone_get_transform);

+ 3 - 3
servers/rendering_server.h

@@ -367,7 +367,7 @@ public:
 		MULTIMESH_TRANSFORM_3D,
 	};
 
-	virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+	virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
 	virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
 
 	virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
@@ -409,7 +409,7 @@ public:
 	/* SKELETON API */
 
 	virtual RID skeleton_create() = 0;
-	virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
+	virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
 	virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
 	virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0;
 	virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
@@ -552,7 +552,7 @@ public:
 
 	virtual RID gi_probe_create() = 0;
 
-	virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
+	virtual void gi_probe_allocate_data(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
 
 	virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
 	virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;

+ 395 - 465
servers/server_wrap_mt_common.h

@@ -29,245 +29,89 @@
 /*************************************************************************/
 
 #define FUNC0R(m_r, m_type)                                                     \
-	virtual m_r m_type() {                                                      \
+	virtual m_r m_type() override {                                             \
 		if (Thread::get_caller_id() != server_thread) {                         \
 			m_r ret;                                                            \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
 			SYNC_DEBUG                                                          \
 			return ret;                                                         \
 		} else {                                                                \
+			command_queue.flush_if_pending();                                   \
 			return server_name->m_type();                                       \
 		}                                                                       \
 	}
 
-#define FUNCRID(m_type)                                                                    \
-	List<RID> m_type##_id_pool;                                                            \
-	int m_type##allocn() {                                                                 \
-		for (int i = 0; i < pool_max_size; i++) {                                          \
-			m_type##_id_pool.push_back(server_name->m_type##_create());                    \
-		}                                                                                  \
-		return 0;                                                                          \
-	}                                                                                      \
-	void m_type##_free_cached_ids() {                                                      \
-		while (m_type##_id_pool.size()) {                                                  \
-			server_name->free(m_type##_id_pool.front()->get());                            \
-			m_type##_id_pool.pop_front();                                                  \
-		}                                                                                  \
-	}                                                                                      \
-	virtual RID m_type##_create() {                                                        \
-		if (Thread::get_caller_id() != server_thread) {                                    \
-			RID rid;                                                                       \
-			MutexLock lock(alloc_mutex);                                                   \
-			if (m_type##_id_pool.size() == 0) {                                            \
-				int ret;                                                                   \
-				command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, &ret); \
-				SYNC_DEBUG                                                                 \
-			}                                                                              \
-			rid = m_type##_id_pool.front()->get();                                         \
-			m_type##_id_pool.pop_front();                                                  \
-			return rid;                                                                    \
-		} else {                                                                           \
-			return server_name->m_type##_create();                                         \
-		}                                                                                  \
-	}
-
-#define FUNC1RID(m_type, m_arg1)                                                               \
-	int m_type##allocn() {                                                                     \
-		for (int i = 0; i < m_type##_pool_max_size; i++) {                                     \
-			m_type##_id_pool.push_back(server_name->m_type##_create());                        \
-		}                                                                                      \
-		return 0;                                                                              \
-	}                                                                                          \
-	void m_type##_free_cached_ids() {                                                          \
-		while (m_type##_id_pool.size()) {                                                      \
-			free(m_type##_id_pool.front()->get());                                             \
-			m_type##_id_pool.pop_front();                                                      \
-		}                                                                                      \
-	}                                                                                          \
-	virtual RID m_type##_create(m_arg1 p1) {                                                   \
-		if (Thread::get_caller_id() != server_thread) {                                        \
-			RID rid;                                                                           \
-			MutexLock lock(alloc_mutex);                                                       \
-			if (m_type##_id_pool.size() == 0) {                                                \
-				int ret;                                                                       \
-				command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, &ret); \
-				SYNC_DEBUG                                                                     \
-			}                                                                                  \
-			rid = m_type##_id_pool.front()->get();                                             \
-			m_type##_id_pool.pop_front();                                                      \
-			return rid;                                                                        \
-		} else {                                                                               \
-			return server_name->m_type##_create(p1);                                           \
-		}                                                                                      \
-	}
-
-#define FUNC2RID(m_type, m_arg1, m_arg2)                                                           \
-	int m_type##allocn() {                                                                         \
-		for (int i = 0; i < m_type##_pool_max_size; i++) {                                         \
-			m_type##_id_pool.push_back(server_name->m_type##_create());                            \
-		}                                                                                          \
-		return 0;                                                                                  \
-	}                                                                                              \
-	void m_type##_free_cached_ids() {                                                              \
-		while (m_type##_id_pool.size()) {                                                          \
-			free(m_type##_id_pool.front()->get());                                                 \
-			m_type##_id_pool.pop_front();                                                          \
-		}                                                                                          \
-	}                                                                                              \
-	virtual RID m_type##_create(m_arg1 p1, m_arg2 p2) {                                            \
-		if (Thread::get_caller_id() != server_thread) {                                            \
-			RID rid;                                                                               \
-			MutexLock lock(alloc_mutex);                                                           \
-			if (m_type##_id_pool.size() == 0) {                                                    \
-				int ret;                                                                           \
-				command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, &ret); \
-				SYNC_DEBUG                                                                         \
-			}                                                                                      \
-			rid = m_type##_id_pool.front()->get();                                                 \
-			m_type##_id_pool.pop_front();                                                          \
-			return rid;                                                                            \
-		} else {                                                                                   \
-			return server_name->m_type##_create(p1, p2);                                           \
-		}                                                                                          \
-	}
-
-#define FUNC3RID(m_type, m_arg1, m_arg2, m_arg3)                                                       \
-	int m_type##allocn() {                                                                             \
-		for (int i = 0; i < m_type##_pool_max_size; i++) {                                             \
-			m_type##_id_pool.push_back(server_name->m_type##_create());                                \
-		}                                                                                              \
-		return 0;                                                                                      \
-	}                                                                                                  \
-	void m_type##_free_cached_ids() {                                                                  \
-		while (m_type##_id_pool.size()) {                                                              \
-			free(m_type##_id_pool.front()->get());                                                     \
-			m_type##_id_pool.pop_front();                                                              \
-		}                                                                                              \
-	}                                                                                                  \
-	virtual RID m_type##_create(m_arg1 p1, m_arg2 p2, m_arg3 p3) {                                     \
-		if (Thread::get_caller_id() != server_thread) {                                                \
-			RID rid;                                                                                   \
-			MutexLock lock(alloc_mutex);                                                               \
-			if (m_type##_id_pool.size() == 0) {                                                        \
-				int ret;                                                                               \
-				command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, p3, &ret); \
-				SYNC_DEBUG                                                                             \
-			}                                                                                          \
-			rid = m_type##_id_pool.front()->get();                                                     \
-			m_type##_id_pool.pop_front();                                                              \
-			return rid;                                                                                \
-		} else {                                                                                       \
-			return server_name->m_type##_create(p1, p2, p3);                                           \
-		}                                                                                              \
-	}
-
-#define FUNC4RID(m_type, m_arg1, m_arg2, m_arg3, m_arg4)                                                   \
-	int m_type##allocn() {                                                                                 \
-		for (int i = 0; i < m_type##_pool_max_size; i++) {                                                 \
-			m_type##_id_pool.push_back(server_name->m_type##_create());                                    \
-		}                                                                                                  \
-		return 0;                                                                                          \
-	}                                                                                                      \
-	void m_type##_free_cached_ids() {                                                                      \
-		while (m_type##_id_pool.size()) {                                                                  \
-			free(m_type##_id_pool.front()->get());                                                         \
-			m_type##_id_pool.pop_front();                                                                  \
-		}                                                                                                  \
-	}                                                                                                      \
-	virtual RID m_type##_create(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) {                              \
-		if (Thread::get_caller_id() != server_thread) {                                                    \
-			RID rid;                                                                                       \
-			MutexLock lock(alloc_mutex);                                                                   \
-			if (m_type##_id_pool.size() == 0) {                                                            \
-				int ret;                                                                                   \
-				command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, p3, p4, &ret); \
-				SYNC_DEBUG                                                                                 \
-			}                                                                                              \
-			rid = m_type##_id_pool.front()->get();                                                         \
-			m_type##_id_pool.pop_front();                                                                  \
-			return rid;                                                                                    \
-		} else {                                                                                           \
-			return server_name->m_type##_create(p1, p2, p3, p4);                                           \
-		}                                                                                                  \
+#define FUNCRIDSPLIT(m_type)                                                        \
+	virtual RID m_type##_create() override {                                        \
+		RID ret = server_name->m_type##_allocate();                                 \
+		if (Thread::get_caller_id() != server_thread) {                             \
+			command_queue.push(server_name, &ServerName::m_type##_initialize, ret); \
+		} else {                                                                    \
+			server_name->m_type##_initialize(ret);                                  \
+		}                                                                           \
+		return ret;                                                                 \
 	}
 
-#define FUNC5RID(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                               \
-	List<RID> m_type##_id_pool;                                                                                \
-	int m_type##allocn(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) {                                \
-		for (int i = 0; i < pool_max_size; i++) {                                                              \
-			m_type##_id_pool.push_back(server_name->m_type##_create(p1, p2, p3, p4, p5));                      \
-		}                                                                                                      \
-		return 0;                                                                                              \
-	}                                                                                                          \
-	void m_type##_free_cached_ids() {                                                                          \
-		while (m_type##_id_pool.size()) {                                                                      \
-			free(m_type##_id_pool.front()->get());                                                             \
-			m_type##_id_pool.pop_front();                                                                      \
-		}                                                                                                      \
-	}                                                                                                          \
-	virtual RID m_type##_create(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) {                       \
-		if (Thread::get_caller_id() != server_thread) {                                                        \
-			RID rid;                                                                                           \
-			MutexLock lock(alloc_mutex);                                                                       \
-			if (m_type##_id_pool.size() == 0) {                                                                \
-				int ret;                                                                                       \
-				command_queue.push_and_ret(this, &ServerNameWrapMT::m_type##allocn, p1, p2, p3, p4, p5, &ret); \
-				SYNC_DEBUG                                                                                     \
-			}                                                                                                  \
-			rid = m_type##_id_pool.front()->get();                                                             \
-			m_type##_id_pool.pop_front();                                                                      \
-			return rid;                                                                                        \
-		} else {                                                                                               \
-			return server_name->m_type##_create(p1, p2, p3, p4, p5);                                           \
-		}                                                                                                      \
+//RID now returns directly, ensure thread safety yourself
+#define FUNCRID(m_type)                        \
+	virtual RID m_type##_create() override {   \
+		return server_name->m_type##_create(); \
 	}
 
 #define FUNC0RC(m_r, m_type)                                                    \
-	virtual m_r m_type() const {                                                \
+	virtual m_r m_type() const override {                                       \
+		WRITE_ACTION                                                            \
 		if (Thread::get_caller_id() != server_thread) {                         \
 			m_r ret;                                                            \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
 			SYNC_DEBUG                                                          \
 			return ret;                                                         \
 		} else {                                                                \
+			command_queue.flush_if_pending();                                   \
 			return server_name->m_type();                                       \
 		}                                                                       \
 	}
 
 #define FUNC0(m_type)                                             \
-	virtual void m_type() {                                       \
+	virtual void m_type() override {                              \
+		WRITE_ACTION                                              \
 		if (Thread::get_caller_id() != server_thread) {           \
 			command_queue.push(server_name, &ServerName::m_type); \
 		} else {                                                  \
+			command_queue.flush_if_pending();                     \
 			server_name->m_type();                                \
 		}                                                         \
 	}
 
 #define FUNC0C(m_type)                                            \
-	virtual void m_type() const {                                 \
+	virtual void m_type() const override {                        \
 		if (Thread::get_caller_id() != server_thread) {           \
 			command_queue.push(server_name, &ServerName::m_type); \
 		} else {                                                  \
+			command_queue.flush_if_pending();                     \
 			server_name->m_type();                                \
 		}                                                         \
 	}
 
 #define FUNC0S(m_type)                                                     \
-	virtual void m_type() {                                                \
+	virtual void m_type() override {                                       \
+		WRITE_ACTION                                                       \
 		if (Thread::get_caller_id() != server_thread) {                    \
 			command_queue.push_and_sync(server_name, &ServerName::m_type); \
 			SYNC_DEBUG                                                     \
 		} else {                                                           \
+			command_queue.flush_if_pending();                              \
 			server_name->m_type();                                         \
 		}                                                                  \
 	}
 
 #define FUNC0SC(m_type)                                                    \
-	virtual void m_type() const {                                          \
+	virtual void m_type() const override {                                 \
 		if (Thread::get_caller_id() != server_thread) {                    \
 			command_queue.push_and_sync(server_name, &ServerName::m_type); \
 			SYNC_DEBUG                                                     \
 		} else {                                                           \
+			command_queue.flush_if_pending();                              \
 			server_name->m_type();                                         \
 		}                                                                  \
 	}
@@ -275,560 +119,646 @@
 ///////////////////////////////////////////////
 
 #define FUNC1R(m_r, m_type, m_arg1)                                                 \
-	virtual m_r m_type(m_arg1 p1) {                                                 \
+	virtual m_r m_type(m_arg1 p1) override {                                        \
+		WRITE_ACTION                                                                \
 		if (Thread::get_caller_id() != server_thread) {                             \
 			m_r ret;                                                                \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
 			SYNC_DEBUG                                                              \
 			return ret;                                                             \
 		} else {                                                                    \
+			command_queue.flush_if_pending();                                       \
 			return server_name->m_type(p1);                                         \
 		}                                                                           \
 	}
 
 #define FUNC1RC(m_r, m_type, m_arg1)                                                \
-	virtual m_r m_type(m_arg1 p1) const {                                           \
+	virtual m_r m_type(m_arg1 p1) const override {                                  \
 		if (Thread::get_caller_id() != server_thread) {                             \
 			m_r ret;                                                                \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
 			SYNC_DEBUG                                                              \
 			return ret;                                                             \
 		} else {                                                                    \
+			command_queue.flush_if_pending();                                       \
 			return server_name->m_type(p1);                                         \
 		}                                                                           \
 	}
 
 #define FUNC1S(m_type, m_arg1)                                                 \
-	virtual void m_type(m_arg1 p1) {                                           \
+	virtual void m_type(m_arg1 p1) override {                                  \
+		WRITE_ACTION                                                           \
 		if (Thread::get_caller_id() != server_thread) {                        \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
 			SYNC_DEBUG                                                         \
 		} else {                                                               \
+			command_queue.flush_if_pending();                                  \
 			server_name->m_type(p1);                                           \
 		}                                                                      \
 	}
 
 #define FUNC1SC(m_type, m_arg1)                                                \
-	virtual void m_type(m_arg1 p1) const {                                     \
+	virtual void m_type(m_arg1 p1) const override {                            \
 		if (Thread::get_caller_id() != server_thread) {                        \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
 			SYNC_DEBUG                                                         \
 		} else {                                                               \
+			command_queue.flush_if_pending();                                  \
 			server_name->m_type(p1);                                           \
 		}                                                                      \
 	}
 
 #define FUNC1(m_type, m_arg1)                                         \
-	virtual void m_type(m_arg1 p1) {                                  \
+	virtual void m_type(m_arg1 p1) override {                         \
+		WRITE_ACTION                                                  \
 		if (Thread::get_caller_id() != server_thread) {               \
 			command_queue.push(server_name, &ServerName::m_type, p1); \
 		} else {                                                      \
+			command_queue.flush_if_pending();                         \
 			server_name->m_type(p1);                                  \
 		}                                                             \
 	}
 
 #define FUNC1C(m_type, m_arg1)                                        \
-	virtual void m_type(m_arg1 p1) const {                            \
+	virtual void m_type(m_arg1 p1) const override {                   \
 		if (Thread::get_caller_id() != server_thread) {               \
 			command_queue.push(server_name, &ServerName::m_type, p1); \
 		} else {                                                      \
+			command_queue.flush_if_pending();                         \
 			server_name->m_type(p1);                                  \
 		}                                                             \
 	}
 
 #define FUNC2R(m_r, m_type, m_arg1, m_arg2)                                             \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2) {                                          \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2) override {                                 \
+		WRITE_ACTION                                                                    \
 		if (Thread::get_caller_id() != server_thread) {                                 \
 			m_r ret;                                                                    \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
 			SYNC_DEBUG                                                                  \
 			return ret;                                                                 \
 		} else {                                                                        \
+			command_queue.flush_if_pending();                                           \
 			return server_name->m_type(p1, p2);                                         \
 		}                                                                               \
 	}
 
 #define FUNC2RC(m_r, m_type, m_arg1, m_arg2)                                            \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2) const {                                    \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2) const override {                           \
 		if (Thread::get_caller_id() != server_thread) {                                 \
 			m_r ret;                                                                    \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
 			SYNC_DEBUG                                                                  \
 			return ret;                                                                 \
 		} else {                                                                        \
+			command_queue.flush_if_pending();                                           \
 			return server_name->m_type(p1, p2);                                         \
 		}                                                                               \
 	}
 
 #define FUNC2S(m_type, m_arg1, m_arg2)                                             \
-	virtual void m_type(m_arg1 p1, m_arg2 p2) {                                    \
+	virtual void m_type(m_arg1 p1, m_arg2 p2) override {                           \
+		WRITE_ACTION                                                               \
 		if (Thread::get_caller_id() != server_thread) {                            \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
 			SYNC_DEBUG                                                             \
 		} else {                                                                   \
+			command_queue.flush_if_pending();                                      \
 			server_name->m_type(p1, p2);                                           \
 		}                                                                          \
 	}
 
 #define FUNC2SC(m_type, m_arg1, m_arg2)                                            \
-	virtual void m_type(m_arg1 p1, m_arg2 p2) const {                              \
+	virtual void m_type(m_arg1 p1, m_arg2 p2) const override {                     \
 		if (Thread::get_caller_id() != server_thread) {                            \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
 			SYNC_DEBUG                                                             \
 		} else {                                                                   \
+			command_queue.flush_if_pending();                                      \
 			server_name->m_type(p1, p2);                                           \
 		}                                                                          \
 	}
 
 #define FUNC2(m_type, m_arg1, m_arg2)                                     \
-	virtual void m_type(m_arg1 p1, m_arg2 p2) {                           \
+	virtual void m_type(m_arg1 p1, m_arg2 p2) override {                  \
+		WRITE_ACTION                                                      \
 		if (Thread::get_caller_id() != server_thread) {                   \
 			command_queue.push(server_name, &ServerName::m_type, p1, p2); \
 		} else {                                                          \
+			command_queue.flush_if_pending();                             \
 			server_name->m_type(p1, p2);                                  \
 		}                                                                 \
 	}
 
 #define FUNC2C(m_type, m_arg1, m_arg2)                                    \
-	virtual void m_type(m_arg1 p1, m_arg2 p2) const {                     \
+	virtual void m_type(m_arg1 p1, m_arg2 p2) const override {            \
 		if (Thread::get_caller_id() != server_thread) {                   \
 			command_queue.push(server_name, &ServerName::m_type, p1, p2); \
 		} else {                                                          \
+			command_queue.flush_if_pending();                             \
 			server_name->m_type(p1, p2);                                  \
 		}                                                                 \
 	}
 
 #define FUNC3R(m_r, m_type, m_arg1, m_arg2, m_arg3)                                         \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) {                                   \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) override {                          \
+		WRITE_ACTION                                                                        \
 		if (Thread::get_caller_id() != server_thread) {                                     \
 			m_r ret;                                                                        \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
 			SYNC_DEBUG                                                                      \
 			return ret;                                                                     \
 		} else {                                                                            \
+			command_queue.flush_if_pending();                                               \
 			return server_name->m_type(p1, p2, p3);                                         \
 		}                                                                                   \
 	}
 
 #define FUNC3RC(m_r, m_type, m_arg1, m_arg2, m_arg3)                                        \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const {                             \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const override {                    \
 		if (Thread::get_caller_id() != server_thread) {                                     \
 			m_r ret;                                                                        \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
 			SYNC_DEBUG                                                                      \
 			return ret;                                                                     \
 		} else {                                                                            \
+			command_queue.flush_if_pending();                                               \
 			return server_name->m_type(p1, p2, p3);                                         \
 		}                                                                                   \
 	}
 
 #define FUNC3S(m_type, m_arg1, m_arg2, m_arg3)                                         \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) {                             \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) override {                    \
+		WRITE_ACTION                                                                   \
 		if (Thread::get_caller_id() != server_thread) {                                \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
 			SYNC_DEBUG                                                                 \
 		} else {                                                                       \
+			command_queue.flush_if_pending();                                          \
 			server_name->m_type(p1, p2, p3);                                           \
 		}                                                                              \
 	}
 
 #define FUNC3SC(m_type, m_arg1, m_arg2, m_arg3)                                        \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const {                       \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const override {              \
 		if (Thread::get_caller_id() != server_thread) {                                \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
 			SYNC_DEBUG                                                                 \
 		} else {                                                                       \
+			command_queue.flush_if_pending();                                          \
 			server_name->m_type(p1, p2, p3);                                           \
 		}                                                                              \
 	}
 
 #define FUNC3(m_type, m_arg1, m_arg2, m_arg3)                                 \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) {                    \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) override {           \
+		WRITE_ACTION                                                          \
 		if (Thread::get_caller_id() != server_thread) {                       \
 			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3); \
 		} else {                                                              \
+			command_queue.flush_if_pending();                                 \
 			server_name->m_type(p1, p2, p3);                                  \
 		}                                                                     \
 	}
 
 #define FUNC3C(m_type, m_arg1, m_arg2, m_arg3)                                \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const {              \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const override {     \
 		if (Thread::get_caller_id() != server_thread) {                       \
 			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3); \
 		} else {                                                              \
+			command_queue.flush_if_pending();                                 \
 			server_name->m_type(p1, p2, p3);                                  \
 		}                                                                     \
 	}
 
 #define FUNC4R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4)                                     \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) {                            \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) override {                   \
+		WRITE_ACTION                                                                            \
 		if (Thread::get_caller_id() != server_thread) {                                         \
 			m_r ret;                                                                            \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
 			SYNC_DEBUG                                                                          \
 			return ret;                                                                         \
 		} else {                                                                                \
+			command_queue.flush_if_pending();                                                   \
 			return server_name->m_type(p1, p2, p3, p4);                                         \
 		}                                                                                       \
 	}
 
 #define FUNC4RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4)                                    \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const {                      \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const override {             \
 		if (Thread::get_caller_id() != server_thread) {                                         \
 			m_r ret;                                                                            \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
 			SYNC_DEBUG                                                                          \
 			return ret;                                                                         \
 		} else {                                                                                \
+			command_queue.flush_if_pending();                                                   \
 			return server_name->m_type(p1, p2, p3, p4);                                         \
 		}                                                                                       \
 	}
 
 #define FUNC4S(m_type, m_arg1, m_arg2, m_arg3, m_arg4)                                     \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) {                      \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) override {             \
+		WRITE_ACTION                                                                       \
 		if (Thread::get_caller_id() != server_thread) {                                    \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
 			SYNC_DEBUG                                                                     \
 		} else {                                                                           \
+			command_queue.flush_if_pending();                                              \
 			server_name->m_type(p1, p2, p3, p4);                                           \
 		}                                                                                  \
 	}
 
 #define FUNC4SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4)                                    \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const {                \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const override {       \
 		if (Thread::get_caller_id() != server_thread) {                                    \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
 			SYNC_DEBUG                                                                     \
 		} else {                                                                           \
+			command_queue.flush_if_pending();                                              \
 			server_name->m_type(p1, p2, p3, p4);                                           \
 		}                                                                                  \
 	}
 
 #define FUNC4(m_type, m_arg1, m_arg2, m_arg3, m_arg4)                             \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) {             \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) override {    \
+		WRITE_ACTION                                                              \
 		if (Thread::get_caller_id() != server_thread) {                           \
 			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4); \
 		} else {                                                                  \
+			command_queue.flush_if_pending();                                     \
 			server_name->m_type(p1, p2, p3, p4);                                  \
 		}                                                                         \
 	}
 
-#define FUNC4C(m_type, m_arg1, m_arg2, m_arg3, m_arg4)                            \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const {       \
-		if (Thread::get_caller_id() != server_thread) {                           \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4); \
-		} else {                                                                  \
-			server_name->m_type(p1, p2, p3, p4);                                  \
-		}                                                                         \
+#define FUNC4C(m_type, m_arg1, m_arg2, m_arg3, m_arg4)                               \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const override { \
+		if (Thread::get_caller_id() != server_thread) {                              \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4);    \
+		} else {                                                                     \
+			command_queue.flush_if_pending();                                        \
+			server_name->m_type(p1, p2, p3, p4);                                     \
+		}                                                                            \
 	}
 
 #define FUNC5R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                 \
 	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) {                     \
+		WRITE_ACTION                                                                                \
 		if (Thread::get_caller_id() != server_thread) {                                             \
 			m_r ret;                                                                                \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
 			SYNC_DEBUG                                                                              \
 			return ret;                                                                             \
 		} else {                                                                                    \
+			command_queue.flush_if_pending();                                                       \
 			return server_name->m_type(p1, p2, p3, p4, p5);                                         \
 		}                                                                                           \
 	}
 
 #define FUNC5RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const {               \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const override {      \
 		if (Thread::get_caller_id() != server_thread) {                                             \
 			m_r ret;                                                                                \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
 			SYNC_DEBUG                                                                              \
 			return ret;                                                                             \
 		} else {                                                                                    \
+			command_queue.flush_if_pending();                                                       \
 			return server_name->m_type(p1, p2, p3, p4, p5);                                         \
 		}                                                                                           \
 	}
 
 #define FUNC5S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                 \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) {               \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) override {      \
+		WRITE_ACTION                                                                           \
 		if (Thread::get_caller_id() != server_thread) {                                        \
 			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
 			SYNC_DEBUG                                                                         \
 		} else {                                                                               \
+			command_queue.flush_if_pending();                                                  \
 			server_name->m_type(p1, p2, p3, p4, p5);                                           \
 		}                                                                                      \
 	}
 
-#define FUNC5SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const {         \
-		if (Thread::get_caller_id() != server_thread) {                                        \
-			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
-			SYNC_DEBUG                                                                         \
-		} else {                                                                               \
-			server_name->m_type(p1, p2, p3, p4, p5);                                           \
-		}                                                                                      \
+#define FUNC5SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                 \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                         \
+			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5);  \
+			SYNC_DEBUG                                                                          \
+		} else {                                                                                \
+			command_queue.flush_if_pending();                                                   \
+			server_name->m_type(p1, p2, p3, p4, p5);                                            \
+		}                                                                                       \
 	}
 
-#define FUNC5(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                         \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) {      \
-		if (Thread::get_caller_id() != server_thread) {                               \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
-		} else {                                                                      \
-			server_name->m_type(p1, p2, p3, p4, p5);                                  \
-		}                                                                             \
+#define FUNC5(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                             \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) override { \
+		WRITE_ACTION                                                                      \
+		if (Thread::get_caller_id() != server_thread) {                                   \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5);     \
+		} else {                                                                          \
+			command_queue.flush_if_pending();                                             \
+			server_name->m_type(p1, p2, p3, p4, p5);                                      \
+		}                                                                                 \
 	}
 
-#define FUNC5C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                         \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \
-		if (Thread::get_caller_id() != server_thread) {                                \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5);  \
-		} else {                                                                       \
-			server_name->m_type(p1, p2, p3, p4, p5);                                   \
-		}                                                                              \
+#define FUNC5C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                  \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                         \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5);           \
+		} else {                                                                                \
+			command_queue.flush_if_pending();                                                   \
+			server_name->m_type(p1, p2, p3, p4, p5);                                            \
+		}                                                                                       \
 	}
 
 #define FUNC6R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                             \
 	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) {              \
+		WRITE_ACTION                                                                                    \
 		if (Thread::get_caller_id() != server_thread) {                                                 \
 			m_r ret;                                                                                    \
 			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
 			SYNC_DEBUG                                                                                  \
 			return ret;                                                                                 \
 		} else {                                                                                        \
+			command_queue.flush_if_pending();                                                           \
 			return server_name->m_type(p1, p2, p3, p4, p5, p6);                                         \
 		}                                                                                               \
 	}
 
-#define FUNC6RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                            \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const {        \
-		if (Thread::get_caller_id() != server_thread) {                                                 \
-			m_r ret;                                                                                    \
-			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
-			SYNC_DEBUG                                                                                  \
-			return ret;                                                                                 \
-		} else {                                                                                        \
-			return server_name->m_type(p1, p2, p3, p4, p5, p6);                                         \
-		}                                                                                               \
+#define FUNC6RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                              \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                   \
+			m_r ret;                                                                                      \
+			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret);   \
+			SYNC_DEBUG                                                                                    \
+			return ret;                                                                                   \
+		} else {                                                                                          \
+			command_queue.flush_if_pending();                                                             \
+			return server_name->m_type(p1, p2, p3, p4, p5, p6);                                           \
+		}                                                                                                 \
+	}
+
+#define FUNC6S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                               \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) override { \
+		WRITE_ACTION                                                                                 \
+		if (Thread::get_caller_id() != server_thread) {                                              \
+			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6);   \
+			SYNC_DEBUG                                                                               \
+		} else {                                                                                     \
+			command_queue.flush_if_pending();                                                        \
+			server_name->m_type(p1, p2, p3, p4, p5, p6);                                             \
+		}                                                                                            \
+	}
+
+#define FUNC6SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                                    \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                    \
+			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6);         \
+			SYNC_DEBUG                                                                                     \
+		} else {                                                                                           \
+			command_queue.flush_if_pending();                                                              \
+			server_name->m_type(p1, p2, p3, p4, p5, p6);                                                   \
+		}                                                                                                  \
 	}
 
-#define FUNC6S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                             \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) {        \
-		if (Thread::get_caller_id() != server_thread) {                                            \
-			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
-			SYNC_DEBUG                                                                             \
-		} else {                                                                                   \
-			server_name->m_type(p1, p2, p3, p4, p5, p6);                                           \
-		}                                                                                          \
+#define FUNC6(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                                \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) override { \
+		WRITE_ACTION                                                                                 \
+		if (Thread::get_caller_id() != server_thread) {                                              \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6);            \
+		} else {                                                                                     \
+			command_queue.flush_if_pending();                                                        \
+			server_name->m_type(p1, p2, p3, p4, p5, p6);                                             \
+		}                                                                                            \
 	}
 
-#define FUNC6SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                            \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const {  \
-		if (Thread::get_caller_id() != server_thread) {                                            \
-			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
-			SYNC_DEBUG                                                                             \
-		} else {                                                                                   \
-			server_name->m_type(p1, p2, p3, p4, p5, p6);                                           \
-		}                                                                                          \
+#define FUNC6C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                                     \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                    \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6);                  \
+		} else {                                                                                           \
+			command_queue.flush_if_pending();                                                              \
+			server_name->m_type(p1, p2, p3, p4, p5, p6);                                                   \
+		}                                                                                                  \
 	}
 
-#define FUNC6(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                       \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \
-		if (Thread::get_caller_id() != server_thread) {                                     \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6);   \
-		} else {                                                                            \
-			server_name->m_type(p1, p2, p3, p4, p5, p6);                                    \
-		}                                                                                   \
+#define FUNC7R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                            \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) override { \
+		WRITE_ACTION                                                                                           \
+		if (Thread::get_caller_id() != server_thread) {                                                        \
+			m_r ret;                                                                                           \
+			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret);    \
+			SYNC_DEBUG                                                                                         \
+			return ret;                                                                                        \
+		} else {                                                                                               \
+			command_queue.flush_if_pending();                                                                  \
+			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                            \
+		}                                                                                                      \
 	}
 
-#define FUNC6C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)                            \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \
-		if (Thread::get_caller_id() != server_thread) {                                           \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6);         \
-		} else {                                                                                  \
-			server_name->m_type(p1, p2, p3, p4, p5, p6);                                          \
-		}                                                                                         \
-	}
-
-#define FUNC7R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                         \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) {       \
-		if (Thread::get_caller_id() != server_thread) {                                                     \
-			m_r ret;                                                                                        \
-			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
-			SYNC_DEBUG                                                                                      \
-			return ret;                                                                                     \
-		} else {                                                                                            \
-			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                         \
-		}                                                                                                   \
-	}
-
-#define FUNC7RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                        \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \
-		if (Thread::get_caller_id() != server_thread) {                                                     \
-			m_r ret;                                                                                        \
-			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
-			SYNC_DEBUG                                                                                      \
-			return ret;                                                                                     \
-		} else {                                                                                            \
-			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                         \
-		}                                                                                                   \
-	}
-
-#define FUNC7S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                         \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \
-		if (Thread::get_caller_id() != server_thread) {                                                \
-			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
-			SYNC_DEBUG                                                                                 \
-		} else {                                                                                       \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                           \
-		}                                                                                              \
-	}
-
-#define FUNC7SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                              \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \
-		if (Thread::get_caller_id() != server_thread) {                                                      \
-			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7);       \
-			SYNC_DEBUG                                                                                       \
-		} else {                                                                                             \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                                 \
-		}                                                                                                    \
-	}
-
-#define FUNC7(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                          \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \
-		if (Thread::get_caller_id() != server_thread) {                                                \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7);          \
-		} else {                                                                                       \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                           \
-		}                                                                                              \
-	}
-
-#define FUNC7C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                               \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \
-		if (Thread::get_caller_id() != server_thread) {                                                      \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7);                \
-		} else {                                                                                             \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                                 \
-		}                                                                                                    \
-	}
-
-#define FUNC8R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                      \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
-		if (Thread::get_caller_id() != server_thread) {                                                          \
-			m_r ret;                                                                                             \
-			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret);  \
-			SYNC_DEBUG                                                                                           \
-			return ret;                                                                                          \
-		} else {                                                                                                 \
-			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                          \
-		}                                                                                                        \
-	}
-
-#define FUNC8RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                           \
-	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
-		if (Thread::get_caller_id() != server_thread) {                                                                \
-			m_r ret;                                                                                                   \
-			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret);        \
-			SYNC_DEBUG                                                                                                 \
-			return ret;                                                                                                \
-		} else {                                                                                                       \
-			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                \
-		}                                                                                                              \
-	}
-
-#define FUNC8S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                            \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
-		if (Thread::get_caller_id() != server_thread) {                                                           \
-			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);        \
-			SYNC_DEBUG                                                                                            \
-		} else {                                                                                                  \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                  \
-		}                                                                                                         \
-	}
-
-#define FUNC8SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                                 \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
-		if (Thread::get_caller_id() != server_thread) {                                                                 \
-			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);              \
-			SYNC_DEBUG                                                                                                  \
-		} else {                                                                                                        \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                        \
-		}                                                                                                               \
-	}
-
-#define FUNC8(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                             \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
-		if (Thread::get_caller_id() != server_thread) {                                                           \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);                 \
-		} else {                                                                                                  \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                  \
-		}                                                                                                         \
-	}
-
-#define FUNC8C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                                  \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
-		if (Thread::get_caller_id() != server_thread) {                                                                 \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);                       \
-		} else {                                                                                                        \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                        \
-		}                                                                                                               \
-	}
-
-#define FUNC9(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9)                                \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9) { \
-		if (Thread::get_caller_id() != server_thread) {                                                                      \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9);                        \
-		} else {                                                                                                             \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9);                                                         \
-		}                                                                                                                    \
-	}
-
-#define FUNC10(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10)                                   \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10) { \
-		if (Thread::get_caller_id() != server_thread) {                                                                                   \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);                                \
-		} else {                                                                                                                          \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);                                                                 \
-		}                                                                                                                                 \
-	}
-
-#define FUNC11(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11)                                       \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11) { \
-		if (Thread::get_caller_id() != server_thread) {                                                                                                \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);                                        \
-		} else {                                                                                                                                       \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);                                                                         \
-		}                                                                                                                                              \
-	}
-
-#define FUNC12(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12)                                           \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12) { \
-		if (Thread::get_caller_id() != server_thread) {                                                                                                             \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);                                                \
-		} else {                                                                                                                                                    \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);                                                                                 \
-		}                                                                                                                                                           \
-	}
-
-#define FUNC13(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13)                                               \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13) { \
-		if (Thread::get_caller_id() != server_thread) {                                                                                                                          \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);                                                        \
-		} else {                                                                                                                                                                 \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);                                                                                         \
-		}                                                                                                                                                                        \
-	}
-
-#define FUNC14(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14)                                                   \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14) { \
-		if (Thread::get_caller_id() != server_thread) {                                                                                                                                       \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);                                                                \
-		} else {                                                                                                                                                                              \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);                                                                                                 \
-		}                                                                                                                                                                                     \
-	}
-
-#define FUNC15(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14, m_arg15)                                                       \
-	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14, m_arg15 p15) { \
-		if (Thread::get_caller_id() != server_thread) {                                                                                                                                                    \
-			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);                                                                        \
-		} else {                                                                                                                                                                                           \
-			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);                                                                                                         \
-		}                                                                                                                                                                                                  \
+#define FUNC7RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                                 \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                              \
+			m_r ret;                                                                                                 \
+			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret);          \
+			SYNC_DEBUG                                                                                               \
+			return ret;                                                                                              \
+		} else {                                                                                                     \
+			command_queue.flush_if_pending();                                                                        \
+			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                                  \
+		}                                                                                                            \
+	}
+
+#define FUNC7S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                                  \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) override { \
+		WRITE_ACTION                                                                                            \
+		if (Thread::get_caller_id() != server_thread) {                                                         \
+			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7);          \
+			SYNC_DEBUG                                                                                          \
+		} else {                                                                                                \
+			command_queue.flush_if_pending();                                                                   \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                                    \
+		}                                                                                                       \
+	}
+
+#define FUNC7SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                                       \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                               \
+			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7);                \
+			SYNC_DEBUG                                                                                                \
+		} else {                                                                                                      \
+			command_queue.flush_if_pending();                                                                         \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                                          \
+		}                                                                                                             \
+	}
+
+#define FUNC7(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                                   \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) override { \
+		WRITE_ACTION                                                                                            \
+		if (Thread::get_caller_id() != server_thread) {                                                         \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7);                   \
+		} else {                                                                                                \
+			command_queue.flush_if_pending();                                                                   \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                                    \
+		}                                                                                                       \
+	}
+
+#define FUNC7C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)                                        \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                               \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7);                         \
+		} else {                                                                                                      \
+			command_queue.flush_if_pending();                                                                         \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7);                                                          \
+		}                                                                                                             \
+	}
+
+#define FUNC8R(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                               \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) override { \
+		WRITE_ACTION                                                                                                      \
+		if (Thread::get_caller_id() != server_thread) {                                                                   \
+			m_r ret;                                                                                                      \
+			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret);           \
+			SYNC_DEBUG                                                                                                    \
+			return ret;                                                                                                   \
+		} else {                                                                                                          \
+			command_queue.flush_if_pending();                                                                             \
+			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                   \
+		}                                                                                                                 \
+	}
+
+#define FUNC8RC(m_r, m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                                    \
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                                         \
+			m_r ret;                                                                                                            \
+			command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret);                 \
+			SYNC_DEBUG                                                                                                          \
+			return ret;                                                                                                         \
+		} else {                                                                                                                \
+			command_queue.flush_if_pending();                                                                                   \
+			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                         \
+		}                                                                                                                       \
+	}
+
+#define FUNC8S(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                                     \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) override { \
+		WRITE_ACTION                                                                                                       \
+		if (Thread::get_caller_id() != server_thread) {                                                                    \
+			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);                 \
+			SYNC_DEBUG                                                                                                     \
+		} else {                                                                                                           \
+			command_queue.flush_if_pending();                                                                              \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                           \
+		}                                                                                                                  \
+	}
+
+#define FUNC8SC(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                                          \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                                          \
+			command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);                       \
+			SYNC_DEBUG                                                                                                           \
+		} else {                                                                                                                 \
+			command_queue.flush_if_pending();                                                                                    \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                                 \
+		}                                                                                                                        \
+	}
+
+#define FUNC8(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                                      \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) override { \
+		WRITE_ACTION                                                                                                       \
+		if (Thread::get_caller_id() != server_thread) {                                                                    \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);                          \
+		} else {                                                                                                           \
+			command_queue.flush_if_pending();                                                                              \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                           \
+		}                                                                                                                  \
+	}
+
+#define FUNC8C(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)                                           \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const override { \
+		if (Thread::get_caller_id() != server_thread) {                                                                          \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8);                                \
+		} else {                                                                                                                 \
+			command_queue.flush_if_pending();                                                                                    \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                                 \
+		}                                                                                                                        \
+	}
+
+#define FUNC9(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9)                                         \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9) override { \
+		WRITE_ACTION                                                                                                                  \
+		if (Thread::get_caller_id() != server_thread) {                                                                               \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9);                                 \
+		} else {                                                                                                                      \
+			command_queue.flush_if_pending();                                                                                         \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9);                                                                  \
+		}                                                                                                                             \
+	}
+
+#define FUNC10(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10)                                            \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10) override { \
+		WRITE_ACTION                                                                                                                               \
+		if (Thread::get_caller_id() != server_thread) {                                                                                            \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);                                         \
+		} else {                                                                                                                                   \
+			command_queue.flush_if_pending();                                                                                                      \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);                                                                          \
+		}                                                                                                                                          \
+	}
+
+#define FUNC11(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11)                                                \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11) override { \
+		WRITE_ACTION                                                                                                                                            \
+		if (Thread::get_caller_id() != server_thread) {                                                                                                         \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);                                                 \
+		} else {                                                                                                                                                \
+			command_queue.flush_if_pending();                                                                                                                   \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);                                                                                  \
+		}                                                                                                                                                       \
+	}
+
+#define FUNC12(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12)                                                    \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12) override { \
+		WRITE_ACTION                                                                                                                                                         \
+		if (Thread::get_caller_id() != server_thread) {                                                                                                                      \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);                                                         \
+		} else {                                                                                                                                                             \
+			command_queue.flush_if_pending();                                                                                                                                \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);                                                                                          \
+		}                                                                                                                                                                    \
+	}
+
+#define FUNC13(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13)                                                        \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13) override { \
+		WRITE_ACTION                                                                                                                                                                      \
+		if (Thread::get_caller_id() != server_thread) {                                                                                                                                   \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);                                                                 \
+		} else {                                                                                                                                                                          \
+			command_queue.flush_if_pending();                                                                                                                                             \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);                                                                                                  \
+		}                                                                                                                                                                                 \
+	}
+
+#define FUNC14(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14)                                                            \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14) override { \
+		WRITE_ACTION                                                                                                                                                                                   \
+		if (Thread::get_caller_id() != server_thread) {                                                                                                                                                \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);                                                                         \
+		} else {                                                                                                                                                                                       \
+			command_queue.flush_if_pending();                                                                                                                                                          \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);                                                                                                          \
+		}                                                                                                                                                                                              \
+	}
+
+#define FUNC15(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14, m_arg15)                                                                \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13, m_arg14 p14, m_arg15 p15) override { \
+		WRITE_ACTION                                                                                                                                                                                                \
+		if (Thread::get_caller_id() != server_thread) {                                                                                                                                                             \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);                                                                                 \
+		} else {                                                                                                                                                                                                    \
+			command_queue.flush_if_pending();                                                                                                                                                                       \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);                                                                                                                  \
+		}                                                                                                                                                                                                           \
 	}

+ 10 - 4
tests/test_physics_3d.cpp

@@ -86,7 +86,9 @@ protected:
 		PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
 
 		RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape], scenario);
-		RID body = ps->body_create(p_body, !p_active_default);
+		RID body = ps->body_create();
+		ps->body_set_mode(body, p_body);
+		ps->body_set_state(body, PhysicsServer3D::BODY_STATE_SLEEPING, !p_active_default);
 		ps->body_set_space(body, space);
 		ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0);
 		//todo set space
@@ -108,7 +110,9 @@ protected:
 		RID world_margin_shape = ps->shape_create(PhysicsServer3D::SHAPE_PLANE);
 		ps->shape_set_data(world_margin_shape, p_plane);
 
-		RID b = ps->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+		RID b = ps->body_create();
+		ps->body_set_mode(b, PhysicsServer3D::BODY_MODE_STATIC);
+
 		ps->body_set_space(b, space);
 		//todo set space
 		ps->body_add_shape(b, world_margin_shape);
@@ -202,7 +206,8 @@ protected:
 
 		RID triins = vs->instance_create2(trimesh_mesh, scenario);
 
-		RID tribody = ps->body_create(PhysicsServer3D::BODY_MODE_STATIC);
+		RID tribody = ps->body_create();
+		ps->body_set_mode(tribody, PhysicsServer3D::BODY_MODE_STATIC);
 		ps->body_set_space(tribody, space);
 		//todo set space
 		ps->body_add_shape(tribody, trimesh_shape);
@@ -358,7 +363,8 @@ public:
 		ps->shape_set_data(capsule_shape, capsule_params);
 
 		RID mesh_instance = vs->instance_create2(capsule_mesh, scenario);
-		character = ps->body_create(PhysicsServer3D::BODY_MODE_CHARACTER);
+		character = ps->body_create();
+		ps->body_set_mode(character, PhysicsServer3D::BODY_MODE_CHARACTER);
 		ps->body_set_space(character, space);
 		//todo add space
 		ps->body_add_shape(character, capsule_shape);