Skip to content

Commit

Permalink
Bar105 collision avoidance mt (#327)
Browse files Browse the repository at this point in the history
* mt collision avoidance
* fixed race condition on the temp number.
* mt collision avoidence
* fixed race condition on the temp number.
* removed unneeded code.
* tempNums are now saved.
  • Loading branch information
marcushutchings authored Aug 1, 2022
1 parent 96b06d1 commit 5075cc0
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 21 deletions.
4 changes: 4 additions & 0 deletions rts/Sim/Misc/GlobalSynced.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "GlobalSynced.h"

#include <algorithm>
#include <assert.h>
#include <cstring>

Expand Down Expand Up @@ -34,6 +35,7 @@ CR_BIND(CGlobalSynced, )
CR_REG_METADATA(CGlobalSynced, (
CR_MEMBER(frameNum),
CR_MEMBER(tempNum),
CR_MEMBER(mtTempNum),
CR_MEMBER(godMode),

CR_MEMBER(speedFactor),
Expand All @@ -58,6 +60,8 @@ void CGlobalSynced::ResetState() {
tempNum = 1;
godMode = 0;

std::fill(std::begin(mtTempNum), std::end(mtTempNum), 1);

#ifdef SYNCCHECK
// reset checksum
CSyncChecker::NewFrame();
Expand Down
4 changes: 4 additions & 0 deletions rts/Sim/Misc/GlobalSynced.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "System/creg/creg_cond.h"
#include "System/GlobalRNG.h"
#include "System/Threading/ThreadPool.h"


class CGameSetup;
Expand Down Expand Up @@ -38,6 +39,8 @@ class CGlobalSynced
int GetLuaSimFrame() { return (frameNum * (frameNum > 0)); }
int GetTempNum() { return tempNum++; }

int GetMtTempNum() { return mtTempNum[ThreadPool::GetThreadNum()]++; }

// remains true until first SimFrame call
bool PreSimFrame() const { return (frameNum == -1); }

Expand All @@ -49,6 +52,7 @@ class CGlobalSynced
* (increase after each use)
*/
int tempNum = 1;
std::array<int, ThreadPool::MAX_THREADS> mtTempNum = {};

This comment has been minimized.

Copy link
@dzosz

dzosz Aug 5, 2022

Collaborator

hey. not sure if that's relevant in this use case (because this variable is not changed as often) but did you benchmark against false sharing by putting each of these ints on separate cache line?
although based on these benchmarks this might not be an issue https://stackoverflow.com/questions/61672049/why-does-false-sharing-still-affect-non-atomics-but-much-less-than-atomics


public:
/**
Expand Down
59 changes: 46 additions & 13 deletions rts/Sim/Misc/QuadField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Sim/Misc/GlobalConstants.h"
#include "Sim/Misc/TeamHandler.h"
#include "System/ContainerUtil.h"
#include "System/Threading/ThreadPool.h"

#ifndef UNIT_TEST
#include "Sim/Features/Feature.h"
Expand Down Expand Up @@ -121,8 +122,20 @@ void CQuadField::Init(int2 mapDims, int quadSize)
invQuadSize = {1.0f / quadSizeX, 1.0f / quadSizeZ};

baseQuads.resize(numQuadsX * numQuadsZ);
tempQuads.ReserveAll(numQuadsX * numQuadsZ);
tempQuads.ReleaseAll();

int threadCount = ThreadPool::GetNumThreads();
tempQuads.reserve(threadCount);
tempSolids.reserve(threadCount);

for (auto i = 0; i < threadCount; ++i) {
auto newQueryVectorCache = tempQuads.emplace_back();

newQueryVectorCache.ReserveAll(numQuadsX * numQuadsZ);
newQueryVectorCache.ReleaseAll();

tempSolids.emplace_back();
}


#ifndef UNIT_TEST
for (Quad& quad: baseQuads) {
Expand All @@ -142,8 +155,26 @@ void CQuadField::Kill()
tempUnits.ReleaseAll();
tempFeatures.ReleaseAll();
tempProjectiles.ReleaseAll();
tempSolids.ReleaseAll();
tempQuads.ReleaseAll();

for (auto cache : tempSolids) {
cache.ReleaseAll();
}
tempSolids.clear();

for (auto cache : tempQuads) {
cache.ReleaseAll();
}
tempQuads.clear();
}

void CQuadField::ReleaseVector(std::vector<CSolidObject*>* v)
{
tempSolids[ThreadPool::GetThreadNum()].ReleaseVector(v);
}

void CQuadField::ReleaseVector(std::vector<int>* v)
{
tempQuads[ThreadPool::GetThreadNum()].ReleaseVector(v);
}


Expand All @@ -167,7 +198,7 @@ void CQuadField::GetQuads(QuadFieldQuery& qfq, float3 pos, float radius)
{
pos.AssertNaNs();
pos.ClampInBounds();
qfq.quads = tempQuads.ReserveVector();
qfq.quads = tempQuads[ThreadPool::GetThreadNum()].ReserveVector();

const int2 min = WorldPosToQuadField(pos - radius);
const int2 max = WorldPosToQuadField(pos + radius);
Expand Down Expand Up @@ -197,7 +228,7 @@ void CQuadField::GetQuadsRectangle(QuadFieldQuery& qfq, const float3& mins, cons
{
mins.AssertNaNs();
maxs.AssertNaNs();
qfq.quads = tempQuads.ReserveVector();
qfq.quads = tempQuads[ThreadPool::GetThreadNum()].ReserveVector();

const int2 min = WorldPosToQuadField(mins);
const int2 max = WorldPosToQuadField(maxs);
Expand All @@ -224,7 +255,7 @@ void CQuadField::GetQuadsOnRay(QuadFieldQuery& qfq, const float3& start, const f
dir.AssertNaNs();
start.AssertNaNs();

auto& queryQuads = *(qfq.quads = tempQuads.ReserveVector());
auto& queryQuads = *(qfq.quads = tempQuads[ThreadPool::GetThreadNum()].ReserveVector());

const float3 to = start + (dir * length);

Expand Down Expand Up @@ -729,15 +760,17 @@ void CQuadField::GetSolidsExact(
) {
QuadFieldQuery qfQuery;
GetQuads(qfQuery, pos, radius);
const int tempNum = gs->GetTempNum();
qfq.solids = tempSolids.ReserveVector();
const int tempNum = gs->GetMtTempNum();
auto curThread = ThreadPool::GetThreadNum();
qfq.solids = tempSolids[curThread].ReserveVector();


for (const int qi: *qfQuery.quads) {
for (CUnit* u: baseQuads[qi].units) {
if (u->tempNum == tempNum)
if (u->mtTempNum[curThread] == tempNum)
continue;

u->tempNum = tempNum;
u->mtTempNum[curThread] = tempNum;

if (!u->HasPhysicalStateBit(physicalStateBits))
continue;
Expand All @@ -750,10 +783,10 @@ void CQuadField::GetSolidsExact(
}

for (CFeature* f: baseQuads[qi].features) {
if (f->tempNum == tempNum)
if (f->mtTempNum[curThread] == tempNum)
continue;

f->tempNum = tempNum;
f->mtTempNum[curThread] = tempNum;

if (!f->HasPhysicalStateBit(physicalStateBits))
continue;
Expand Down
12 changes: 8 additions & 4 deletions rts/Sim/Misc/QuadField.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,12 @@ class CQuadField : spring::noncopyable
void ReleaseVector(std::vector<CUnit*>* v ) { tempUnits.ReleaseVector(v); }
void ReleaseVector(std::vector<CFeature*>* v ) { tempFeatures.ReleaseVector(v); }
void ReleaseVector(std::vector<CProjectile*>* v ) { tempProjectiles.ReleaseVector(v); }
void ReleaseVector(std::vector<CSolidObject*>* v) { tempSolids.ReleaseVector(v); }
void ReleaseVector(std::vector<int>* v ) { tempQuads.ReleaseVector(v); }

// Ensure release in same thread as original quad field query generated.
void ReleaseVector(std::vector<CSolidObject*>* v); //{ tempSolids.ReleaseVector(v); }

// Ensure release in same thread as original quad field query generated.
void ReleaseVector(std::vector<int>* v );// { tempQuads.ReleaseVector(v); }

struct Quad {
public:
Expand Down Expand Up @@ -242,8 +246,8 @@ class CQuadField : spring::noncopyable
QueryVectorCache<CUnit*> tempUnits;
QueryVectorCache<CFeature*> tempFeatures;
QueryVectorCache<CProjectile*> tempProjectiles;
QueryVectorCache<CSolidObject*> tempSolids;
QueryVectorCache<int> tempQuads;
std::vector< QueryVectorCache<CSolidObject*> > tempSolids;
std::vector< QueryVectorCache<int> > tempQuads;

float2 invQuadSize;

Expand Down
31 changes: 29 additions & 2 deletions rts/Sim/MoveTypes/GroundMoveType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,30 @@ void CGroundMoveType::StopMoving(bool callScript, bool hardStop, bool cancelRaw)
progressState = Done;
}

void CGroundMoveType::UpdateObstacleAvoidance() {
if (owner->GetTransporter() != nullptr)
return;

if (owner->IsSkidding())
return;

if (owner->IsFalling())
return;

if (owner->IsStunned() || owner->beingBuilt)
return;

if (owner->UnderFirstPersonControl())
return;

if (WantToStop())
return;

const float3& ffd = flatFrontDir;
auto wantReverse = WantReverse(waypointDir, ffd);
const float3 rawWantedDir = waypointDir * Sign(int(!wantReverse));
const float3& modWantedDir = GetObstacleAvoidanceDir(mix(ffd, rawWantedDir, !atGoal));
}

bool CGroundMoveType::FollowPath()
{
Expand Down Expand Up @@ -847,10 +871,13 @@ bool CGroundMoveType::FollowPath()
wantReverse = WantReverse(waypointDir, ffd);

// apply obstacle avoidance (steering), prevent unit from chasing its own tail if already at goal
const float3 rawWantedDir = waypointDir * Sign(int(!wantReverse));
const float3& modWantedDir = GetObstacleAvoidanceDir(mix(ffd, rawWantedDir, !atGoal));
// const float3 rawWantedDir = waypointDir * Sign(int(!wantReverse));
// const float3& modWantedDir = GetObstacleAvoidanceDir(mix(ffd, rawWantedDir, !atGoal));

// const float3& modWantedDir = GetObstacleAvoidanceDir(mix(ffd, rawWantedDir, (!atGoal) && (wpProjDists.x > wpProjDists.y || wpProjDists.z < 0.995f)));

const float3& modWantedDir = lastAvoidanceDir;

ChangeHeading(GetHeadingFromVector(modWantedDir.x, modWantedDir.z));
ChangeSpeed(maxWantedSpeed, wantReverse);

Expand Down
2 changes: 2 additions & 0 deletions rts/Sim/MoveTypes/GroundMoveType.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class CGroundMoveType : public AMoveType
bool Update() override;
void SlowUpdate() override;

void UpdateObstacleAvoidance() override;

void StartMovingRaw(const float3 moveGoalPos, float moveGoalRadius) override;
void StartMoving(float3 pos, float moveGoalRadius) override;
void StartMoving(float3 pos, float moveGoalRadius, float speed) override { StartMoving(pos, moveGoalRadius); }
Expand Down
2 changes: 2 additions & 0 deletions rts/Sim/MoveTypes/MoveType.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class AMoveType : public CObject
virtual void SlowUpdate() {};
void UpdateCollisionMap();

virtual void UpdateObstacleAvoidance() {};

virtual bool IsSkidding() const { return false; }
virtual bool IsFlying() const { return false; }
virtual bool IsReversing() const { return false; }
Expand Down
4 changes: 2 additions & 2 deletions rts/Sim/Objects/WorldObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

#include "WorldObject.h"
#include "Rendering/Models/3DModel.h"
#include "System/Threading/ThreadPool.h"

CR_BIND_DERIVED(CWorldObject, CObject, )
CR_REG_METADATA(CWorldObject, (
CR_MEMBER(id),
CR_MEMBER(tempNum),

CR_MEMBER(mtTempNum),
CR_MEMBER(radius),
CR_MEMBER(height),
CR_MEMBER(sqRadius),
Expand All @@ -32,4 +33,3 @@ void CWorldObject::SetRadiusAndHeight(const S3DModel* mdl)
// we always want the (more reliable) auto-calculated DR value
drawRadius = mdl->CalcDrawRadius();
}

4 changes: 4 additions & 0 deletions rts/Sim/Objects/WorldObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "System/Object.h"
#include "System/float4.h"
#include "System/Threading/ThreadPool.h"

struct S3DModel;

Expand Down Expand Up @@ -69,6 +70,9 @@ class CWorldObject: public CObject
S3DModel* model = nullptr;
protected:
float drawRadius = 0.0f; ///< unsynced, used for projectile visibility culling

public:
std::array<int, ThreadPool::MAX_THREADS> mtTempNum = {};
};

#endif /* WORLD_OBJECT_H */
7 changes: 7 additions & 0 deletions rts/Sim/Units/UnitHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,13 @@ void CUnitHandler::UpdateUnitMoveTypes()
{
SCOPED_TIMER("Sim::Unit::MoveType");

for_mt(0, activeUnits.size(), [this](const int i){
CUnit* unit = activeUnits[i];
AMoveType* moveType = unit->moveType;

moveType->UpdateObstacleAvoidance();
});

for (activeUpdateUnit = 0; activeUpdateUnit < activeUnits.size(); ++activeUpdateUnit) {
CUnit* unit = activeUnits[activeUpdateUnit];
AMoveType* moveType = unit->moveType;
Expand Down

0 comments on commit 5075cc0

Please sign in to comment.