From d6327709b568594949cbb3e98eb97126af67b17c Mon Sep 17 00:00:00 2001 From: "K. S. Ernest (iFire) Lee" Date: Sun, 21 Jun 2020 08:59:11 -0700 Subject: [PATCH] Add multithreaded Godot Engine Bullet processing. --- modules/bullet/SCsub | 3 ++- modules/bullet/register_types.cpp | 6 ++++++ modules/bullet/space_bullet.cpp | 25 ++++++++++++++----------- modules/bullet/space_bullet.h | 30 ++++++++++++++++++------------ 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index 692c749886..bbe4f5a9b4 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -202,7 +202,8 @@ if env["builtin_bullet"]: env_bullet.Prepend(CPPPATH=[thirdparty_dir]) # if env['target'] == "debug" or env['target'] == "release_debug": # env_bullet.Append(CPPDEFINES=['BT_DEBUG']) - + env_bullet.Append(CPPDEFINES=['BT_THREADSAFE']) + env_thirdparty = env_bullet.Clone() env_thirdparty.disable_warnings() env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) diff --git a/modules/bullet/register_types.cpp b/modules/bullet/register_types.cpp index 7819b67cad..3efe6584cd 100644 --- a/modules/bullet/register_types.cpp +++ b/modules/bullet/register_types.cpp @@ -39,6 +39,11 @@ */ #ifndef _3D_DISABLED +bool init_bt_task_scheduler() { + btITaskScheduler *godot_bullet_task_scheduler = btCreateDefaultTaskScheduler(); + btSetTaskScheduler(godot_bullet_task_scheduler); + return true; +} PhysicsServer *_createBulletPhysicsCallback() { return memnew(BulletPhysicsServer); } @@ -46,6 +51,7 @@ PhysicsServer *_createBulletPhysicsCallback() { void register_bullet_types() { #ifndef _3D_DISABLED + static bool bt_task_scheduler = init_bt_task_scheduler(); PhysicsServerManager::register_server("Bullet", &_createBulletPhysicsCallback); PhysicsServerManager::set_default_server("Bullet", 1); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 9835cc6d75..f1669988ac 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -34,6 +34,7 @@ #include "bullet_types_converter.h" #include "bullet_utilities.h" #include "constraint_bullet.h" +#include "core/os/os.h" #include "core/project_settings.h" #include "core/ustring.h" #include "godot_collision_configuration.h" @@ -48,6 +49,8 @@ #include #include #include +#include +#include #include #include #include @@ -591,7 +594,6 @@ btScalar calculateGodotCombinedFriction(const btCollisionObject *body0, const bt } void SpaceBullet::create_empty_world(bool p_create_soft_world) { - gjk_epa_pen_solver = bulletnew(btGjkEpaPenetrationDepthSolver); gjk_simplex_solver = bulletnew(btVoronoiSimplexSolver); @@ -599,7 +601,7 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) { if (p_create_soft_world) { world_mem = malloc(sizeof(btSoftRigidDynamicsWorld)); } else { - world_mem = malloc(sizeof(btDiscreteDynamicsWorld)); + world_mem = malloc(sizeof(btDiscreteDynamicsWorldMt)); } ERR_FAIL_COND_MSG(!world_mem, "Out of memory."); @@ -607,28 +609,28 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) { if (p_create_soft_world) { collisionConfiguration = bulletnew(GodotSoftCollisionConfiguration(static_cast(world_mem))); } else { - collisionConfiguration = bulletnew(GodotCollisionConfiguration(static_cast(world_mem))); + collisionConfiguration = bulletnew(GodotCollisionConfiguration(static_cast(world_mem))); } dispatcher = bulletnew(GodotCollisionDispatcher(collisionConfiguration)); broadphase = bulletnew(btDbvtBroadphase); solver = bulletnew(btSequentialImpulseConstraintSolver); + int32_t process_count = OS::get_singleton()->get_processor_count() - 2; + solver_pool = bulletnew(btConstraintSolverPoolMt(process_count)); + solver_mutithread = bulletnew(btSequentialImpulseConstraintSolverMt); if (p_create_soft_world) { dynamicsWorld = new (world_mem) btSoftRigidDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); soft_body_world_info = bulletnew(btSoftBodyWorldInfo); } else { - dynamicsWorld = new (world_mem) btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); - } - + dynamicsWorld = new (world_mem) btDiscreteDynamicsWorldMt(dispatcher, broadphase, solver_pool, solver_mutithread, collisionConfiguration); + } + dynamicsWorld->setWorldUserInfo(this); ghostPairCallback = bulletnew(btGhostPairCallback); godotFilterCallback = bulletnew(GodotFilterCallback); gCalculateCombinedRestitutionCallback = &calculateGodotCombinedRestitution; gCalculateCombinedFrictionCallback = &calculateGodotCombinedFriction; gContactAddedCallback = &godotContactAddedCallback; - - dynamicsWorld->setWorldUserInfo(this); - dynamicsWorld->setInternalTickCallback(onBulletPreTickCallback, this, true); dynamicsWorld->setInternalTickCallback(onBulletTickCallback, this, false); dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(ghostPairCallback); // Setup ghost check @@ -646,7 +648,6 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) { void SpaceBullet::destroy_world() { /// The world elements (like: Collision Objects, Constraints, Shapes) are managed by godot - dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(NULL); dynamicsWorld->getPairCache()->setOverlapFilterCallback(NULL); @@ -657,8 +658,10 @@ void SpaceBullet::destroy_world() { dynamicsWorld->~btDiscreteDynamicsWorld(); free(dynamicsWorld); dynamicsWorld = NULL; - + bulletdelete(solver); + bulletdelete(solver_pool); + bulletdelete(solver_mutithread); bulletdelete(broadphase); bulletdelete(dispatcher); bulletdelete(collisionConfiguration); diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 29f81c5a2e..e15176953f 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -39,7 +39,10 @@ #include #include +#include +#include #include +#include #include #include @@ -53,7 +56,7 @@ class btCollisionDispatcher; class btConstraintSolver; class btDefaultCollisionConfiguration; class btDynamicsWorld; -class btDiscreteDynamicsWorld; +class btDiscreteDynamicsWorldMt; class btEmptyShape; class btGhostPairCallback; class btSoftRigidDynamicsWorld; @@ -92,19 +95,22 @@ class SpaceBullet : public RIDBullet { friend void onBulletTickCallback(btDynamicsWorld *world, btScalar timeStep); friend class BulletPhysicsDirectSpaceState; - btBroadphaseInterface *broadphase; - btDefaultCollisionConfiguration *collisionConfiguration; - btCollisionDispatcher *dispatcher; - btConstraintSolver *solver; - btDiscreteDynamicsWorld *dynamicsWorld; - btSoftBodyWorldInfo *soft_body_world_info; - btGhostPairCallback *ghostPairCallback; - GodotFilterCallback *godotFilterCallback; + btBroadphaseInterface *broadphase = nullptr; + btDefaultCollisionConfiguration *collisionConfiguration = nullptr; + btCollisionDispatcher *dispatcher = nullptr; + btConstraintSolver *solver = nullptr; + btSequentialImpulseConstraintSolverMt *solver_mutithread = nullptr; + btConstraintSolverPoolMt *solver_pool = nullptr; + btDiscreteDynamicsWorld *dynamicsWorld = nullptr; + btSoftBodyWorldInfo *soft_body_world_info = nullptr; + btGhostPairCallback *ghostPairCallback = nullptr; + GodotFilterCallback *godotFilterCallback = nullptr; - btGjkEpaPenetrationDepthSolver *gjk_epa_pen_solver; - btVoronoiSimplexSolver *gjk_simplex_solver; - BulletPhysicsDirectSpaceState *direct_access; + btGjkEpaPenetrationDepthSolver *gjk_epa_pen_solver = nullptr; + btVoronoiSimplexSolver *gjk_simplex_solver = nullptr; + + BulletPhysicsDirectSpaceState *direct_access = nullptr; Vector3 gravityDirection; real_t gravityMagnitude;