Skip to content

Commit

Permalink
Started work on OEPF
Browse files Browse the repository at this point in the history
(One Entity Per File)
  • Loading branch information
ChunkTreasure1 committed Dec 12, 2023
1 parent 1914b0e commit d13c445
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 14 deletions.
120 changes: 108 additions & 12 deletions Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include "Volt/Core/BinarySerializer.h"

#include "Volt/Utility/Algorithms.h"

namespace Volt
{
template<typename T>
Expand Down Expand Up @@ -147,9 +149,10 @@ namespace Volt
streamReader.ExitScope();

const std::filesystem::path& scenePath = filePath;
std::filesystem::path folderPath = scenePath.parent_path();
std::filesystem::path directoryPath = scenePath.parent_path();

LoadSceneLayers(metadata, scene, folderPath);
LoadSceneLayers(metadata, scene, directoryPath);
LoadEntities(metadata, scene, directoryPath);
scene->SortScene();
return true;
}
Expand All @@ -158,13 +161,13 @@ namespace Volt
{
const Ref<Scene> scene = std::reinterpret_pointer_cast<Scene>(asset);

std::filesystem::path folderPath = AssetManager::GetFilesystemPath(metadata.filePath);
if (!std::filesystem::is_directory(folderPath))
std::filesystem::path directoryPath = AssetManager::GetFilesystemPath(metadata.filePath);
if (!std::filesystem::is_directory(directoryPath))
{
folderPath = folderPath.parent_path();
directoryPath = directoryPath.parent_path();
}

std::filesystem::path scenePath = folderPath / (metadata.filePath.stem().string() + ".vtscene");
std::filesystem::path scenePath = directoryPath / (metadata.filePath.stem().string() + ".vtscene");

YAMLStreamWriter streamWriter{ scenePath };
streamWriter.BeginMap();
Expand All @@ -174,7 +177,8 @@ namespace Volt
streamWriter.EndMap();
streamWriter.WriteToDisk();

SaveSceneLayers(metadata, scene, folderPath);
SaveSceneLayers(metadata, scene, directoryPath);
SaveEntities(metadata, scene, directoryPath);
}

void SceneImporter::LoadSceneLayers(const AssetMetadata& metadata, const Ref<Scene>& scene, const std::filesystem::path& sceneDirectory) const
Expand Down Expand Up @@ -218,10 +222,10 @@ namespace Volt
sceneLayer.visible = streamReader.ReadKey("visible", true);
sceneLayer.locked = streamReader.ReadKey("locked", false);

streamReader.ForEach("Entities", [&]()
{
DeserializeEntity(scene, metadata, streamReader);
});
//streamReader.ForEach("Entities", [&]()
//{
// DeserializeEntity(scene, metadata, streamReader);
//});
}
streamReader.ExitScope();
}
Expand Down Expand Up @@ -277,6 +281,98 @@ namespace Volt
}
}

void SceneImporter::SaveEntities(const AssetMetadata& metadata, const Ref<Scene>& scene, const std::filesystem::path& sceneDirectory) const
{
std::filesystem::path entitiesDirectoryPath = sceneDirectory / "Entities";
if (!std::filesystem::exists(entitiesDirectoryPath))
{
std::filesystem::create_directories(entitiesDirectoryPath);
}

const auto entities = scene->GetAllEntities();

Algo::ForEachParallel([entitiesDirectoryPath, entities, metadata, scene, this](uint32_t i)
{
Entity entity = entities.at(i);
const auto entityPath = entitiesDirectoryPath / ("entity_" + entity.ToString() + ".entity");

YAMLStreamWriter streamWriter{ entityPath };
SerializeEntity(entity, metadata, scene, streamWriter);

streamWriter.WriteToDisk();
},
static_cast<uint32_t>(entities.size()));
}

void SceneImporter::LoadEntities(const AssetMetadata& metadata, const Ref<Scene>& scene, const std::filesystem::path& sceneDirectory) const
{
VT_PROFILE_FUNCTION();

std::filesystem::path layersFolderPath = sceneDirectory / "Entities";
if (!std::filesystem::exists(layersFolderPath))
{
return;
}

std::vector<std::filesystem::path> entityPaths;

for (const auto& it : std::filesystem::directory_iterator(layersFolderPath))
{
if (!it.is_directory() && it.path().extension().string() == ".entity")
{
entityPaths.emplace_back(it.path());
}
}

scene->m_registry.reserve(entityPaths.size());

for (auto&& curr : scene->m_registry.storage())
{
curr.second.reserve(entityPaths.size());
}

std::vector<Ref<Scene>> dummyScenes{};

auto futures = Algo::ForEachParallelLockable([&dummyScenes, entityPaths, metadata, this](uint32_t i)
{
Ref<Scene> dummyScene = CreateRef<Scene>();

const auto& path = entityPaths.at(i);

YAMLStreamReader streamReader{};
if (!streamReader.OpenFile(path))
{
return;
}

DeserializeEntity(dummyScene, metadata, streamReader);
dummyScenes.push_back(dummyScene);
},
static_cast<uint32_t>(entityPaths.size()));

for (auto& f : futures)
{
f.wait();
}

for (const auto& dummyScene : dummyScenes)
{
for (const auto& entity : dummyScene->GetAllEntities())
{
Entity realEntity = scene->CreateEntityWithUUID(entity.GetID());
Entity::Copy(entity, realEntity, Volt::EntityCopyFlags::None);
}
}
}

Entity SceneImporter::CreateEntityFromUUIDThreadSafe(EntityID entityId, const Ref<Scene>& scene) const
{
static std::mutex createEntityMutex;
std::scoped_lock lock{ createEntityMutex };

return scene->CreateEntityWithUUID(entityId);
}

void SceneImporter::SerializeEntity(entt::entity id, const AssetMetadata& metadata, const Ref<Scene>& scene, YAMLStreamWriter& streamWriter) const
{
streamWriter.BeginMap();
Expand Down Expand Up @@ -519,7 +615,7 @@ namespace Volt
return;
}

auto entity = scene->CreateEntityWithUUID(entityId);
auto entity = CreateEntityFromUUIDThreadSafe(entityId, scene);

streamReader.ForEach("components", [&]()
{
Expand Down
7 changes: 6 additions & 1 deletion Volt/Volt/src/Volt/Asset/Importers/SceneImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "Volt/Utility/FileIO/YAMLStreamWriter.h"
#include "Volt/Utility/FileIO/YAMLStreamReader.h"

#include <entt.hpp>
#include "Volt/Scene/Entity.h"

#include <thread>
#include <typeindex>
Expand Down Expand Up @@ -45,6 +45,11 @@ namespace Volt
void LoadSceneLayers(const AssetMetadata& metadata, const Ref<Scene>& scene, const std::filesystem::path& sceneDirectory) const;
void SaveSceneLayers(const AssetMetadata& metadata, const Ref<Scene>& scene, const std::filesystem::path& sceneDirectory) const;

void SaveEntities(const AssetMetadata& metadata, const Ref<Scene>& scene, const std::filesystem::path& sceneDirectory) const;
void LoadEntities(const AssetMetadata& metadata, const Ref<Scene>& scene, const std::filesystem::path& sceneDirectory) const;

Entity CreateEntityFromUUIDThreadSafe(EntityID entityId, const Ref<Scene>& scene) const;

void SerializeClass(const uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLStreamWriter& streamWriter, bool isSubComponent) const;
void SerializeArray(const uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLStreamWriter& streamWriter) const;
void SerializeMono(entt::entity id, const Ref<Scene>& scene, YAMLStreamWriter& streamWriter) const;
Expand Down
1 change: 1 addition & 0 deletions Volt/Volt/src/Volt/Core/Threading/ThreadPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace Volt
}

m_hasBeenInitialized = true;
m_threadCount = threadCount;
});
}

Expand Down
3 changes: 3 additions & 0 deletions Volt/Volt/src/Volt/Core/Threading/ThreadPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace Volt

inline const bool Initialized() const { ReadLock lock{ m_mutex }; return m_hasBeenInitialized; }
inline const bool IsRunning() const { ReadLock lock{ m_mutex }; return IsRunningImpl(); }
inline const uint32_t GetThreadCount() const { return m_threadCount; }

private:
inline const bool IsRunningImpl() const
Expand All @@ -37,6 +38,8 @@ namespace Volt
bool m_shouldStop = false;
bool m_shouldCancel = false;

uint32_t m_threadCount = 0;

mutable ThreadSafeQueue<std::function<void()>> m_tasks;
mutable std::once_flag m_onceFlag;
mutable std::shared_mutex m_mutex;
Expand Down
6 changes: 6 additions & 0 deletions Volt/Volt/src/Volt/Math/Math.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,10 @@ namespace Math
{
return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
}

template<typename T>
inline static T DivideRoundUp(const T& numerator, const T& denominator)
{
return (numerator + denominator - T{ 1 }) / denominator;
}
}
2 changes: 1 addition & 1 deletion Volt/Volt/src/Volt/Scene/Entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace Volt

const std::string Entity::ToString() const
{
return std::to_string(static_cast<uint32_t>(m_handle));
return std::to_string(static_cast<uint32_t>(GetComponent<IDComponent>().id));
}

const uint32_t Entity::GetLayerID() const
Expand Down
70 changes: 70 additions & 0 deletions Volt/Volt/src/Volt/Utility/Algorithms.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "vtpch.h"
#include "Algorithms.h"

#include "Volt/Math/Math.h"
#include "Volt/Core/Application.h"
#include "Volt/Core/Threading/ThreadPool.h"

namespace Volt::Algo
{
std::vector<std::future<void>> ForEachParallelLockable(std::function<void(uint32_t)>&& func, uint32_t iterationCount)
{
auto& threadPool = Application::GetThreadPool();

const uint32_t threadCount = std::min(iterationCount, threadPool.GetThreadCount());
const uint32_t perThreadIterationCount = Math::DivideRoundUp(iterationCount, threadCount);

std::vector<std::future<void>> futures;
futures.reserve(threadCount);

uint32_t iterOffset = 0;
for (uint32_t i = 0; i < threadCount; i++)
{
uint32_t currThreadIterationCount = perThreadIterationCount;
if (i == threadCount - 1)
{
currThreadIterationCount = iterationCount - i * perThreadIterationCount;
}

futures.emplace_back(threadPool.SubmitTask([currThreadIterationCount, func, iterOffset]()
{
for (uint32_t iter = 0; iter < currThreadIterationCount; iter++)
{
func(iter + iterOffset);
}
}));

iterOffset += currThreadIterationCount;
}

return futures;
}

void ForEachParallel(std::function<void(uint32_t)>&& func, uint32_t iterationCount)
{
auto& threadPool = Application::GetThreadPool();

const uint32_t threadCount = std::min(iterationCount, threadPool.GetThreadCount());
const uint32_t perThreadIterationCount = Math::DivideRoundUp(iterationCount, threadCount);

uint32_t iterOffset = 0;
for (uint32_t i = 0; i < threadCount; i++)
{
uint32_t currThreadIterationCount = perThreadIterationCount;
if (i == threadCount - 1)
{
currThreadIterationCount = iterationCount - i * perThreadIterationCount;
}

threadPool.SubmitTask([currThreadIterationCount, func, iterOffset]()
{
for (uint32_t iter = 0; iter < currThreadIterationCount; iter++)
{
func(iter + iterOffset);
}
});

iterOffset += currThreadIterationCount;
}
}
}
10 changes: 10 additions & 0 deletions Volt/Volt/src/Volt/Utility/Algorithms.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <functional>


namespace Volt::Algo
{
extern [[nodiscard]] std::vector<std::future<void>> ForEachParallelLockable(std::function<void(uint32_t)>&& func, uint32_t iterationCount);
extern void ForEachParallel(std::function<void(uint32_t)>&& func, uint32_t iterationCount);
}

0 comments on commit d13c445

Please sign in to comment.