From 53b39913e550c874b976199b97799f8d63311613 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 4 Jun 2025 19:22:28 +0200 Subject: [PATCH] fixing multithreading --- Application/ThreadPool.cpp | 37 ------------------------ Application/ThreadPool.h | 32 --------------------- Application/World.cpp | 59 +++++++++++++++++++++++++++----------- Application/World.h | 2 -- Makefile | 7 ++++- 5 files changed, 49 insertions(+), 88 deletions(-) delete mode 100644 Application/ThreadPool.cpp delete mode 100644 Application/ThreadPool.h diff --git a/Application/ThreadPool.cpp b/Application/ThreadPool.cpp deleted file mode 100644 index 94a6286..0000000 --- a/Application/ThreadPool.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -ThreadPool::ThreadPool() : m_concurency(std::max(std::thread::hardware_concurrency(), DEFAULT_CONCURENCY)), m_waiting_count(m_concurency) -{ - for(std::size_t i = 0; i < m_concurency; i++) - { - m_pool.emplace_back([this] - { - using namespace std::chrono_literals; - - for(;;) - { - if(m_stop) - return; - if(!m_tasks.IsEmpty()) - { - std::function task = std::move(m_tasks.Pop()); - m_waiting_count--; - task(); - m_waiting_count++; - } - else - std::this_thread::sleep_for(10ms); - } - }); - } - Scop::Message("ThreadPool started with a capacity of %", m_concurency); -} - -ThreadPool::~ThreadPool() -{ - m_stop = true; - for(auto& thread : m_pool) - thread.join(); -} diff --git a/Application/ThreadPool.h b/Application/ThreadPool.h deleted file mode 100644 index 52e0456..0000000 --- a/Application/ThreadPool.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef THREAD_POOL_H -#define THREAD_POOL_H - -#include -#include -#include -#include - -constexpr std::uint32_t DEFAULT_CONCURENCY = 6; - -class ThreadPool -{ - public: - ThreadPool(); - inline void EnqueueTask(std::function task) { m_tasks.Push(std::move(task)); } - inline void WaitForAllTasks() const - { - using namespace std::chrono_literals; - for(; m_waiting_count != m_concurency && !m_tasks.IsEmpty();) - std::this_thread::sleep_for(10ms); - } - ~ThreadPool(); - - private: - ThreadSafeQueue> m_tasks; - std::vector m_pool; - std::uint32_t m_concurency; - std::atomic_uint32_t m_waiting_count; - std::atomic_bool m_stop = false; -}; - -#endif diff --git a/Application/World.cpp b/Application/World.cpp index 42d926a..7cfe86a 100644 --- a/Application/World.cpp +++ b/Application/World.cpp @@ -128,7 +128,6 @@ World::~World() using namespace std::chrono_literals; std::this_thread::sleep_for(16ms); } - m_thread_pool.WaitForAllTasks(); } [[nodiscard]] Scop::NonOwningPtr World::GetChunk(Scop::Vec2i position) const @@ -166,7 +165,7 @@ void World::UnloadChunks() #define QUIT_CHECK() if(m_generation_status == GenerationState::Quitting) goto quit void World::GenerateWorld() { - constexpr float LIMIT = 80.0f; + std::vector pool; for(;;) { @@ -179,7 +178,7 @@ void World::GenerateWorld() continue; } - std::queue> mesh_generation_queue; + ThreadSafeQueue> mesh_generation_queue; Scop::Vec2i current_chunk = m_current_chunk_position.load(); Scop::Vec2i x_range{ @@ -191,7 +190,7 @@ void World::GenerateWorld() current_chunk.y + RENDER_DISTANCE + 1 }; - std::size_t range = (RENDER_DISTANCE + RENDER_DISTANCE + 2) * 2; + std::size_t range = ((x_range.y - x_range.x) * (z_range.y - z_range.x)); m_loading_progress = 0.0f; @@ -201,39 +200,67 @@ void World::GenerateWorld() { QUIT_CHECK(); - std::unordered_map::iterator chunk_data; { std::unique_lock guard(m_chunk_mutex); - chunk_data = m_chunks.try_emplace(Scop::Vec2i{ x, z }, *this, Scop::Vec2i{ x, z }).first; + m_chunks.try_emplace(Scop::Vec2i{ x, z }, *this, Scop::Vec2i{ x, z }); } - chunk_data->second.GenerateChunk(); - if(!chunk_data->second.GetActor() && !chunk_data->second.GetWaterActor() && x > x_range.x && x < x_range.y && z > z_range.x && z < z_range.y) - mesh_generation_queue.push(std::ref(chunk_data->second)); - m_loading_progress = std::min(m_loading_progress + (1.0f / LIMIT) * range, LIMIT); + if(pool.size() >= std::max(std::thread::hardware_concurrency(), 4u)) + { + for(auto& thread : pool) + thread.join(); + pool.clear(); + } + + Chunk& chunk = m_chunks.at(Scop::Vec2i{ x, z }); + pool.emplace_back([this, &chunk, range, x, z, x_range, z_range, &mesh_generation_queue] + { + chunk.GenerateChunk(); + if(!chunk.GetActor() && !chunk.GetWaterActor() && x > x_range.x && x < x_range.y && z > z_range.x && z < z_range.y) + mesh_generation_queue.Push(std::ref(chunk)); + m_loading_progress = std::min(m_loading_progress + ((1.0f / range) * 50.0f), 50.0f); + }); } } + for(auto& thread : pool) + thread.join(); + pool.clear(); + QUIT_CHECK(); - while(!mesh_generation_queue.empty()) + while(!mesh_generation_queue.IsEmpty()) { - auto& chunk = mesh_generation_queue.front().get(); - mesh_generation_queue.pop(); + QUIT_CHECK(); + auto& chunk = mesh_generation_queue.Pop().get(); - m_thread_pool.EnqueueTask([this, &chunk, range] + if(pool.size() >= std::max(std::thread::hardware_concurrency(), 4u)) + { + for(auto& thread : pool) + thread.join(); + pool.clear(); + } + + pool.emplace_back([this, &chunk, range] { chunk.GenerateMesh(); m_chunks_to_upload.Push(chunk); - m_loading_progress = std::min(m_loading_progress + (1.0f / (100.0f - LIMIT)) * range, 100.0f); + m_loading_progress = std::min(m_loading_progress + ((1.0f / range) * 50.0f), 99.0f); }); } - m_thread_pool.WaitForAllTasks(); + for(auto& thread : pool) + thread.join(); + pool.clear(); + + m_loading_progress = 100.0f; + m_generation_status = GenerationState::Finished; } quit: + for(auto& thread : pool) + thread.join(); m_generation_status = GenerationState::Finished; } diff --git a/Application/World.h b/Application/World.h index 4b519ae..47f53cc 100644 --- a/Application/World.h +++ b/Application/World.h @@ -10,7 +10,6 @@ #include #include #include -#include #include constexpr std::uint8_t RENDER_DISTANCE = 15; @@ -53,7 +52,6 @@ class World private: NoiseCollection m_noisecollection; FpsCounter m_fps_counter; - ThreadPool m_thread_pool; std::unordered_map m_chunks; ThreadSafeQueue> m_chunks_to_upload; std::shared_ptr p_block_material; diff --git a/Makefile b/Makefile index 0ee0f1f..a1aa9ed 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ CXXFLAGS = -std=c++20 -I ScopEngine/Runtime/Includes -I Application -I ScopEngin LDFLAGS = -lSDL2 ScopEngine/Bin/engine.a -latomic DEBUG ?= false +VOX_DEBUG ?= false TSAN ?= false MODE = "release" @@ -36,7 +37,11 @@ _GRAY := $(shell $(TPUT) setaf 8) _PURPLE := $(shell $(TPUT) setaf 5) ifeq ($(DEBUG), true) - CXXFLAGS += -g -D DEBUG + CXXFLAGS += -g -D VOX_DEBUG + MODE := $(_RESET)$(_PURPLE)$(_BOLD)Debug$(_RESET)$(_PURPLE) + COLOR := $(_PURPLE) +else ifeq ($(VOX_DEBUG), true) + CXXFLAGS += -g -D VOX_DEBUG MODE := $(_RESET)$(_PURPLE)$(_BOLD)Debug$(_RESET)$(_PURPLE) COLOR := $(_PURPLE) else