Skip to content

Commit

Permalink
Merge pull request #45852 from reduz/make-servers-truly-thread-safe
Browse files Browse the repository at this point in the history
Make Servers truly Thread Safe
  • Loading branch information
akien-mga authored Feb 10, 2021
2 parents f3d1577 + 8b19ffd commit 1808f1d
Show file tree
Hide file tree
Showing 74 changed files with 2,902 additions and 2,806 deletions.
4 changes: 2 additions & 2 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
5 changes: 5 additions & 0 deletions core/templates/command_queue_mt.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,11 @@ class CommandQueueMT {
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();
Expand Down
91 changes: 82 additions & 9 deletions core/templates/rid_owner.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -115,15 +114,22 @@ class RID_Alloc : public RID_AllocBase {
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) {
Expand All @@ -133,7 +139,20 @@ class RID_Alloc : public RID_AllocBase {
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();
}
Expand All @@ -151,10 +170,32 @@ class RID_Alloc : public RID_AllocBase {
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;
}

Expand All @@ -166,6 +207,11 @@ class RID_Alloc : public RID_AllocBase {

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) {
Expand All @@ -186,7 +232,7 @@ class RID_Alloc : public RID_AllocBase {

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();
Expand All @@ -213,7 +259,12 @@ class RID_Alloc : public RID_AllocBase {
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();
}
Expand Down Expand Up @@ -330,6 +381,14 @@ class RID_PtrOwner {
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)) {
Expand All @@ -338,6 +397,12 @@ class RID_PtrOwner {
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);
}
Expand Down Expand Up @@ -379,6 +444,14 @@ class RID_Owner {
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);
}
Expand Down
10 changes: 3 additions & 7 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand Down
8 changes: 4 additions & 4 deletions modules/bullet/bullet_physics_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions modules/bullet/bullet_physics_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ class BulletPhysicsServer3D : public PhysicsServer3D {
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;
Expand Down
3 changes: 2 additions & 1 deletion modules/bullet/config.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down
8 changes: 4 additions & 4 deletions modules/bullet/soft_body_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions modules/bullet/soft_body_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class SoftBodyBullet : public CollisionObjectBullet {
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]
Expand Down Expand Up @@ -129,8 +129,8 @@ class SoftBodyBullet : public CollisionObjectBullet {
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; }
Expand Down
6 changes: 4 additions & 2 deletions modules/csg/csg_shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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());
Expand Down
5 changes: 3 additions & 2 deletions modules/gridmap/grid_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion platform/uwp/os_uwp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 0 additions & 1 deletion platform/windows/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion scene/2d/cpu_particles_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading

0 comments on commit 1808f1d

Please sign in to comment.