mirror of
https://github.com/Kbz-8/42_vox.git
synced 2026-01-10 22:23:35 +00:00
fixing multithreading
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
#include <ThreadPool.h>
|
||||
#include <ScopCore.h>
|
||||
#include <thread>
|
||||
|
||||
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<void()> 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();
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#ifndef THREAD_POOL_H
|
||||
#define THREAD_POOL_H
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <Utils.h>
|
||||
|
||||
constexpr std::uint32_t DEFAULT_CONCURENCY = 6;
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
ThreadPool();
|
||||
inline void EnqueueTask(std::function<void()> 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<std::function<void()>> m_tasks;
|
||||
std::vector<std::thread> m_pool;
|
||||
std::uint32_t m_concurency;
|
||||
std::atomic_uint32_t m_waiting_count;
|
||||
std::atomic_bool m_stop = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -128,7 +128,6 @@ World::~World()
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(16ms);
|
||||
}
|
||||
m_thread_pool.WaitForAllTasks();
|
||||
}
|
||||
|
||||
[[nodiscard]] Scop::NonOwningPtr<const Chunk> 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<std::thread> pool;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
@@ -179,7 +178,7 @@ void World::GenerateWorld()
|
||||
continue;
|
||||
}
|
||||
|
||||
std::queue<std::reference_wrapper<Chunk>> mesh_generation_queue;
|
||||
ThreadSafeQueue<std::reference_wrapper<Chunk>> 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<Scop::Vec2i, Chunk>::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;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <Chunk.h>
|
||||
#include <Utils.h>
|
||||
#include <FpsCounter.h>
|
||||
#include <ThreadPool.h>
|
||||
#include <NoiseCollection.h>
|
||||
|
||||
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<Scop::Vec2i, Chunk> m_chunks;
|
||||
ThreadSafeQueue<std::reference_wrapper<Chunk>> m_chunks_to_upload;
|
||||
std::shared_ptr<Scop::Material> p_block_material;
|
||||
|
||||
7
Makefile
7
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
|
||||
|
||||
Reference in New Issue
Block a user