Skip to content

Commit 500b9b7

Browse files
author
Dan Liebault
committed
Améliore la gestion des chunks et le pool de threads
- Activation du profilage dans `R3DVoxel.vcxproj` pour l'analyse des performances. - Utilisation d'un pool de threads dans `ChunkManager.cpp` pour la création de chunks, remplaçant les threads individuels. - Introduction des fonctions `compute_world_update_x` et `compute_world_update_z` pour gérer les mises à jour des chunks. - Ajout de la structure `render_update_t` dans `ChunkManager.h` pour encapsuler les informations de mise à jour. - Amélioration de la gestion de l'instance du pool de threads dans `thread_pool.cpp` et ajustements dans `thread_pool.hpp` pour renforcer l'encapsulation.
1 parent ebaa84e commit 500b9b7

6 files changed

Lines changed: 196 additions & 38 deletions

File tree

R3DVoxel/Application.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,15 @@ void Application::Start()
6666

6767
do
6868
{
69-
const bool updated = chunk_manager.UpdateWorld(*mp_engine->GetMainCamera());
70-
if (updated)
69+
const auto update_x = chunk_manager.compute_world_update_x(*mp_engine->GetMainCamera());
70+
if (update_x.updated)
71+
chunk_manager.update_world_x(update_x.created, update_x.update_plus, update_x.update_min);
72+
73+
const auto update_z = chunk_manager.compute_world_update_z(*mp_engine->GetMainCamera());
74+
if (update_z.updated)
75+
chunk_manager.update_world_z(update_z.created, update_z.update_plus, update_z.update_min);
76+
77+
if (update_x.updated || update_z.updated)
7178
scene->ToUpdate();
7279

7380
Watcher::WatchPosition("camera", mp_engine->GetMainCamera()->GetPosition());

R3DVoxel/R3DVoxel.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
<GenerateDebugInformation>true</GenerateDebugInformation>
128128
<AdditionalLibraryDirectories>$(VULKAN_SDK)\Lib;$(SolutionDir)\dependencies\assimp-5.0.1\lib\Debug;$(SolutionDir)\dependencies\glew-2.1.0\lib;$(SolutionDir)\dependencies\glfw-3.3.7\lib\win;$(SolutionDir)\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
129129
<AdditionalDependencies>vulkan-1.lib;glfw3.lib;assimp-vc142-mtd.lib;Engine.lib;shaderc_combinedd.lib;%(AdditionalDependencies)</AdditionalDependencies>
130+
<Profile>true</Profile>
130131
</Link>
131132
</ItemDefinitionGroup>
132133
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

R3DVoxel/VoxelEngine/ChunkManager.cpp

Lines changed: 136 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <barrier>
55

66
ChunkManager::ChunkManager(std::shared_ptr<GameObject> pworld, std::shared_ptr<Material> p_world_mat, const Camera& camera) :
7-
mp_world(std::move(pworld)), mp_world_mat(std::move(p_world_mat)), m_worldmenu(m_load_radius)
7+
mp_world(std::move(pworld)), mp_world_mat(std::move(p_world_mat)), m_worldmenu(m_load_radius), _tpool(thread_pool_t::instance())
88
{
99
mp_terrain_generator = std::make_unique<TerrainGenerator>();
1010
m_render_position = camera.GetPosition();
@@ -34,20 +34,19 @@ void ChunkManager::CreateWorld()
3434

3535
for (int32_t x = m_render_min.x; x <= m_render_max.x; x++)
3636
{
37-
std::thread t([&chunks, x, &sync, this]() {
37+
auto task = [x, &chunks, &sync, this]()
38+
{
3839
for (int32_t y = m_render_min.y; y <= m_render_max.y; y++)
3940
{
40-
4141
for (int32_t z = m_render_min.z; z <= m_render_max.z; z++)
4242
{
43-
// CreateNewChunk(x, y, z);
4443
chunks.at({ x, y, z }) = create_chunk(x, y, z);
4544
}
4645
}
46+
sync.arrive_and_drop();
47+
};
4748

48-
sync.arrive_and_wait();
49-
});
50-
t.detach();
49+
_tpool.enqueue(task);
5150
}
5251

5352
sync.arrive_and_wait(); // wait for all chunks to be created
@@ -199,6 +198,136 @@ bool ChunkManager::UpdateWorld(const Camera& camera)
199198
return scene_x_need_update || scene_z_need_update;
200199
}
201200

201+
render_update_t ChunkManager::compute_world_update_x(const Camera& camera)
202+
{
203+
render_update_t render_update;
204+
205+
if (camera.GetPosition().x > m_render_position.x + Voxel::CHUNK_SIZE)
206+
{
207+
m_render_position.x = camera.GetPosition().x;
208+
209+
m_render_max.x = m_render_max.x + 1;
210+
211+
for (int32_t z = m_render_min.z; z <= m_render_max.z; z++)
212+
{
213+
for (int32_t y = m_render_min.y; y <= m_render_max.y; y++)
214+
{
215+
CreateNewChunk(m_render_max.x, y, z);
216+
DestroyChunk(m_render_min.x, y, z);
217+
}
218+
}
219+
220+
m_render_min.x = m_render_min.x + 1;
221+
222+
render_update.created = m_render_max.x;
223+
render_update.update_plus = m_render_max.x - 1;
224+
render_update.update_min = m_render_min.x;
225+
render_update.updated = true;
226+
}
227+
else if (camera.GetPosition().x < m_render_position.x - Voxel::CHUNK_SIZE)
228+
{
229+
m_render_position.x = camera.GetPosition().x;
230+
231+
m_render_min.x = m_render_min.x - 1;
232+
233+
for (int32_t z = m_render_min.z; z <= m_render_max.z; z++)
234+
{
235+
for (int32_t y = m_render_min.y; y <= m_render_max.y; y++)
236+
{
237+
CreateNewChunk(m_render_min.x, y, z);
238+
DestroyChunk(m_render_max.x, y, z);
239+
}
240+
}
241+
242+
m_render_max.x = m_render_max.x - 1;
243+
244+
render_update.created = m_render_min.x;
245+
render_update.update_plus = m_render_min.x + 1;
246+
render_update.update_min = m_render_max.x;
247+
render_update.updated = true;
248+
}
249+
250+
return render_update;
251+
}
252+
253+
render_update_t ChunkManager::compute_world_update_z(const Camera& camera)
254+
{
255+
render_update_t render_update;
256+
257+
if (camera.GetPosition().z > m_render_position.z + Voxel::CHUNK_SIZE)
258+
{
259+
m_render_position.z = camera.GetPosition().z;
260+
261+
m_render_max.z = m_render_max.z + 1;
262+
263+
for (int32_t x = m_render_min.x; x <= m_render_max.x; x++)
264+
{
265+
for (int32_t y = m_render_min.y; y <= m_render_max.y; y++)
266+
{
267+
CreateNewChunk(x, y, m_render_max.z);
268+
DestroyChunk(x, y, m_render_min.z);
269+
}
270+
}
271+
272+
m_render_min.z = m_render_min.z + 1;
273+
274+
render_update.created = m_render_max.z;
275+
render_update.update_plus = m_render_max.z - 1;
276+
render_update.update_min = m_render_min.z;
277+
render_update.updated = true;
278+
}
279+
else if (camera.GetPosition().z < m_render_position.z - Voxel::CHUNK_SIZE)
280+
{
281+
m_render_position.z = camera.GetPosition().z;
282+
283+
m_render_min.z = m_render_min.z - 1;
284+
285+
for (int32_t x = m_render_min.x; x <= m_render_max.x; x++)
286+
{
287+
for (int32_t y = m_render_min.y; y <= m_render_max.y; y++)
288+
{
289+
CreateNewChunk(x, y, m_render_min.z);
290+
DestroyChunk(x, y, m_render_max.z);
291+
}
292+
}
293+
294+
m_render_max.z = m_render_max.z - 1;
295+
296+
render_update.created = m_render_min.z;
297+
render_update.update_plus = m_render_min.z + 1;
298+
render_update.update_min = m_render_max.z;
299+
render_update.updated = true;
300+
}
301+
302+
return render_update;
303+
}
304+
305+
void ChunkManager::update_world_x(int32_t create_x, int32_t update_xplus, int32_t update_xmin) const
306+
{
307+
for (int32_t z = m_render_min.z; z <= m_render_max.z; z++)
308+
{
309+
for (int32_t y = m_render_min.y; y <= m_render_max.y; y++)
310+
{
311+
m_chunk_map.at({ create_x, y, z })->BuildChunk(m_chunk_map, mp_world, mp_world_mat);
312+
m_chunk_map.at({ update_xplus, y, z })->UpdateChunk(m_chunk_map, *mp_world);
313+
m_chunk_map.at({ update_xmin, y, z })->UpdateChunk(m_chunk_map, *mp_world);
314+
}
315+
}
316+
}
317+
318+
void ChunkManager::update_world_z(int32_t create_z, int32_t update_zplus, int32_t update_zmin) const
319+
{
320+
for (int32_t x = m_render_min.x; x <= m_render_max.x; x++)
321+
{
322+
for (int32_t y = m_render_min.y; y <= m_render_max.y; y++)
323+
{
324+
m_chunk_map.at({ x, y, create_z })->BuildChunk(m_chunk_map, mp_world, mp_world_mat);
325+
m_chunk_map.at({ x, y, update_zplus })->UpdateChunk(m_chunk_map, *mp_world);
326+
m_chunk_map.at({ x, y, update_zmin })->UpdateChunk(m_chunk_map, *mp_world);
327+
}
328+
}
329+
}
330+
202331
void ChunkManager::CreateNewChunk(int32_t x, int32_t y, int32_t z)
203332
{
204333
const ChunkKey key = { x, y, z };

R3DVoxel/VoxelEngine/ChunkManager.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,20 @@
55
#include <utility>
66
#include <cmath>
77

8+
#include "../utils/thread_pool.hpp"
89
#include "../WorldMenu.h"
910
#include "Chunk.h"
1011
#include "TerrainGenerator.h"
1112

13+
struct render_update_t
14+
{
15+
int32_t created = -1;
16+
int32_t update_plus = -1;
17+
int32_t update_min = -1;
18+
19+
bool updated = false;
20+
};
21+
1222
class ChunkManager
1323
{
1424
public:
@@ -18,6 +28,12 @@ class ChunkManager
1828
void CreateWorld();
1929
bool UpdateWorld(const Camera& camera);
2030

31+
render_update_t compute_world_update_x(const Camera& camera);
32+
render_update_t compute_world_update_z(const Camera& camera);
33+
34+
void update_world_x(int32_t create_x, int32_t update_xplus, int32_t update_xmin) const;
35+
void update_world_z(int32_t create_z, int32_t update_zplus, int32_t update_zmin) const;
36+
2137
void CreateNewChunk(int32_t x, int32_t y, int32_t z);
2238
void DestroyChunk(const int32_t x, const int32_t y, const int32_t z);
2339

@@ -40,6 +56,8 @@ class ChunkManager
4056
glm::i32vec3 m_render_min;
4157

4258
WorldMenu m_worldmenu;
59+
60+
thread_pool_t& _tpool;
4361
};
4462

4563
#endif

R3DVoxel/utils/thread_pool.cpp

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@
22

33
#include <type_traits>
44

5-
thread_pool_t& thread_pool_t::instance()
6-
{
7-
static thread_pool_t instance;
8-
return instance;
9-
}
10-
11-
void thread_pool_t::init(size_t n)
5+
thread_pool_t::thread_pool_t(size_t n)
126
{
137
workers.reserve(n);
148
for (size_t i = 0; i < n; ++i)
@@ -17,7 +11,7 @@ void thread_pool_t::init(size_t n)
1711
}
1812
}
1913

20-
void thread_pool_t::end()
14+
thread_pool_t::~thread_pool_t()
2115
{
2216
{
2317
std::unique_lock<std::mutex> lock(mutex);
@@ -31,6 +25,12 @@ void thread_pool_t::end()
3125
}
3226
}
3327

28+
thread_pool_t& thread_pool_t::instance()
29+
{
30+
static thread_pool_t instance;
31+
return instance;
32+
}
33+
3434
void thread_pool_t::worker()
3535
{
3636
for (;;)
@@ -53,20 +53,3 @@ void thread_pool_t::worker()
5353
cur_task();
5454
}
5555
}
56-
57-
template <typename F, typename... Args>
58-
inline auto thread_pool_t::enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
59-
{
60-
auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
61-
auto encapsulated_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
62-
63-
std::future<std::invoke_result<F, Args...>> future_object = encapsulated_ptr->get_future();
64-
{
65-
std::unique_lock<std::mutex> lock(mutex);
66-
queue.emplace([encapsulated_ptr]() {
67-
(*encapsulated_ptr)(); // execute the fx
68-
});
69-
}
70-
cv.notify_one();
71-
return future_object;
72-
}

R3DVoxel/utils/thread_pool.hpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,35 @@ struct thread_pool_t
1616
std::condition_variable cv;
1717
bool stop = false;
1818

19-
static thread_pool_t& instance();
19+
thread_pool_t(size_t n = std::thread::hardware_concurrency());
20+
~thread_pool_t();
2021

21-
void init(size_t n = std::thread::hardware_concurrency());
22-
void end();
22+
thread_pool_t(const thread_pool_t&) = delete;
23+
thread_pool_t& operator=(const thread_pool_t&) = delete;
24+
thread_pool_t(thread_pool_t&&) = delete;
25+
thread_pool_t& operator=(thread_pool_t&&) = delete;
2326

27+
static thread_pool_t& instance();
2428
void worker();
2529

2630
template <typename F, typename... Args>
27-
inline auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))>;
31+
inline auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
32+
{
33+
auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
34+
auto encapsulated_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
35+
36+
std::future<decltype(f(args...))> future_object = encapsulated_ptr->get_future();
37+
{
38+
std::unique_lock<std::mutex> lock(mutex);
39+
queue.emplace(
40+
[encapsulated_ptr]()
41+
{
42+
(*encapsulated_ptr)(); // execute the fx
43+
});
44+
}
45+
cv.notify_one();
46+
return future_object;
47+
}
2848
};
2949

3050
#endif // R3D_THREAD_POOL_HPP

0 commit comments

Comments
 (0)