Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Commit

Permalink
Merge pull request #563 from cortex-command-community/thread-pooling
Browse files Browse the repository at this point in the history
Thread Pooling
  • Loading branch information
Causeless authored Nov 24, 2023
2 parents 6221af8 + b3b4f1e commit 08ddaf0
Show file tree
Hide file tree
Showing 88 changed files with 15,497 additions and 398 deletions.
2 changes: 1 addition & 1 deletion Activities/GibEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ void GibEditor::Update()
std::list<MovableObject *> *pEditedGibList = m_pEditorGUI->GetPlacedGibs();
MovableObject *pGibCopy = 0;

for (std::list<Gib>::iterator gItr = pLoadedGibList->begin(); gItr != pLoadedGibList->end(); ++gItr)
for (auto gItr = pLoadedGibList->begin(); gItr != pLoadedGibList->end(); ++gItr)
{
pGibCopy = dynamic_cast<MovableObject *>((*gItr).GetParticlePreset()->Clone());
if (pGibCopy)
Expand Down
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- Added a save/load game menu which can be accessed from the main or pause menus, which allows the user to save their current progress in an activity to resume at a later date.

- New `Settings.ini` property `EnableMultithreadedLua`, which can be used to enable multithreaded Lua scripts and AI, for any lua script with the `--[[MULTITHREAD]]--` tag. Defaults to true.
- Massive performance improvements, especially in very large scenes with lots of actors.

- New multithreaded AI and Lua scripts.
Lua scripts now have extra callback functions `ThreadedUpdateAI(self)`, `ThreadedUpdate(self)` and `SyncedUpdate(self)`.
The `Threaded` callback functions are run in a multithreaded fashion, whereas `Update` runs in a singlethreaded fashion (where it's safe to modify global state or affect other objects).
The `SyncedUpdate` callback is called in a single-threaded fashion, but only when an MO directly requests it by calling `self:RequestSyncedUpdate()`. This gives greater performance, as the script can avoid any single-threaded updates being called on it until it explicitly needs it.

- New generic Lua messaging system, to allow scripts on objects to communicate with other objects or scripts.
Scripts on `MovableObject` now have new callback functions `OnMessage(self, message, context)` and `OnGlobalMessage(self, message, context)`.
Expand All @@ -28,8 +33,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
New INI and Lua (R/W) property `CanAdjustAngleWhileFiring`, which defines whether the jet angle can change while the jetpack is active. Defaults to true.
New INI and Lua (R/W) property `AdjustsThrottleForWeight`, which defines whether the jetpack will adjust it's throttle (between `NegativeThrottleMultiplier` and `PositiveThrottleMultiplier`) to account for any extra inventory mass. Increased throttle will decrease jet time accordingly. Defaults to true.

- New Lua event function `SyncedUpdate()`, which will be called in a thread-safe synchronized manner and allows multithreaded scripts to modify game state in a safe and consistent way.

- Multithreaded asynchronous pathfinding, which dramatically improves performance on large maps and improves AI responsiveness.
New `Actor` Lua property (R) `IsWaitingOnNewMovePath`, which returns true while the actor is currently calculating a new path.
New Lua `SceneMan` function `CalculatePathAsync` for asynchronous pathfinding. This function has no return value, and is used as follows:
Expand Down
4 changes: 4 additions & 0 deletions Entities/ACDropShip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "AEmitter.h"
#include "PresetMan.h"

#include "tracy/Tracy.hpp"

namespace RTE {

ConcreteClassInfo(ACDropShip, ACraft, 10);
Expand Down Expand Up @@ -272,6 +274,8 @@ MOID ACDropShip::DetectObstacle(float distance)

void ACDropShip::PreControllerUpdate()
{
ZoneScoped;

ACraft::PreControllerUpdate();

// TODO: Improve and make optional thrusters more robust!
Expand Down
6 changes: 6 additions & 0 deletions Entities/ACrab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "GUI.h"
#include "AllegroBitmap.h"

#include "tracy/Tracy.hpp"

namespace RTE {

ConcreteClassInfo(ACrab, Actor, 20);
Expand Down Expand Up @@ -997,6 +999,8 @@ void ACrab::OnNewMovePath()

void ACrab::PreControllerUpdate()
{
ZoneScoped;

Actor::PreControllerUpdate();

float deltaTime = g_TimerMan.GetDeltaTimeSecs();
Expand Down Expand Up @@ -1383,6 +1387,8 @@ void ACrab::PreControllerUpdate()

void ACrab::Update()
{
ZoneScoped;

Actor::Update();

////////////////////////////////////
Expand Down
4 changes: 4 additions & 0 deletions Entities/ADoor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "PresetMan.h"
#include "SettingsMan.h"

#include "tracy/Tracy.hpp"

namespace RTE {

ConcreteClassInfo(ADoor, Actor, 20);
Expand Down Expand Up @@ -379,6 +381,8 @@ namespace RTE {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void ADoor::Update() {
ZoneScoped;

if (m_Door) {
if (m_DoorState != STOPPED && m_Status != Actor::Status::INACTIVE && m_SensorTimer.IsPastSimMS(m_SensorInterval)) {
UpdateSensors();
Expand Down
22 changes: 11 additions & 11 deletions Entities/AEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,17 @@ void AEmitter::Update()
m_WasEmitting = false;
}
}

// Set the screen flash effect to draw at the final post processing stage
if (m_EmitEnabled && (!m_FlashOnlyOnBurst || m_BurstTriggered) && m_pFlash && m_pFlash->GetScreenEffect()) {
// Fudge the glow pos forward a bit so it aligns nicely with the flash
Vector emitPos(m_pFlash->GetScreenEffect()->w * 0.3F * m_FlashScale, 0);
emitPos.RadRotate(m_HFlipped ? c_PI + m_Rotation.GetRadAngle() - m_EmitAngle.GetRadAngle() : m_Rotation.GetRadAngle() + m_EmitAngle.GetRadAngle());
emitPos = m_Pos + RotateOffset(m_EmissionOffset) + emitPos;
if (m_EffectAlwaysShows || !g_SceneMan.ObscuredPoint(emitPos)) {
g_PostProcessMan.RegisterPostEffect(emitPos, m_pFlash->GetScreenEffect(), m_pFlash->GetScreenEffectHash(), RandomNum(m_pFlash->GetEffectStopStrength(), m_pFlash->GetEffectStartStrength()) * std::clamp(m_FlashScale, 0.0F, 1.0F), m_pFlash->GetEffectRotAngle());
}
}
}


Expand All @@ -616,17 +627,6 @@ void AEmitter::Draw(BITMAP *pTargetBitmap,
if (m_pFlash && m_pFlash->IsDrawnAfterParent() &&
!onlyPhysical && mode == g_DrawColor && m_EmitEnabled && (!m_FlashOnlyOnBurst || m_BurstTriggered))
m_pFlash->Draw(pTargetBitmap, targetPos, mode, onlyPhysical);

// Set the screen flash effect to draw at the final post processing stage
if (m_EmitEnabled && (!m_FlashOnlyOnBurst || m_BurstTriggered) && m_pFlash && m_pFlash->GetScreenEffect() && mode == g_DrawColor && !onlyPhysical) {
// Fudge the glow pos forward a bit so it aligns nicely with the flash
Vector emitPos(m_pFlash->GetScreenEffect()->w * 0.3F * m_FlashScale, 0);
emitPos.RadRotate(m_HFlipped ? c_PI + m_Rotation.GetRadAngle() - m_EmitAngle.GetRadAngle() : m_Rotation.GetRadAngle() + m_EmitAngle.GetRadAngle());
emitPos = m_Pos + RotateOffset(m_EmissionOffset) + emitPos;
if (!g_SceneMan.ObscuredPoint(emitPos)) {
g_PostProcessMan.RegisterPostEffect(emitPos, m_pFlash->GetScreenEffect(), m_pFlash->GetScreenEffectHash(), RandomNum(m_pFlash->GetEffectStopStrength(), m_pFlash->GetEffectStartStrength()) * std::clamp(m_FlashScale, 0.0F, 1.0F), m_pFlash->GetEffectRotAngle());
}
}
}

} // namespace RTE
8 changes: 7 additions & 1 deletion Entities/AHuman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "GUI.h"
#include "AllegroBitmap.h"

#include "tracy/Tracy.hpp"

namespace RTE {

ConcreteClassInfo(AHuman, Actor, 20);
Expand Down Expand Up @@ -1710,6 +1712,8 @@ void AHuman::UpdateWalkAngle(AHuman::Layer whichLayer) {

void AHuman::PreControllerUpdate()
{
ZoneScoped;

Actor::PreControllerUpdate();

float deltaTime = g_TimerMan.GetDeltaTimeSecs();
Expand Down Expand Up @@ -2142,7 +2146,7 @@ void AHuman::PreControllerUpdate()
reach += m_pFGArm ? m_pFGArm->GetMaxLength() : m_pBGArm->GetMaxLength();
reachPoint = m_pFGArm ? m_pFGArm->GetJointPos() : m_pBGArm->GetJointPos();

MOID itemMOID = g_SceneMan.CastMORay(reachPoint, Vector(reach * RandomNum(0.5F, 1.0F) * GetFlipFactor(), 0).RadRotate(m_pItemInReach ? adjustedAimAngle : RandomNum(-(c_HalfPI + c_EighthPI), m_AimAngle * 0.75F + c_EighthPI) * GetFlipFactor()), m_MOID, Activity::NoTeam, g_MaterialGrass, true, 3);
MOID itemMOID = g_SceneMan.CastMORay(reachPoint, Vector(reach * RandomNum(0.5F, 1.0F) * GetFlipFactor(), 0).RadRotate(m_pItemInReach ? adjustedAimAngle : RandomNum(-(c_HalfPI + c_EighthPI), m_AimAngle * 0.75F + c_EighthPI) * GetFlipFactor()), m_MOID, m_Team, g_MaterialGrass, true, 3);

if (MovableObject *foundMO = g_MovableMan.GetMOFromID(itemMOID)) {
if (HeldDevice *foundDevice = dynamic_cast<HeldDevice *>(foundMO->GetRootParent())) {
Expand Down Expand Up @@ -2499,6 +2503,8 @@ void AHuman::PreControllerUpdate()

void AHuman::Update()
{
ZoneScoped;

float rot = m_Rotation.GetRadAngle(); // eugh, for backwards compat to be the same behaviour as with multithreaded AI

Actor::Update();
Expand Down
14 changes: 4 additions & 10 deletions Entities/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "GUI.h"
#include "AllegroBitmap.h"

#include "tracy/Tracy.hpp"

namespace RTE {

ConcreteClassInfo(Actor, MOSRotating, 20);
Expand Down Expand Up @@ -1248,16 +1250,6 @@ float Actor::EstimateDigStrength() const {
return m_AIBaseDigStrength;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Actor::UpdateAIScripted(ThreadScriptsToRun scriptsToRun) {
RunScriptedFunctionInAppropriateScripts("UpdateAI", false, true, {}, {}, {}, scriptsToRun);
if (scriptsToRun == ThreadScriptsToRun::SingleThreaded) {
// If we're in a SingleThreaded context, we run the MultiThreaded scripts synced updates
RunScriptedFunctionInAppropriateScripts("SyncedUpdateAI", false, true, {}, {}, {}, ThreadScriptsToRun::Both);
}
}

//////////////////////////////////////////////////////////////////////////////////////////
// Method: VerifyMOIDs
//////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1309,6 +1301,8 @@ void Actor::PreControllerUpdate() {

void Actor::Update()
{
ZoneScoped;

/////////////////////////////////
// Hit Body update and handling
MOSRotating::Update();
Expand Down
14 changes: 1 addition & 13 deletions Entities/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class Actor : public MOSRotating {

// Concrete allocation and cloning definitions
EntityAllocation(Actor);
AddScriptFunctionNames(MOSRotating, "UpdateAI", "SyncedUpdateAI", "OnControllerInputModeChange");
AddScriptFunctionNames(MOSRotating, "ThreadedUpdateAI", "UpdateAI", "OnControllerInputModeChange");
SerializableOverrideMethods;
ClassInfoGetters;

Expand Down Expand Up @@ -1155,18 +1155,6 @@ ClassInfoGetters;
/// <param name="newAIBaseDigStrength">The new base dig strength for this Actor.</param>
void SetAIBaseDigStrength(float newAIBaseDigStrength) { m_AIBaseDigStrength = newAIBaseDigStrength; }


//////////////////////////////////////////////////////////////////////////////////////////
// Method: UpdateAIScripted
//////////////////////////////////////////////////////////////////////////////////////////
// Description: Updates this' AI state with the provided scripted AI Update function.
// Arguments: None.
// Return value: Whether there was an AI Update function defined for this in its script,
// and if it was executed successfully.

void UpdateAIScripted(ThreadScriptsToRun scriptsToRun);


//////////////////////////////////////////////////////////////////////////////////////////
// Virtual method: PreControllerUpdate
//////////////////////////////////////////////////////////////////////////////////////////
Expand Down
11 changes: 5 additions & 6 deletions Entities/Attachable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,12 @@ namespace RTE {

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int Attachable::UpdateScripts(ThreadScriptsToRun scriptsToRun) {
int Attachable::UpdateScripts() {
if (m_Parent && !m_AllLoadedScripts.empty() && !ObjectScriptsInitialized()) {
RunScriptedFunctionInAppropriateScripts("OnAttach", false, false, { m_Parent }, {}, {}, scriptsToRun);
RunScriptedFunctionInAppropriateScripts("OnAttach", false, false, { m_Parent }, {}, {});
}

return MOSRotating::UpdateScripts(scriptsToRun);
return MOSRotating::UpdateScripts();
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -389,13 +389,12 @@ namespace RTE {
}

// If we're attached to something, MovableMan doesn't own us, and therefore isn't calling our UpdateScripts method (and neither is our parent), so we should here.
// We run our single-threaded scripts here, so that single-threaded behaviour is unchanged from prior to the multithreaded lua implementation
if (m_Parent && GetRootParent()->HasEverBeenAddedToMovableMan()) {
g_PerformanceMan.StartPerformanceMeasurement(PerformanceMan::ScriptsUpdate);
if (!m_AllLoadedScripts.empty() && !ObjectScriptsInitialized()) {
RunScriptedFunctionInAppropriateScripts("OnAttach", false, false, { m_Parent }, {}, {}, ThreadScriptsToRun::SingleThreaded);
RunScriptedFunctionInAppropriateScripts("OnAttach", false, false, { m_Parent }, {}, {});
}
UpdateScripts(ThreadScriptsToRun::SingleThreaded);
UpdateScripts();
g_PerformanceMan.StopPerformanceMeasurement(PerformanceMan::ScriptsUpdate);
}

Expand Down
3 changes: 1 addition & 2 deletions Entities/Attachable.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,8 @@ namespace RTE {
/// <summary>
/// Updates this Attachable's Lua scripts.
/// </summary>
/// <param name="scriptsToRun">Whether to run this objects single-threaded or multi-threaded scripts.</params>
/// <returns>An error return value signaling success or any particular failure. Anything below 0 is an error signal.</returns>
int UpdateScripts(ThreadScriptsToRun scriptsToRun) override;
int UpdateScripts() override;

/// <summary>
/// Updates this Attachable. Supposed to be done every frame.
Expand Down
16 changes: 8 additions & 8 deletions Entities/HDFirearm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,14 @@ void HDFirearm::Update()
}

m_FiredLastFrame = m_FireFrame;

// Set the screen flash effect to draw at the final post processing stage
if (m_FireFrame && m_pFlash && m_pFlash->GetScreenEffect()) {
Vector muzzlePos = m_Pos + RotateOffset(m_MuzzleOff + Vector(m_pFlash->GetSpriteWidth() * 0.3F, 0));
if (m_EffectAlwaysShows || !g_SceneMan.ObscuredPoint(muzzlePos)) {
g_PostProcessMan.RegisterPostEffect(muzzlePos, m_pFlash->GetScreenEffect(), m_pFlash->GetScreenEffectHash(), RandomNum(m_pFlash->GetEffectStopStrength(), m_pFlash->GetEffectStartStrength()), m_pFlash->GetEffectRotAngle());
}
}
}


Expand Down Expand Up @@ -1144,14 +1152,6 @@ void HDFirearm::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mo
if (m_pFlash && m_FireFrame && m_pFlash->IsDrawnAfterParent() && mode == g_DrawColor && !onlyPhysical) {
m_pFlash->Draw(pTargetBitmap, targetPos, mode, onlyPhysical);
}

// Set the screen flash effect to draw at the final post processing stage
if (m_FireFrame && m_pFlash && m_pFlash->GetScreenEffect() && mode == g_DrawColor && !onlyPhysical) {
Vector muzzlePos = m_Pos + RotateOffset(m_MuzzleOff + Vector(m_pFlash->GetSpriteWidth() * 0.3F, 0));
if (!g_SceneMan.ObscuredPoint(muzzlePos)) {
g_PostProcessMan.RegisterPostEffect(muzzlePos, m_pFlash->GetScreenEffect(), m_pFlash->GetScreenEffectHash(), RandomNum(m_pFlash->GetEffectStopStrength(), m_pFlash->GetEffectStartStrength()), m_pFlash->GetEffectRotAngle());
}
}
}


Expand Down
8 changes: 4 additions & 4 deletions Entities/MOPixel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ namespace RTE {
}
}
}

if (m_pScreenEffect) {
SetPostScreenEffectToDraw();
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -261,10 +265,6 @@ namespace RTE {
}

g_SceneMan.RegisterDrawing(targetBitmap, mode == g_DrawNoMOID ? g_NoMOID : m_MOID, pixelPos, 1.0F);

if (mode == g_DrawColor && m_pScreenEffect && !onlyPhysical) {
SetPostScreenEffectToDraw();
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
10 changes: 8 additions & 2 deletions Entities/MOSParticle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ namespace RTE {
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MOSParticle::Update() {
MOSprite::Update();

if (m_pScreenEffect) { SetPostScreenEffectToDraw(); }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MOSParticle::Draw(BITMAP *targetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const {
Expand Down Expand Up @@ -221,8 +229,6 @@ namespace RTE {

g_SceneMan.RegisterDrawing(targetBitmap, mode == g_DrawNoMOID ? g_NoMOID : m_MOID, spriteX, spriteY, spriteX + m_aSprite[m_Frame]->w, spriteY + m_aSprite[m_Frame]->h);
}

if (m_pScreenEffect && mode == g_DrawColor && !onlyPhysical) { SetPostScreenEffectToDraw(); }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
5 changes: 5 additions & 0 deletions Entities/MOSParticle.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ namespace RTE {
/// <returns>Whether the MOSParticle should immediately halt any travel going on after this sinkage.</returns>
bool OnSink(HitData &hd) override { return false; }

/// <summary>
/// Updates this MOParticle. Supposed to be done every frame.
/// </summary>
void Update() override;

/// <summary>
/// Draws this MOSParticle's current graphical representation to a BITMAP of choice.
/// </summary>
Expand Down
Loading

0 comments on commit 08ddaf0

Please sign in to comment.