Skip to content

Commit

Permalink
Update pathing hash to avoid collisions.
Browse files Browse the repository at this point in the history
  • Loading branch information
marcushutchings committed Nov 26, 2023
1 parent 0966385 commit fca907d
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 32 deletions.
13 changes: 7 additions & 6 deletions rts/Sim/Path/QTPFS/Path.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <algorithm>
#include <vector>

#include "PathDefines.h"
#include "Sim/MoveTypes/MoveDefHandler.h"

#include "System/float3.h"
Expand Down Expand Up @@ -94,16 +95,16 @@ namespace QTPFS {
unsigned int GetNextPointIndex() const { return nextPointIndex; }
unsigned int GetNumPathUpdates() const { return numPathUpdates; }

void SetHash(std::uint64_t hash) { this->hash = hash; }
void SetVirtualHash(std::uint64_t virtualHash) { this->virtualHash = virtualHash; }
void SetHash(PathHashType hash) { this->hash = hash; }
void SetVirtualHash(PathHashType virtualHash) { this->virtualHash = virtualHash; }
void SetRadius(float radius) { this->radius = radius; }
void SetSynced(bool synced) { this->synced = synced; }
void SetHasFullPath(bool fullPath) { this->haveFullPath = fullPath; }
void SetHasPartialPath(bool partialPath) { this->havePartialPath = partialPath; }

float GetRadius() const { return radius; }
std::uint64_t GetHash() const { return hash; }
std::uint64_t GetVirtualHash() const { return virtualHash; }
PathHashType GetHash() const { return hash; }
PathHashType GetVirtualHash() const { return virtualHash; }
bool IsSynced() const { return synced; }
bool IsFullPath() const { return haveFullPath; }
bool IsPartialPath() const { return havePartialPath; }
Expand Down Expand Up @@ -246,14 +247,14 @@ namespace QTPFS {

// Identifies the layer, target quad and source quad for a search query so that similar
// searches can be combined.
std::uint64_t hash = -1;
PathHashType hash = BAD_HASH;

// Similar to hash, but the target quad and source quad numbers may not relate to actual
// leaf nodes in the quad tree. They repesent the quad that would be there if the leaf node
// was exactly the size of QTPFS_PARTIAL_SHARE_PATH_MAX_SIZE. This allows searches that
// start and/or end in different, but close, quads. This is used to handle partially-
// shared path searches.
std::uint64_t virtualHash = -1;
PathHashType virtualHash = BAD_HASH;
float radius = 0.f;
bool synced = true;
bool haveFullPath = true;
Expand Down
32 changes: 32 additions & 0 deletions rts/Sim/Path/QTPFS/PathDefines.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef QTPFS_DEFINES_HDR
#define QTPFS_DEFINES_HDR

#include <cstdint>
#include <limits>

// #define QTPFS_NO_LOADSCREEN
Expand Down Expand Up @@ -34,6 +35,37 @@

namespace QTPFS {
constexpr int SEARCH_DIRS = 2;

struct PathHashType {
private:
uint64_t low;
uint64_t high;
public:
PathHashType()
: low(0)
, high(0)
{}

constexpr PathHashType(uint64_t _low, uint64_t _high)
: low(_low)
, high(_high)
{}

bool operator==(const PathHashType& other) const {
return (high == other.high) ? (low == other.low) : false;
}

bool operator!=(const PathHashType& other) const {
return (high != other.high) ? true : (low != other.low);
}

bool operator<(const PathHashType& other) const {
return (high < other.high) ? true : ((high == other.high) ? (low < other.low) : false);
}
};

constexpr uint64_t BAD_HASH_PART = std::numeric_limits<std::uint64_t>::max();
constexpr PathHashType BAD_HASH{BAD_HASH_PART, BAD_HASH_PART};
}

#endif
Expand Down
15 changes: 8 additions & 7 deletions rts/Sim/Path/QTPFS/PathManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ void QTPFS::PathManager::UpdateNodeLayer(unsigned int layerNum, const SRectangle
assert(re.x1 <= r.x1);
assert(re.z1 <= r.z1);
assert(re.x2 >= r.x2);
assert(re.z2 >= r.z2); // TODO: re can be dropped?
assert(re.z2 >= r.z2);

// { bool printMoveInfo = (selectedUnitsHandler.selectedUnits.size() == 1);
// if (printMoveInfo) {
Expand Down Expand Up @@ -765,6 +765,7 @@ bool QTPFS::PathManager::InitializeSearch(entt::entity searchEntity) {
if (registry.valid(pathEntity)) {
assert(registry.all_of<IPath>(pathEntity));
IPath* path = &registry.get<IPath>(pathEntity);
assert(path->GetPathType() == pathType);
search->Initialize(&nodeLayer, path->GetSourcePoint(), path->GetTargetPoint(), path->GetOwner());
path->SetHash(search->GetHash());
path->SetVirtualHash(search->GetPartialSearchHash());
Expand All @@ -774,7 +775,7 @@ bool QTPFS::PathManager::InitializeSearch(entt::entity searchEntity) {
// assert(search->GetPartialSearchHash() == path->GetVirtualHash());

if (path->IsSynced()) {
if (search->GetHash() != PathSearch::BAD_HASH) {
if (search->GetHash() != QTPFS::BAD_HASH) {
assert(!registry.all_of<SharedPathChain>(pathEntity));
SharedPathMap::iterator sharedPathsIt = sharedPaths.find(path->GetHash());
if (sharedPathsIt == sharedPaths.end()) {
Expand All @@ -784,8 +785,8 @@ bool QTPFS::PathManager::InitializeSearch(entt::entity searchEntity) {
linkedListHelper.InsertChain<SharedPathChain>(sharedPaths[path->GetHash()], pathEntity);
}
}
if (search->GetPartialSearchHash() != PathSearch::BAD_HASH) {
assert(path->GetVirtualHash() != PathSearch::BAD_HASH);
if (search->GetPartialSearchHash() != QTPFS::BAD_HASH) {
assert(path->GetVirtualHash() != QTPFS::BAD_HASH);
assert(!registry.all_of<PartialSharedPathChain>(pathEntity));
PartialSharedPathMap::iterator partialSharedPathsIt = partialSharedPaths.find(path->GetVirtualHash());
if (partialSharedPathsIt == partialSharedPaths.end()) {
Expand Down Expand Up @@ -956,7 +957,7 @@ bool QTPFS::PathManager::ExecuteSearch(
{
PartialSharedPathMap::const_iterator partialSharedPathsIt = partialSharedPaths.find(path->GetVirtualHash());
if (partialSharedPathsIt != partialSharedPaths.end()) {
assert(path->GetVirtualHash() != PathSearch::BAD_HASH);
assert(path->GetVirtualHash() != QTPFS::BAD_HASH);
partialChainHeadEntity = partialSharedPathsIt->second;
if (partialChainHeadEntity != pathEntity) {
bool pathIsCopyable = !registry.all_of<PathSearchRef>(partialChainHeadEntity);
Expand Down Expand Up @@ -1177,7 +1178,7 @@ unsigned int QTPFS::PathManager::RequeueSearch(
RemovePathFromShared(pathEntity);
RemovePathFromPartialShared(pathEntity);

oldPath->SetHash(PathSearch::BAD_HASH);
oldPath->SetHash(QTPFS::BAD_HASH);
oldPath->SetNextPointIndex(0);
// oldPath->SetNumPathUpdates(oldPath->GetNumPathUpdates() + 1);

Expand Down Expand Up @@ -1277,7 +1278,7 @@ void QTPFS::PathManager::RemovePathFromPartialShared(entt::entity entity) {

// case: when entity is at the head of the chain.
if (iter != partialSharedPaths.end() && iter->second == entity) {
assert(path->GetVirtualHash() != PathSearch::BAD_HASH);
assert(path->GetVirtualHash() != QTPFS::BAD_HASH);
auto& chain = registry.get<PartialSharedPathChain>(entity);
if (chain.next == entity) {
partialSharedPaths.erase(path->GetVirtualHash());
Expand Down
8 changes: 4 additions & 4 deletions rts/Sim/Path/QTPFS/PathManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ namespace QTPFS {
typedef spring::unordered_map<unsigned int, unsigned int>::iterator PathTypeMapIt;
typedef spring::unordered_map<unsigned int, PathSearchTrace::Execution*> PathTraceMap;
typedef spring::unordered_map<unsigned int, PathSearchTrace::Execution*>::iterator PathTraceMapIt;
typedef spring::unordered_map<std::uint64_t, entt::entity> SharedPathMap;
typedef spring::unordered_map<std::uint64_t, entt::entity>::iterator SharedPathMapIt;
typedef spring::unordered_map<std::uint64_t, entt::entity> PartialSharedPathMap;
typedef spring::unordered_map<std::uint64_t, entt::entity>::iterator PartialSharedPathMapIt;
typedef spring::unordered_map<PathHashType, entt::entity> SharedPathMap;
typedef spring::unordered_map<PathHashType, entt::entity>::iterator SharedPathMapIt;
typedef spring::unordered_map<PathHashType, entt::entity> PartialSharedPathMap;
typedef spring::unordered_map<PathHashType, entt::entity>::iterator PartialSharedPathMapIt;

typedef std::vector<PathSearch*> PathSearchVect;
typedef std::vector<PathSearch*>::iterator PathSearchVectIt;
Expand Down
17 changes: 11 additions & 6 deletions rts/Sim/Path/QTPFS/PathSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ void QTPFS::PathSearch::LoadPartialPath(IPath* path) {
ZoneScoped;
auto& nodes = path->GetNodeList();

assert(path->GetPathType() == pathType);

searchEarlyDrop = false;

auto addNode = [this](uint32_t dir, uint32_t nodeId, uint32_t prevNodeId, const float2& netPoint, uint32_t stepIndex){
Expand Down Expand Up @@ -1171,6 +1173,9 @@ void QTPFS::PathSearch::SmoothSharedPath(IPath* path) {

assert(n0->pathPointIndex > -1);

assert(n0->nodeId < nodeLayer->GetMaxNodesAlloced());
assert(n1->nodeId < nodeLayer->GetMaxNodesAlloced());

INode* nn0 = nodeLayer->GetPoolNode(n0->nodeId);
INode* nn1 = nodeLayer->GetPoolNode(n1->nodeId);

Expand Down Expand Up @@ -1349,7 +1354,7 @@ unsigned int GetChildId(uint32_t nodeNumber, uint32_t i, uint32_t rootMask) {
return rootId | ((nodeId << 2) + (i + 1));
}

const std::uint64_t QTPFS::PathSearch::GenerateHash(const INode* srcNode, const INode* tgtNode) const {
const QTPFS::PathHashType QTPFS::PathSearch::GenerateHash(const INode* srcNode, const INode* tgtNode) const {
uint32_t nodeSize = srcNode->xsize();

if (rawPathCheck)
Expand All @@ -1376,7 +1381,7 @@ const std::uint64_t QTPFS::PathSearch::GenerateHash(const INode* srcNode, const
return GenerateHash2(srcNodeNumber, tgtNode->GetNodeNumber());
}

const std::uint64_t QTPFS::PathSearch::GenerateVirtualHash(const INode* srcNode, const INode* tgtNode) const {
const QTPFS::PathHashType QTPFS::PathSearch::GenerateVirtualHash(const INode* srcNode, const INode* tgtNode) const {
uint32_t srcNodeSize = srcNode->xsize();
uint32_t tgtNodeSize = tgtNode->xsize();

Expand Down Expand Up @@ -1410,11 +1415,11 @@ const std::uint64_t QTPFS::PathSearch::GenerateVirtualHash(const INode* srcNode,
return GenerateHash2(vSrcNodeId, vTgtNodeId);
}

const std::uint64_t QTPFS::PathSearch::GenerateHash2(uint32_t src, uint32_t dest) const {
std::uint64_t N = mapDims.mapx * mapDims.mapy;
std::uint32_t k = nodeLayer->GetNodelayer();
const QTPFS::PathHashType QTPFS::PathSearch::GenerateHash2(uint32_t src, uint32_t dest) const {
std::uint64_t k = nodeLayer->GetNodelayer();
PathHashType result(std::uint64_t(src) + ((std::uint64_t(dest) << 32)), k);

return (src + (dest * N) + (k * N * N));
return result;
}

const std::uint32_t QTPFS::PathSearch::GenerateVirtualNodeNumber(const INode* startNode, int nodeMaxSize, int x, int z) const {
Expand Down
16 changes: 7 additions & 9 deletions rts/Sim/Path/QTPFS/PathSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ namespace QTPFS {
bool SharedFinalize(const IPath* srcPath, IPath* dstPath);
PathSearchTrace::Execution* GetExecutionTrace() { return searchExec; }

const std::uint64_t GetHash() const { return pathSearchHash; };
const std::uint64_t GetPartialSearchHash() const { return pathPartialSearchHash; };
const PathHashType GetHash() const { return pathSearchHash; };
const PathHashType GetPartialSearchHash() const { return pathPartialSearchHash; };

bool PathWasFound() const { return haveFullPath | havePartPath; }

Expand Down Expand Up @@ -163,24 +163,24 @@ namespace QTPFS {

void SetForwardSearchLimit();

const std::uint64_t GenerateHash(const INode* srcNode, const INode* tgtNode) const;
const std::uint64_t GenerateHash2(uint32_t p1, uint32_t p2) const;
const PathHashType GenerateHash(const INode* srcNode, const INode* tgtNode) const;
const PathHashType GenerateHash2(uint32_t p1, uint32_t p2) const;

const std::uint64_t GenerateVirtualHash(const INode* srcNode, const INode* tgtNode) const;
const PathHashType GenerateVirtualHash(const INode* srcNode, const INode* tgtNode) const;
const std::uint32_t GenerateVirtualNodeNumber(const INode* startNode, int nodeMaxSize, int x, int z) const;

QTPFS::SearchThreadData* searchThreadData;

// Identifies the layer, target quad and source quad for a search query so that similar
// searches can be combined.
std::uint64_t pathSearchHash;
PathHashType pathSearchHash;

// Similar to hash, but the target quad and source quad numbers may not relate to actual
// leaf nodes in the quad tree. They repesent the quad that would be there if the leaf node
// was exactly the size of QTPFS_PARTIAL_SHARE_PATH_MAX_SIZE. This allows searches that
// start and/or end in different, but close, quads. This is used to handle partially-
// shared path searches.
std::uint64_t pathPartialSearchHash;
PathHashType pathPartialSearchHash;

const CSolidObject* pathOwner;
NodeLayer* nodeLayer;
Expand Down Expand Up @@ -226,8 +226,6 @@ namespace QTPFS {

bool fwdPathConnected = false;
bool bwdPathConnected = false;

static constexpr std::uint64_t BAD_HASH = std::numeric_limits<std::uint64_t>::max();
};
}

Expand Down

0 comments on commit fca907d

Please sign in to comment.