From 8a222fdd7c926e041bc2a0923937cd9510b10b3f Mon Sep 17 00:00:00 2001 From: Redacted Date: Fri, 18 Apr 2025 17:45:31 -0400 Subject: [PATCH] Performance optimization --- CMakeLists.txt | 12 +++- include/Engine/types/ConcurrentWorker.h | 24 -------- include/Engine/types/InstancedTexture.h | 24 -------- include/Engine/types/Scene.h | 16 +++--- include/Engine/types/entity/InstancedSprite.h | 6 +- include/Game/scene/ControllableBox.h | 2 +- src/Engine/types/ConcurrentWorker.cpp | 14 ----- src/Engine/types/InstancedTexture.cpp | 31 ---------- src/Engine/types/Scene.cpp | 56 ++++++------------- src/Engine/types/entity/InstancedSprite.cpp | 26 +-------- src/Game/Scene/ControllableBox.cpp | 2 +- 11 files changed, 38 insertions(+), 175 deletions(-) delete mode 100644 include/Engine/types/ConcurrentWorker.h delete mode 100644 include/Engine/types/InstancedTexture.h delete mode 100644 src/Engine/types/ConcurrentWorker.cpp delete mode 100644 src/Engine/types/InstancedTexture.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d58fdc..ebe188e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.28) +cmake_minimum_required(VERSION 3.18..3.28) project(DemoGame VERSION 1.0 LANGUAGES CXX @@ -19,7 +19,12 @@ CPMAddPackage( CPMAddPackage( NAME ReWindow - URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-31.zip + URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-32.zip +) + +CPMAddPackage( + NAME MultiThreading + URL https://git.redacted.cc/Redacted/MultiThreading/archive/prerelease-1.zip ) #set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra") @@ -30,9 +35,10 @@ file(COPY "assets" DESTINATION "${PROJECT_BINARY_DIR}") add_executable(DemoGame ${SOURCES} main.cpp) target_include_directories(DemoGame PUBLIC + ${MultiThreading_SOURCE_DIR}/include ${JGL_SOURCE_DIR}/include ${ReWindow_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include ) -target_link_libraries(DemoGame PUBLIC JGL ReWindowLibrary) +target_link_libraries(DemoGame PUBLIC JGL ReWindowLibrary MultiThreading) diff --git a/include/Engine/types/ConcurrentWorker.h b/include/Engine/types/ConcurrentWorker.h deleted file mode 100644 index 391411b..0000000 --- a/include/Engine/types/ConcurrentWorker.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace Engine { - class ConcurrentWorker; -} - -class Engine::ConcurrentWorker { -private: - std::atomic work_complete{ false }; - std::thread worker_thread; -public: - [[nodiscard]] bool Done(); -public: - ~ConcurrentWorker(); - - template - explicit ConcurrentWorker(Function&& func, Args&&... args) : worker_thread([this, func = std::forward(func), - ...args = std::forward(args)]() mutable { func(std::forward(args) ...); work_complete = true; }) - { worker_thread.detach(); } -}; \ No newline at end of file diff --git a/include/Engine/types/InstancedTexture.h b/include/Engine/types/InstancedTexture.h deleted file mode 100644 index c3aef1f..0000000 --- a/include/Engine/types/InstancedTexture.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include - -namespace Engine { - class InstancedTexture; - class InstancedSprite; -} - -class Engine::InstancedTexture { -protected: - JGL::Texture* texture = nullptr; - std::vector users{}; -public: - [[nodiscard]] size_t ReferenceCount() { return users.size(); } - [[nodiscard]] bool InUseBy(const InstancedSprite* rhs); - [[nodiscard]] JGL::Texture* GetTexture() const { return texture; } -public: - void AddUser(const InstancedSprite* user); - void RemoveUser(const InstancedSprite* user); -public: - InstancedTexture(JGL::Texture* texture, const InstancedSprite* creator) : texture(texture) { users.push_back(creator); } - ~InstancedTexture(); -}; \ No newline at end of file diff --git a/include/Engine/types/Scene.h b/include/Engine/types/Scene.h index 296c1a0..1a7be48 100644 --- a/include/Engine/types/Scene.h +++ b/include/Engine/types/Scene.h @@ -1,13 +1,14 @@ #pragma once #include -#include #include #include #include -#include +#include #include +#include #include +#include "Engine/types/entity/InstancedSprite.h" namespace Engine { class Camera; @@ -24,12 +25,11 @@ protected: // 25ms. u8 tick_rate = 40; bool should_tick = true; - ConcurrentWorker* update_worker; + MultiThreading::Thread* update_worker; std::string name; Camera* active_camera = nullptr; Entity* entity_list = nullptr; - std::vector instanced_textures{}; - std::vector instanced_alpha_masks{}; + std::unordered_map instanced_textures{}; protected: virtual void Update(); virtual void Render(); @@ -38,8 +38,7 @@ public: [[nodiscard]] size_t EntityCount() const; [[nodiscard]] std::string GetName() const; [[nodiscard]] Camera* GetActiveCamera() const; - [[nodiscard]] InstancedTexture* GetInstancedTexture(const InstancedSprite* user); - [[nodiscard]] InstancedTexture* GetInstancedAlphaMask(const InstancedSprite* user); + [[nodiscard]] JGL::Texture* GetInstancedTexture(const InstancedSprite* user); [[nodiscard]] bool ShouldTick() const; [[nodiscard]] float TickDeltaTime() const; [[nodiscard]] float FrameDeltaTime() const; @@ -49,8 +48,7 @@ public: public: void ShouldTick(bool state); void SetActiveCamera(Camera* camera) { active_camera = camera; }; - void DestroyInstancedTexture(const InstancedTexture* itx); - void DestroyInstancedAlphaMask(const InstancedTexture* alpha_mask); + void DestroyInstancedTexture(const InstancedSprite* itx); virtual void Unload(); virtual void Init() {}; void Run(); diff --git a/include/Engine/types/entity/InstancedSprite.h b/include/Engine/types/entity/InstancedSprite.h index dc8629a..1159baa 100644 --- a/include/Engine/types/entity/InstancedSprite.h +++ b/include/Engine/types/entity/InstancedSprite.h @@ -8,12 +8,9 @@ namespace Engine { class Engine::InstancedSprite : public Sprite { private: std::string texture_path; - std::string alpha_mask_path; public: [[nodiscard]] std::string GetTextureFilesystemPath() const { return texture_path; } - [[nodiscard]] std::string GetAlphaMaskFilesystemPath() const { return alpha_mask_path; } [[nodiscard]] Texture* GetTexture() const override; - [[nodiscard]] Texture* GetAlphaMask() const override; public: /** The Texture *must* be instanced. The alpha-mask *can* be instanced. * You can use SetAlphaMask() to change to a unique one. @@ -24,6 +21,5 @@ public: ~InstancedSprite() override; InstancedSprite(const Vector2& position, unsigned int layer, const std::string& instanced_texture_filesystem_path, const Vector2& origin = {0, 0}, float face_angle = 0.0f, const Color4& base_color = Colors::White, Texture* unique_alpha_mask = nullptr, const std::string& instanced_alpha_mask_filesystem_path = "") - : Sprite(position, origin, layer, face_angle, base_color, nullptr, unique_alpha_mask), texture_path(instanced_texture_filesystem_path), - alpha_mask_path(instanced_alpha_mask_filesystem_path) {} + : Sprite(position, origin, layer, face_angle, base_color, nullptr, unique_alpha_mask), texture_path(instanced_texture_filesystem_path) {} }; diff --git a/include/Game/scene/ControllableBox.h b/include/Game/scene/ControllableBox.h index b96ae0f..f811b7a 100644 --- a/include/Game/scene/ControllableBox.h +++ b/include/Game/scene/ControllableBox.h @@ -5,7 +5,7 @@ class ControllableBox final : public Engine::Scene { public: void Init() final; public: - explicit ControllableBox(const std::string& name) : Scene(name) {} + explicit ControllableBox(const std::string& name) : Scene(name, 64) {} }; diff --git a/src/Engine/types/ConcurrentWorker.cpp b/src/Engine/types/ConcurrentWorker.cpp deleted file mode 100644 index d028518..0000000 --- a/src/Engine/types/ConcurrentWorker.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -using namespace Engine; -ConcurrentWorker::~ConcurrentWorker() { - if (!work_complete) { - std::stringstream thread_id; thread_id << worker_thread.get_id(); - Logger::Fatal("ConcurrentWorker was destroyed for thread " + thread_id.str() + " but the work wasn't finished?"); - } -} - -bool ConcurrentWorker::Done() { - return work_complete; -} diff --git a/src/Engine/types/InstancedTexture.cpp b/src/Engine/types/InstancedTexture.cpp deleted file mode 100644 index caa997f..0000000 --- a/src/Engine/types/InstancedTexture.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -using namespace Engine; -void InstancedTexture::AddUser(const InstancedSprite* user) { - // Prevent double references. - if (!InUseBy(user)) - users.push_back(user); -} - -void InstancedTexture::RemoveUser(const InstancedSprite* user) { - auto it = std::find(users.begin(), users.end(), user); - if (it != users.end()) - users.erase(it); -} - -bool InstancedTexture::InUseBy(const InstancedSprite* rhs) { - if (users.empty()) - return false; - - if (typeid(*users[0]) == typeid(*rhs)) - return true; - - return false; -} - -InstancedTexture::~InstancedTexture() { - delete texture; - for (const auto* is: users) - delete is; -} diff --git a/src/Engine/types/Scene.cpp b/src/Engine/types/Scene.cpp index 31b180b..ca30888 100644 --- a/src/Engine/types/Scene.cpp +++ b/src/Engine/types/Scene.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -93,15 +94,11 @@ Scene::~Scene() { void Scene::Unload() { destroying = true; - while (!update_worker->Done()) {} + + for (auto& itx : instanced_textures) + delete itx.second; + delete update_worker; - - for (auto* itx : instanced_textures) - delete itx; - - for (auto* a : instanced_alpha_masks) - delete a; - delete entity_list; delete active_camera; } @@ -114,45 +111,26 @@ Camera* Scene::GetActiveCamera() const { return active_camera; } -InstancedTexture* Scene::GetInstancedTexture(const InstancedSprite* user) { - for (auto* itx : instanced_textures) - if (itx->InUseBy(user)) - return itx; +Texture* Scene::GetInstancedTexture(const InstancedSprite* user) { + auto it = instanced_textures.find(typeid(user).hash_code()); + if (it != instanced_textures.end()) + return it->second; auto* t = new Texture(user->GetTextureFilesystemPath()); - auto* itx = new InstancedTexture(t, user); - instanced_textures.push_back(itx); - return itx; + instanced_textures.insert(std::make_pair(typeid(user).hash_code(), t)); + return t; } -InstancedTexture* Scene::GetInstancedAlphaMask(const InstancedSprite* user) { - for (auto* itx : instanced_alpha_masks) - if (itx->InUseBy(user)) - return itx; - - if (!user->GetAlphaMaskFilesystemPath().empty()) { - auto *t = new Texture(user->GetAlphaMaskFilesystemPath()); - auto *itx = new InstancedTexture(t, user); - instanced_alpha_masks.push_back(itx); - return itx; +void Scene::DestroyInstancedTexture(const InstancedSprite* user) { + auto it = instanced_textures.find(typeid(user).hash_code()); + if (it != instanced_textures.end()) { + delete it->second; + instanced_textures.erase(it); } - return nullptr; -} - -void Scene::DestroyInstancedTexture(const InstancedTexture* itx) { - auto it = std::find(instanced_textures.begin(), instanced_textures.end(), itx); - if (it != instanced_textures.end()) - delete *it, instanced_textures.erase(it); -} - -void Scene::DestroyInstancedAlphaMask(const Engine::InstancedTexture* alpha_mask) { - auto it = std::find(instanced_alpha_masks.begin(), instanced_alpha_masks.end(), alpha_mask); - if (it != instanced_alpha_masks.end()) - delete *it, instanced_alpha_masks.erase(it); } void Scene::Run() { - update_worker = new ConcurrentWorker([this] { UpdateLoop(); }); + update_worker = new MultiThreading::Thread([this] { UpdateLoop(); } ); } bool Scene::ShouldTick() const { diff --git a/src/Engine/types/entity/InstancedSprite.cpp b/src/Engine/types/entity/InstancedSprite.cpp index 58b3fbb..d89a170 100644 --- a/src/Engine/types/entity/InstancedSprite.cpp +++ b/src/Engine/types/entity/InstancedSprite.cpp @@ -3,31 +3,9 @@ using namespace Engine; Texture* InstancedSprite::GetTexture() const { - auto* itx = GetScene()->GetInstancedTexture(this); - if (itx) - return itx->GetTexture(); - return nullptr; -} - -Texture* InstancedSprite::GetAlphaMask() const { - auto* ita = GetScene()->GetInstancedAlphaMask(this); - if (ita) - return ita->GetTexture(); - return Sprite::GetAlphaMask(); + return GetScene()->GetInstancedTexture(this); } InstancedSprite::~InstancedSprite() { - auto* itx = GetScene()->GetInstancedTexture(this); - if (itx) { - itx->RemoveUser(this); - if (itx->ReferenceCount() == 0) - GetScene()->DestroyInstancedTexture(itx); - } - - auto* ita = GetScene()->GetInstancedAlphaMask(this); - if (ita) { - ita->RemoveUser(this); - if (ita->ReferenceCount() == 0) - GetScene()->DestroyInstancedAlphaMask(ita); - } + GetScene()->DestroyInstancedTexture(this); } diff --git a/src/Game/Scene/ControllableBox.cpp b/src/Game/Scene/ControllableBox.cpp index 56dcf7f..248c171 100644 --- a/src/Game/Scene/ControllableBox.cpp +++ b/src/Game/Scene/ControllableBox.cpp @@ -4,7 +4,7 @@ void ControllableBox::Init() { auto* hud = new Game::DemoGameHud(); - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 10000; i++) { auto *b = new Game::Box({0, 0}); entity_list->AppendChild(b); }