Skip to content

Commit 5dfe7e8

Browse files
committed
perf improvments
1 parent 5282dc0 commit 5dfe7e8

File tree

3 files changed

+66
-50
lines changed

3 files changed

+66
-50
lines changed

src/chunk.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::blocks::block_type::BlockType::Water;
22
use crate::persistence::{Loadable, Saveable};
33
use crate::player::Player;
44
use crate::utils::math_utils::Plane;
5-
use crate::world::{WorldChunk, RNG_SEED, WATER_HEIGHT_LEVEL};
5+
use crate::world::{ChunkMap, WorldChunk, RNG_SEED, WATER_HEIGHT_LEVEL};
66
use crate::{
77
blocks::{
88
block::{Block, BlockVertexData, FaceDirections},
@@ -137,7 +137,7 @@ impl Chunk {
137137
4: water vertex buffer, 5: water index buffer */
138138
pub fn build_mesh(
139139
&self,
140-
other_chunks: Vec<WorldChunk>,
140+
other_chunks: ChunkMap,
141141
) -> (
142142
u32,
143143
u32,
@@ -150,15 +150,14 @@ impl Chunk {
150150
let mut water_indices: Vec<u32> = vec![];
151151
let mut vertex: Vec<BlockVertexData> = vec![];
152152
let mut indices: Vec<u32> = vec![];
153-
let mut adjacent_chunks: Vec<((i32, i32), BlockVec)> =
154-
vec![((self.x, self.y), self.blocks.clone())];
155-
156-
for chunk in &other_chunks {
157-
let chunk_read = chunk.read().unwrap();
158-
if chunk_read.x == self.x + 1 || chunk_read.x == self.x - 1 {
159-
adjacent_chunks.push(((chunk_read.x, chunk_read.y), chunk_read.blocks.clone()));
160-
} else if chunk_read.y == self.y + 1 || chunk_read.y == self.y - 1 {
161-
adjacent_chunks.push(((chunk_read.x, chunk_read.y), chunk_read.blocks.clone()));
153+
let mut adjacent_chunks: Vec<((i32, i32), BlockVec)> = vec![];
154+
155+
for x in self.x - 1..=self.x + 1 {
156+
for y in self.y - 1..=self.y + 1 {
157+
if let Some(chunk) = other_chunks.read().unwrap().get(&(x, y)) {
158+
let chunk_read = chunk.read().unwrap();
159+
adjacent_chunks.push(((x, y), chunk_read.blocks.clone()));
160+
}
162161
}
163162
}
164163

@@ -191,10 +190,13 @@ impl Chunk {
191190
(face_position.z + CHUNK_SIZE as f32) % CHUNK_SIZE as f32,
192191
);
193192

194-
let target_chunk = other_chunks.iter().find(|c| {
195-
let c = c.read().unwrap();
196-
c.x == target_chunk_x && c.y == target_chunk_y
197-
});
193+
let other_chunks_brw = other_chunks.read().unwrap();
194+
let target_chunk =
195+
other_chunks_brw.get(&(target_chunk_x, target_chunk_y));
196+
// let target_chunk = other_chunks.iter().find(|c| {
197+
// let c = c.read().unwrap();
198+
// c.x == target_chunk_x && c.y == target_chunk_y
199+
// });
198200
// If there's a chunk loaded in memory then check that, else it means we're on a edge and we can
199201
// Calculate the block's height when the chunk gets generated
200202
// TODO: Check for saved file chunk

src/state.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,8 @@ impl State {
314314
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
315315
label: Some("command_encoder"),
316316
});
317-
318-
let chunks = self
319-
.world
320-
.chunks
317+
let chunk_map = self.world.chunks.read().unwrap();
318+
let chunks = chunk_map
321319
.values()
322320
.map(|f| f.read().unwrap())
323321
.collect::<Vec<_>>();

src/world.rs

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub const FREQUENCY: f32 = 1. / 128.;
2424
pub const NOISE_CHUNK_PER_ROW: u32 = NOISE_SIZE / CHUNK_SIZE;
2525
pub const MAX_TREES_PER_CHUNK: u32 = 3;
2626

27-
pub const CHUNKS_PER_ROW: u32 = 25;
27+
pub const CHUNKS_PER_ROW: u32 = 60;
2828
pub const CHUNKS_REGION: u32 = CHUNKS_PER_ROW * CHUNKS_PER_ROW;
2929
pub const WATER_HEIGHT_LEVEL: u8 = 5;
3030

@@ -41,8 +41,12 @@ pub const UB: i32 = if CHUNKS_PER_ROW % 2 == 0 {
4141
pub type NoiseData = Vec<f32>;
4242

4343
pub type WorldChunk = Arc<RwLock<Chunk>>;
44+
pub type ChunkMap = Arc<RwLock<HashMap<(i32, i32), WorldChunk>>>;
45+
46+
// TODO: It should be better to unsafely pass the hashmap between threads, since we never modify it except when we're done
47+
// and it will be save since every chunk has its own lock.
4448
pub struct World {
45-
pub chunks: HashMap<(i32, i32), WorldChunk>,
49+
pub chunks: ChunkMap,
4650
pub thread_pool: Option<ThreadPool>,
4751
pub seed: u32,
4852
pub noise_data: Arc<NoiseData>,
@@ -52,23 +56,23 @@ pub struct World {
5256
}
5357

5458
impl World {
55-
pub fn get_other_chunks(&self, chunk_ptr: WorldChunk) -> Vec<WorldChunk> {
56-
self.chunks
57-
.values()
58-
.filter_map(|c| {
59-
return if !Arc::ptr_eq(&chunk_ptr, c) {
60-
Some(c.clone())
61-
} else {
62-
None
63-
};
64-
})
65-
.collect()
66-
}
59+
// pub fn get_other_chunks(&self, chunk_ptr: WorldChunk) -> Vec<WorldChunk> {
60+
// self.chunks
61+
// .values()
62+
// .filter_map(|c| {
63+
// return if !Arc::ptr_eq(&chunk_ptr, c) {
64+
// Some(c.clone())
65+
// } else {
66+
// None
67+
// };
68+
// })
69+
// .collect()
70+
// }
6771
pub fn place_block(&mut self, block: Arc<RwLock<Block>>) {
6872
let block_borrow = block.read().unwrap();
6973
let mut chunks_to_rerender = vec![block_borrow.get_chunk_coords()];
70-
let chunk = self
71-
.chunks
74+
let chunk_map = self.chunks.read().unwrap();
75+
let chunk = chunk_map
7276
.get(&chunks_to_rerender[0])
7377
.expect("Cannot delete a block from unloaded chunk");
7478

@@ -96,8 +100,8 @@ impl World {
96100
pub fn remove_block(&mut self, block: Arc<RwLock<Block>>) {
97101
let block_borrow = block.read().unwrap();
98102
let mut chunks_to_rerender = vec![block_borrow.get_chunk_coords()];
99-
let chunk = self
100-
.chunks
103+
let chunk_map = self.chunks.read().unwrap();
104+
let chunk = chunk_map
101105
.get(&chunks_to_rerender[0])
102106
.expect("Cannot delete a block from unloaded chunk");
103107

@@ -113,7 +117,8 @@ impl World {
113117
pub fn get_blocks_absolute(&self, position: &Vec3) -> Option<Arc<RwLock<Block>>> {
114118
let (chunk_x, chunk_y) = position.get_chunk_from_position_absolute();
115119

116-
let chunk = self.chunks.get(&(chunk_x, chunk_y))?;
120+
let chunk_map = self.chunks.read().unwrap();
121+
let chunk = chunk_map.get(&(chunk_x, chunk_y))?;
117122
let chunk = chunk.read().unwrap();
118123

119124
let relative_position = position.relative_from_absolute();
@@ -206,7 +211,7 @@ impl World {
206211
.collect();
207212

208213
let mut keys_to_remove = vec![];
209-
for key in self.chunks.keys() {
214+
for key in self.chunks.read().unwrap().keys() {
210215
// let chunk = chunk.read().unwrap();
211216
if (delta.1 != 0 && key.1 == chunk_y_remove)
212217
|| (delta.0 != 0 && key.0 == chunk_x_remove)
@@ -218,7 +223,12 @@ impl World {
218223
// Save the unloaded chunks
219224
let (sender, receiver) = mpsc::channel();
220225
for key in keys_to_remove.iter() {
221-
let chunk = self.chunks.remove(key).expect("Something went wrong");
226+
let chunk = self
227+
.chunks
228+
.write()
229+
.unwrap()
230+
.remove(key)
231+
.expect("Something went wrong");
222232
let sender = sender.clone();
223233
self.thread_pool.as_ref().unwrap().execute(move || {
224234
let chunk = chunk.write().unwrap();
@@ -260,6 +270,8 @@ impl World {
260270
for _ in 0..chunks_added {
261271
let chunk = receiver.recv().unwrap();
262272
self.chunks
273+
.write()
274+
.unwrap()
263275
.insert((chunk.x, chunk.y), Arc::new(RwLock::new(chunk)));
264276
}
265277
self.handle_outside_blocks();
@@ -272,7 +284,7 @@ impl World {
272284
// Update visible chunks based on player position and direction
273285
{
274286
let (sender, receiver) = mpsc::channel();
275-
for chunk in self.chunks.values() {
287+
for chunk in self.chunks.read().unwrap().values() {
276288
let chunk = Arc::clone(&chunk);
277289
let sender = sender.clone();
278290
let player = Arc::clone(&player);
@@ -282,7 +294,7 @@ impl World {
282294
sender.send(()).unwrap();
283295
});
284296
}
285-
for _ in self.chunks.iter() {
297+
for _ in self.chunks.read().unwrap().iter() {
286298
receiver.recv().unwrap();
287299
}
288300
}
@@ -292,7 +304,7 @@ impl World {
292304
}
293305

294306
pub fn save_state(&self) {
295-
for chunk in self.chunks.values() {
307+
for chunk in self.chunks.read().unwrap().values() {
296308
let chunkbrw = chunk.read().unwrap();
297309
if chunkbrw.modified {
298310
chunkbrw.save().expect("failed to save");
@@ -327,12 +339,14 @@ impl World {
327339
for _ in 0..CHUNKS_PER_ROW * CHUNKS_PER_ROW {
328340
let chunk = receiver.recv().expect("Some chunks are missing");
329341
self.chunks
342+
.write()
343+
.unwrap()
330344
.insert((chunk.x, chunk.y), Arc::new(RwLock::new(chunk)));
331345
}
332346

333347
self.handle_outside_blocks();
334348
// this is kinda slow
335-
self.render_chunks(self.chunks.keys().collect::<Vec<_>>());
349+
self.render_chunks(self.chunks.read().unwrap().keys().collect::<Vec<_>>());
336350
}
337351
// chunks: slice containing the chunk to re-render
338352
fn render_chunks<I>(&self, chunk_keys: Vec<I>)
@@ -342,15 +356,17 @@ impl World {
342356
let (sender, receiver) = mpsc::channel();
343357

344358
for key in chunk_keys.iter() {
345-
if let Some(chunk) = self.chunks.get(key.borrow()) {
359+
if let Some(chunk) = self.chunks.read().unwrap().get(key.borrow()) {
346360
let sender = sender.clone();
347-
let other = self.get_other_chunks(chunk.clone());
361+
// This is extremely slow O(n^2)
362+
// let other = self.get_other_chunks(chunk.clone());
348363
let chunk = chunk.clone();
364+
let chunk_map = self.chunks.clone();
349365

350366
self.thread_pool.as_ref().unwrap().execute(move || {
351367
let chunk_ptr = chunk.clone();
352368
let chunk = chunk.read().unwrap();
353-
let res = chunk.build_mesh(other);
369+
let res = chunk.build_mesh(chunk_map);
354370
sender.send((res, chunk_ptr)).unwrap();
355371
});
356372
}
@@ -378,7 +394,7 @@ impl World {
378394
}
379395
fn handle_outside_blocks(&mut self) {
380396
let mut blocks_to_add = vec![];
381-
for chunk in self.chunks.values() {
397+
for chunk in self.chunks.read().unwrap().values() {
382398
let mut chunkbrw = chunk.write().unwrap();
383399
blocks_to_add.append(&mut chunkbrw.outside_blocks);
384400
}
@@ -387,7 +403,7 @@ impl World {
387403

388404
for block in blocks_to_add.iter() {
389405
let chunk_coords = block.read().unwrap().get_chunk_coords();
390-
if let Some(chunkptr) = self.chunks.get(&chunk_coords) {
406+
if let Some(chunkptr) = self.chunks.read().unwrap().get(&chunk_coords) {
391407
let mut chunkbrw = chunkptr.write().unwrap();
392408
chunkbrw.add_block(block.clone(), false);
393409
if let None = chunks_to_rerender.iter().find(|c| Arc::ptr_eq(c, chunkptr)) {
@@ -409,7 +425,7 @@ impl World {
409425

410426
World {
411427
chunk_data_layout,
412-
chunks: HashMap::new(),
428+
chunks: Arc::new(RwLock::new(HashMap::new())),
413429
noise_data,
414430
device,
415431
queue,

0 commit comments

Comments
 (0)