Skip to content

Commit

Permalink
Replace PriorityQueue class with it's stl equivalent (#218)
Browse files Browse the repository at this point in the history
* replace PriorityQueue class with stl priority queue

* delete old PriorityQueue class and it's tests

* replace priority_queue push with emplace

* add using keyword for long declarations

* replace emplace with push when not constructing element in place

* replace unneeded assignments with DISCARD

* remove std::make_pair when not needed

* replace priority queue empty with std::swap

* fix swap call

* add new wrapper class of priority_queue with clear method

* add missing std::

* fix compile errors

* fix misstypes

* fix clear method compile errors

* update priority queue templates

* add priority queue tests

* fix priority queue comparator in tests

* fix loops

* fix spelling errors

* fix compile errors

* fix comparsion errors

* change default priority queue predicament from lesser to greater

* add missing comparator

* change back default predicament from greater to less

* change priority queue comparator from less to greater
  • Loading branch information
GGiter authored Mar 29, 2020
1 parent 290916a commit 5098ee7
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 150 deletions.
1 change: 1 addition & 0 deletions PolyEngine/Core/Src/pe/Defines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
#include <cstddef>
#include <vector>
#include <deque>
#include <queue>
#include <future>
#include <optional>

Expand Down
143 changes: 58 additions & 85 deletions PolyEngine/Core/Src/pe/core/storage/PriorityQueue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,109 +2,82 @@

#include <pe/Defines.hpp>


namespace pe::core::storage
{
template<typename T>
struct DefaultCmp
{
bool operator()(const T& a, const T& b) const { return a < b; }
};


template <typename T, typename Less = DefaultCmp<T>>
class PriorityQueue final : BaseObjectLiteralType<>
template<class Ty,class Pr = std::greater<typename std::vector<Ty>::value_type> >
class PriorityQueue final : public std::priority_queue<Ty,std::vector<Ty>,Pr>
{
public:
PriorityQueue(size_t prealocatedSize = 0) { Data.reserve(prealocatedSize); }
PriorityQueue(Less lessCmp, size_t prealocatedSize = 0) : LessCmp(std::move(lessCmp)) { Data.reserve(prealocatedSize);}
PriorityQueue(std::vector<T> data) : Data(std::move(data))

PriorityQueue()
: std::priority_queue<Ty, std::vector<Ty>, Pr>()
{
for (size_t idx = Data.size() / 2; idx > 0; --idx)
SiftDown(idx - 1);
}

void Push(T val)
{
Data.push_back(std::move(val));
SiftUp(Data.size() - 1);
PriorityQueue(const std::vector<Ty>& _Cont)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(Pr(), _Cont)
{
}

T Pop()
{
T& first = Data[0];
T& last = Data[GetSize() - 1];
T tmp = std::move(first);
Swap(first, last);
Data.pop_back();
SiftDown(0);
return tmp;
PriorityQueue(const Pr& Pred, const std::vector<Ty>& _Cont)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(Pred,_Cont)
{
}

void Clear() { Data.clear(); }

const T& Head() const { return Data[0]; }
size_t GetSize() const { return Data.size(); }
void Reserve(size_t size) { Data.reserve(size); }
private:
void SiftUp(size_t idx)
explicit PriorityQueue(const Pr& Pred)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(Pred)
{
while (idx > 0)
{
T& val = Data[idx];
const size_t parentIdx = GetParent(idx);
T& parent = Data[parentIdx];
if (!LessCmp(val, parent))
break;

Swap(val, parent);
idx = parentIdx;
}
}

void SiftDown(size_t idx)
{
while (idx < GetSize())
{
const size_t leftChild = GetLeftChild(idx);
const size_t rightChild = GetRightChild(idx);

const bool leftOk = leftChild < GetSize();
const bool rightOk = rightChild < GetSize();

if (!leftOk && !rightOk)
return;

T& val = Data[idx];
// assign val, simple trick to bypass null reference limitations
T* left = leftOk ? &Data[leftChild] : nullptr;
T* right = rightOk ? &Data[rightChild] : nullptr;

const bool rightBetter = !leftOk || (rightOk && LessCmp(*right, *left));
T* candidate = rightBetter ? right : left;

if (candidate && LessCmp(*candidate, val))
{
Swap(val, *candidate);
idx = rightBetter ? rightChild : leftChild;
}
else
return;
}

template<class InIt>
PriorityQueue(InIt _First, InIt _Last)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(_First,_Last)
{
}

inline void Swap(T& a, T& b)
{
T tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
template<class InIt>
PriorityQueue(InIt _First, InIt _Last, const Pr& Pred)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(_First,_Last,Pred)
{
}

inline size_t GetParent(size_t node) { return (node - 1) / 2; }
inline size_t GetLeftChild(size_t node) { return 2 * node + 1; }
inline size_t GetRightChild(size_t node) { return 2 * node + 2; }

template<class Alloc,
class = std::enable_if_t<std::uses_allocator_v<std::vector<Ty>, Alloc>>>
explicit PriorityQueue(const Alloc& _Al)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(_Al)
{
}

Less LessCmp;
std::vector<T> Data;
template<class Alloc,
class = std::enable_if_t<std::uses_allocator_v<std::vector<Ty>, Alloc>>>
PriorityQueue(const Pr& Pred, const Alloc& _Al)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(Pred,_Al)
{
}

template<class Alloc,
class = std::enable_if_t<std::uses_allocator_v<std::vector<Ty>, Alloc>>>
PriorityQueue(const std::priority_queue<Ty, std::vector<Ty>, Pr>& _Right, const Alloc& _Al)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(_Right,_Al)
{
}


template<class Alloc,
class = std::enable_if_t<std::uses_allocator_v<std::vector<Ty>, Alloc>>>
PriorityQueue(std::priority_queue<Ty, std::vector<Ty>, Pr>&& _Right, const Alloc& _Al)
: std::priority_queue<Ty, std::vector<Ty>, Pr>(_Right,_Al)
{
}


void clear()
{
this->c.clear();
}
};
} //namespace Poly
}

Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void IndexedStringManager::scheduleErase(const IndexedStringEntry* entry)
HEAVY_ASSERTE(entry->getRemovalTimePoint().value_or(0) <= removalTimePoint,
"Cannot set removal time point to a previous one than already set!");
entry->setRemovalTimePoint(removalTimePoint);
m_ttlEntries.Push(TTLEntry{removalTimePoint, entry});
m_ttlEntries.emplace(TTLEntry{removalTimePoint, entry});
}

void IndexedStringManager::erase(const IndexedStringEntry* entry)
Expand All @@ -70,7 +70,7 @@ void IndexedStringManager::setTTLMode(bool enabled)
{
if(m_ttlEnabled && !enabled)
{
m_ttlEntries.Clear();
m_ttlEntries.clear();
}
m_ttlEnabled = enabled;
}
Expand All @@ -88,9 +88,10 @@ void IndexedStringManager::tickTTL(size_t ttlTickCount)

m_tickCount += ttlTickCount;

while(m_ttlEntries.GetSize() > 0 && m_ttlEntries.Head().m_scheduledTimePoint <= m_tickCount)
while(m_ttlEntries.size() > 0 && m_ttlEntries.top().m_scheduledTimePoint <= m_tickCount)
{
auto entry = m_ttlEntries.Pop().m_entry;
auto entry = m_ttlEntries.top().m_entry;
m_ttlEntries.pop();
auto realRemovalTimePoint = entry->getRemovalTimePoint();
if (realRemovalTimePoint.value_or(m_tickCount+1) <= m_tickCount)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct TTLEntry
const IndexedStringEntry* m_entry;

bool operator<(const TTLEntry& rhs) const { return m_scheduledTimePoint < rhs.m_scheduledTimePoint; }
bool operator>(const TTLEntry& rhs) const { return m_scheduledTimePoint > rhs.m_scheduledTimePoint; }
};

class CORE_DLLEXPORT IndexedStringManager final : public core::BaseObjectLiteralType<>
Expand Down
13 changes: 7 additions & 6 deletions PolyEngine/Engine/Src/AI/PathfindingSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ std::optional<std::vector<::pe::core::math::Vector>> CalculateNewPath(const NavG
std::map<const NavNode*, float> minCosts;

AllNodes.push_back(PathNode(startNode, 0, graph->GetHeuristicCost(startNode, destNode) ));
openList.Push(std::make_pair(AllNodes.size() - 1, graph->GetHeuristicCost(startNode, destNode)));
openList.emplace(AllNodes.size() - 1, graph->GetHeuristicCost(startNode, destNode));
minCosts.emplace(startNode, 0.f);

i64 bestNodeIdx = -1;
std::vector<const NavNode*> connections(8);
while (openList.GetSize() > 0 && bestNodeIdx < 0)
while (openList.size() > 0 && bestNodeIdx < 0)
{
i64 qIdx = openList.Pop().first;

i64 qIdx = openList.top().first;
openList.pop();

connections.clear();
graph->GetConnections(AllNodes[qIdx].Node, connections);
for (const NavNode* connection : connections)
Expand All @@ -70,11 +71,11 @@ std::optional<std::vector<::pe::core::math::Vector>> CalculateNewPath(const NavG
continue; // node has worse base cost than other (in the same pos) we visited before, skip it

AllNodes.push_back(s);
openList.Push(std::make_pair(AllNodes.size() - 1, s.TotalCost()));
openList.emplace(AllNodes.size() - 1, s.TotalCost());
minCosts[s.Node] = s.Cost;
}

closedList.Push(std::make_pair(qIdx, AllNodes[qIdx].TotalCost()));
closedList.emplace(qIdx, AllNodes[qIdx].TotalCost());
minCosts[AllNodes[qIdx].Node] = AllNodes[qIdx].Cost;
}

Expand Down
1 change: 1 addition & 0 deletions PolyEngine/Engine/Src/EnginePCH.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <pe/core/storage/Queue.hpp>
#include <pe/core/storage/PriorityQueue.hpp>


// Other
#include <pe/core/math/Color.hpp>
#include <pe/core/utils/FileIO.hpp>
Expand Down
17 changes: 10 additions & 7 deletions PolyEngine/Engine/Src/Resources/MeshResource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

using namespace Poly;

using PairQueue = core::storage::PriorityQueue<std::pair<u8, float>,std::function<bool(const std::pair<u8, float>&, const std::pair<u8, float>&)>>;

RTTI_DEFINE_TYPE(Poly::MeshResource)

core::math::Matrix MatFromAiMat(const aiMatrix4x4& m)
Expand Down Expand Up @@ -150,9 +152,9 @@ void MeshResource::SubMesh::LoadBones(aiMesh* mesh)
if (mesh->HasBones())
{
ASSERTE((i8)mesh->mNumBones <= std::numeric_limits<typename decltype(MeshData.BoneIds)::value_type::ValueType>::max(), "Model has too many bones!");

std::vector<::pe::core::storage::PriorityQueue<std::pair<u8, float>, std::function<bool(const std::pair<u8, float>&, const std::pair<u8, float>&)>>> tmpBonesList;
tmpBonesList.resize(mesh->mNumVertices, { [](const std::pair<u8, float>& v1, const std::pair<u8, float>& v2) { return v1.second > v2.second; } });
std::vector<PairQueue> tmpBonesList;
tmpBonesList.resize(mesh->mNumVertices, { PairQueue([](const std::pair<u8, float>& v1, const std::pair<u8, float>& v2) { return v1.second > v2.second; })});

std::map<::pe::core::storage::String, size_t> nameToBoneIdx;

Expand All @@ -169,7 +171,7 @@ void MeshResource::SubMesh::LoadBones(aiMesh* mesh)
const auto& vertWeight = bone->mWeights[j];
size_t vertId = vertWeight.mVertexId;
float weight = vertWeight.mWeight;
tmpBonesList[vertId].Push({ boneId, weight });
tmpBonesList[vertId].emplace( boneId, weight );
}
}
}
Expand All @@ -182,11 +184,12 @@ void MeshResource::SubMesh::LoadBones(aiMesh* mesh)

for (size_t vertId = 0; vertId < mesh->mNumVertices; ++vertId)
{
auto& boneQueue = tmpBonesList[vertId];
PairQueue& boneQueue = tmpBonesList[vertId];
float sum = 0.f;
for (size_t k = 0; k < 4 && boneQueue.GetSize() > 0; ++k)
for (size_t k = 0; k < 4 && boneQueue.size() > 0; ++k)
{
auto entry = boneQueue.Pop();
auto entry = boneQueue.top();
boneQueue.pop();
sum += entry.second;
MeshData.BoneIds[vertId].Data[k] = entry.first;
MeshData.BoneWeights[vertId].Data[k] = entry.second;
Expand Down
13 changes: 6 additions & 7 deletions PolyEngine/RenderingDevice/OpenGL/Src/GLWorldRendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <GLRenderingDevice.hpp>

#include <algorithm> // std::min

#include <pe/core/storage/PriorityQueue.hpp>
#include <Proxy/GLTextFieldBufferDeviceProxy.hpp>
#include <Proxy/GLTextureDeviceProxy.hpp>
#include <Pipeline/RenderingPassBase.hpp>
Expand Down Expand Up @@ -82,18 +82,18 @@ void GLRenderingDevice::FillSceneView(SceneView& sceneView)
{
if (meshCmp->GetBlendingMode() == eBlendingMode::OPAUQE)
{
sceneView.OpaqueQueue.Push(meshCmp);
sceneView.OpaqueQueue.push(meshCmp);
}
else if (meshCmp->GetBlendingMode() == eBlendingMode::TRANSLUCENT)
{
sceneView.TranslucentQueue.Push(meshCmp);
sceneView.TranslucentQueue.push(meshCmp);
}
}
}

for (const auto& [particleCmp] : sceneView.SceneData->IterateComponents<ParticleComponent>())
{
sceneView.ParticleQueue.Push(particleCmp);
sceneView.ParticleQueue.push(particleCmp);
}

for (const auto& [dirLightCmp] : sceneView.SceneData->IterateComponents<DirectionalLightComponent>())
Expand Down Expand Up @@ -237,13 +237,12 @@ void GLRenderingDevice::CullShadowCasters(SceneView& sceneView, const core::math

// find all meshes that are inside extended DirLights AABB box
core::math::Vector dirLightPos = sceneView.DirectionalLightList[0]->GetTransform().GetGlobalTranslation();
MeshQueue shadowCasterQueue(SceneView::DistanceToCameraComparator(dirLightPos, SceneView::eSortOrderType::FRONT_TO_BACK), 0);

MeshQueue shadowCasterQueue(SceneView::DistanceToCameraComparator(dirLightPos, SceneView::eSortOrderType::FRONT_TO_BACK));
for (auto& [box, meshCmp] : boxMeshes)
{
if (frustumAABBInLS.Contains(box))
{
shadowCasterQueue.Push(meshCmp);
shadowCasterQueue.push(meshCmp);

if (sceneView.SettingsCmp && sceneView.SettingsCmp->DebugDrawShadowCastersBounds)
DebugDrawSystem::DrawBox(scene, box.GetMin(), box.GetMax(), worldFromDirLight, core::math::Color::GREEN);
Expand Down
17 changes: 9 additions & 8 deletions PolyEngine/RenderingDevice/OpenGL/Src/IRendererInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <Rendering/Viewport.hpp>
#include <Rendering/Lighting/LightSourceComponent.hpp>
#include <Rendering/RenderingSettingsComponent.hpp>
#include <pe/core/storage/PriorityQueue.hpp>

// TODO: inherit from BaseRenderPass - make multipass RenderPass

Expand Down Expand Up @@ -54,10 +55,10 @@ namespace Poly {

SceneView(Scene* s, Viewport& v)
: SceneData(s), ViewportData(v), Rect(v.GetRect()), CameraCmp(v.GetCamera()),
DirShadowCastersQueue(DistanceToCameraComparator(::pe::core::math::Vector::ZERO, eSortOrderType::FRONT_TO_BACK), 0), // filled by GLRenderingDevice::CullShadowCasters
OpaqueQueue(DistanceToCameraComparator(v.GetCamera()->GetTransform().GetGlobalTranslation(), eSortOrderType::FRONT_TO_BACK), 0),
TranslucentQueue(DistanceToCameraComparator(v.GetCamera()->GetTransform().GetGlobalTranslation(), eSortOrderType::BACK_TO_FRONT), 0),
ParticleQueue(DistanceToCameraComparator(v.GetCamera()->GetTransform().GetGlobalTranslation(), eSortOrderType::BACK_TO_FRONT), 0)
DirShadowCastersQueue(DistanceToCameraComparator(::pe::core::math::Vector::ZERO, eSortOrderType::FRONT_TO_BACK)), // filled by GLRenderingDevice::CullShadowCasters
OpaqueQueue(DistanceToCameraComparator(v.GetCamera()->GetTransform().GetGlobalTranslation(), eSortOrderType::FRONT_TO_BACK)),
TranslucentQueue(DistanceToCameraComparator(v.GetCamera()->GetTransform().GetGlobalTranslation(), eSortOrderType::BACK_TO_FRONT)),
ParticleQueue(DistanceToCameraComparator(v.GetCamera()->GetTransform().GetGlobalTranslation(), eSortOrderType::BACK_TO_FRONT))
{
SettingsCmp = s->GetWorldComponent<RenderingSettingsComponent>();
};
Expand All @@ -69,10 +70,10 @@ namespace Poly {
const CameraComponent* CameraCmp;
const RenderingSettingsComponent* SettingsCmp;

::pe::core::storage::PriorityQueue<const MeshRenderingComponent*, DistanceToCameraComparator> DirShadowCastersQueue;
::pe::core::storage::PriorityQueue<const MeshRenderingComponent*, DistanceToCameraComparator> OpaqueQueue;
::pe::core::storage::PriorityQueue<const MeshRenderingComponent*, DistanceToCameraComparator> TranslucentQueue;
::pe::core::storage::PriorityQueue<const ParticleComponent*, DistanceToCameraComparator> ParticleQueue; // TODO: make translucent and particles one queue with common priority
core::storage::PriorityQueue<const MeshRenderingComponent*, DistanceToCameraComparator> DirShadowCastersQueue;
core::storage::PriorityQueue<const MeshRenderingComponent*, DistanceToCameraComparator> OpaqueQueue;
core::storage::PriorityQueue<const MeshRenderingComponent*, DistanceToCameraComparator> TranslucentQueue;
core::storage::PriorityQueue<const ParticleComponent*, DistanceToCameraComparator> ParticleQueue; // TODO: make translucent and particles one queue with common priority

::pe::core::math::AABox DirShadowAABBInLS;
std::vector<const DirectionalLightComponent*> DirectionalLightList;
Expand Down
Loading

0 comments on commit 5098ee7

Please sign in to comment.