Skip to content

Commit 5282dc0

Browse files
committed
improved major bottleneck, perf on larger worlds went from 50fps to full vsync fps (144)
1 parent 787ba56 commit 5282dc0

File tree

3 files changed

+71
-111
lines changed

3 files changed

+71
-111
lines changed

src/macros.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#[macro_export]
22
macro_rules! perf {
3-
($start:expr, $end:expr, $fn_name:expr) => {
4-
println!("PERF: {} - {}", $fn_name, ($end - $start).as_secs_f64())
3+
($start:expr, $fn_name:expr) => {
4+
let end = Instant::now();
5+
println!("PERF: {} - {}", $fn_name, (end - $start).as_secs_f64())
56
};
67
}

src/state.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use std::sync::{Mutex, RwLock};
2+
use std::time::Instant;
23
use std::{f32::consts, sync::Arc};
34

45
use crate::blocks::block::Block;
56
use crate::blocks::block_type::BlockType;
67
use crate::collision::CollisionBox;
8+
use crate::perf;
79
use crate::persistence::Saveable;
810
use crate::pipeline::{Pipeline, PipelineTrait};
911
use crate::utils::{ChunkFromPosition, RelativeFromAbsolute};
@@ -246,6 +248,7 @@ impl State {
246248
pub fn update(&mut self, delta_time: f32, total_time: f32) {
247249
let mut collisions = vec![];
248250

251+
let start_update = Instant::now();
249252
if let Some(nearby_blocks) = self.world.get_blocks_nearby(Arc::clone(&self.player)) {
250253
for block in nearby_blocks.iter() {
251254
let block = block.read().unwrap();
@@ -315,7 +318,7 @@ impl State {
315318
let chunks = self
316319
.world
317320
.chunks
318-
.iter()
321+
.values()
319322
.map(|f| f.read().unwrap())
320323
.collect::<Vec<_>>();
321324

src/world.rs

Lines changed: 64 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use glam::Vec3;
2+
use std::borrow::Borrow;
3+
use std::collections::HashMap;
24
use std::fs::File;
35
use std::ops::{Deref, DerefMut};
46
use std::sync::{Mutex, RwLock};
@@ -22,7 +24,7 @@ pub const FREQUENCY: f32 = 1. / 128.;
2224
pub const NOISE_CHUNK_PER_ROW: u32 = NOISE_SIZE / CHUNK_SIZE;
2325
pub const MAX_TREES_PER_CHUNK: u32 = 3;
2426

25-
pub const CHUNKS_PER_ROW: u32 = 9;
27+
pub const CHUNKS_PER_ROW: u32 = 25;
2628
pub const CHUNKS_REGION: u32 = CHUNKS_PER_ROW * CHUNKS_PER_ROW;
2729
pub const WATER_HEIGHT_LEVEL: u8 = 5;
2830

@@ -40,7 +42,7 @@ pub type NoiseData = Vec<f32>;
4042

4143
pub type WorldChunk = Arc<RwLock<Chunk>>;
4244
pub struct World {
43-
pub chunks: Vec<WorldChunk>,
45+
pub chunks: HashMap<(i32, i32), WorldChunk>,
4446
pub thread_pool: Option<ThreadPool>,
4547
pub seed: u32,
4648
pub noise_data: Arc<NoiseData>,
@@ -50,24 +52,9 @@ pub struct World {
5052
}
5153

5254
impl World {
53-
// gets all the chunks except the one passed in the index
54-
pub fn get_other_chunks_by_index(&self, chunk_index: usize) -> Vec<WorldChunk> {
55-
self.chunks
56-
.iter()
57-
.enumerate()
58-
.filter_map(|(i, c)| {
59-
return if i != chunk_index {
60-
Some(c.clone())
61-
} else {
62-
None
63-
};
64-
})
65-
.collect()
66-
}
67-
// gets all the chunks except the one passed
6855
pub fn get_other_chunks(&self, chunk_ptr: WorldChunk) -> Vec<WorldChunk> {
6956
self.chunks
70-
.iter()
57+
.values()
7158
.filter_map(|c| {
7259
return if !Arc::ptr_eq(&chunk_ptr, c) {
7360
Some(c.clone())
@@ -78,89 +65,55 @@ impl World {
7865
.collect()
7966
}
8067
pub fn place_block(&mut self, block: Arc<RwLock<Block>>) {
81-
let mut chunks_to_rerender = vec![];
82-
8368
let block_borrow = block.read().unwrap();
84-
let chunk_coords = block_borrow.get_chunk_coords();
69+
let mut chunks_to_rerender = vec![block_borrow.get_chunk_coords()];
8570
let chunk = self
8671
.chunks
87-
.iter()
88-
.find(|c| {
89-
let c = c.read().unwrap();
90-
c.x == chunk_coords.0 && c.y == chunk_coords.1
91-
})
72+
.get(&chunks_to_rerender[0])
9273
.expect("Cannot delete a block from unloaded chunk");
9374

94-
chunks_to_rerender.push(chunk.clone());
9575
let mut chunk_lock = chunk.write().unwrap();
9676
chunk_lock.add_block(block.clone(), true);
9777

9878
let block_borrow = block.read().unwrap();
99-
let block_neighbour_chunks = block_borrow.get_neighbour_chunks_coords();
79+
chunks_to_rerender.append(&mut block_borrow.get_neighbour_chunks_coords());
10080
std::mem::drop(chunk_lock);
10181

102-
if block_neighbour_chunks.len() > 0 {
103-
for neighbour_chunk in block_neighbour_chunks {
104-
let neighbour_chunk = self
105-
.chunks
106-
.iter()
107-
.find(|o| {
108-
let c = o.read().unwrap();
109-
return c.x == neighbour_chunk.0 && c.y == neighbour_chunk.1;
110-
})
111-
.expect("Cannot destroy a block without neighbour being loaded");
112-
113-
chunks_to_rerender.push(neighbour_chunk.clone());
114-
}
115-
}
82+
// if block_neighbour_chunks.len() > 0 {
83+
// for neighbour_chunk in block_neighbour_chunks {
84+
// let neighbour_chunk = self
85+
// .chunks
86+
// .get(&neighbour_chunk)
87+
// .expect("Cannot destroy a block without neighbour being loaded");
88+
89+
// chunks_to_rerender.push(neighbour_chunk.clone());
90+
// }
91+
// }
11692

117-
self.render_chunks(&chunks_to_rerender);
93+
self.render_chunks(chunks_to_rerender)
94+
// self.render_chunks(block_neighbour_chunks.append(&mut vec![chunk_coords]));
11895
}
11996
pub fn remove_block(&mut self, block: Arc<RwLock<Block>>) {
120-
let mut chunks_to_rerender = vec![];
121-
12297
let block_borrow = block.read().unwrap();
123-
let chunk_coords = block_borrow.get_chunk_coords();
98+
let mut chunks_to_rerender = vec![block_borrow.get_chunk_coords()];
12499
let chunk = self
125100
.chunks
126-
.iter()
127-
.find(|c| {
128-
let c = c.read().unwrap();
129-
c.x == chunk_coords.0 && c.y == chunk_coords.1
130-
})
101+
.get(&chunks_to_rerender[0])
131102
.expect("Cannot delete a block from unloaded chunk");
132103

133104
let mut chunk_lock = chunk.write().unwrap();
134105
chunk_lock.remove_block(&(block_borrow.position));
135-
chunks_to_rerender.push(chunk.clone());
136106
// chunk_lock.build_mesh(self.get_other_chunks(chunk.clone()));
137-
let block_neighbour_chunks = block_borrow.get_neighbour_chunks_coords();
107+
chunks_to_rerender.append(&mut block_borrow.get_neighbour_chunks_coords());
138108
// I hate this so much
139109
std::mem::drop(chunk_lock);
140110

141-
if block_neighbour_chunks.len() > 0 {
142-
for neighbour_chunk in block_neighbour_chunks {
143-
let neighbour_chunk = self
144-
.chunks
145-
.iter()
146-
.find(|o| {
147-
let c = o.read().unwrap();
148-
c.x == neighbour_chunk.0 && c.y == neighbour_chunk.1
149-
})
150-
.expect("Cannot destroy a block without neighbour being loaded");
151-
152-
chunks_to_rerender.push(neighbour_chunk.clone());
153-
}
154-
}
155-
self.render_chunks(&chunks_to_rerender);
111+
self.render_chunks(chunks_to_rerender);
156112
}
157113
pub fn get_blocks_absolute(&self, position: &Vec3) -> Option<Arc<RwLock<Block>>> {
158114
let (chunk_x, chunk_y) = position.get_chunk_from_position_absolute();
159115

160-
let chunk = self.chunks.iter().find(|c| {
161-
let c = c.read().unwrap();
162-
c.x == chunk_x && c.y == chunk_y
163-
})?;
116+
let chunk = self.chunks.get(&(chunk_x, chunk_y))?;
164117
let chunk = chunk.read().unwrap();
165118

166119
let relative_position = position.relative_from_absolute();
@@ -252,20 +205,20 @@ impl World {
252205
})
253206
.collect();
254207

255-
let mut indices_to_remove: Vec<usize> = vec![];
256-
for (i, chunk) in self.chunks.iter().enumerate() {
257-
let chunk = chunk.read().unwrap();
258-
if (delta.1 != 0 && chunk.y == chunk_y_remove)
259-
|| (delta.0 != 0 && chunk.x == chunk_x_remove)
208+
let mut keys_to_remove = vec![];
209+
for key in self.chunks.keys() {
210+
// let chunk = chunk.read().unwrap();
211+
if (delta.1 != 0 && key.1 == chunk_y_remove)
212+
|| (delta.0 != 0 && key.0 == chunk_x_remove)
260213
{
261-
indices_to_remove.push(i);
214+
keys_to_remove.push(key.clone());
262215
}
263216
}
264217

265218
// Save the unloaded chunks
266219
let (sender, receiver) = mpsc::channel();
267-
for (o, index) in indices_to_remove.iter().enumerate() {
268-
let chunk = self.chunks.remove(index - o);
220+
for key in keys_to_remove.iter() {
221+
let chunk = self.chunks.remove(key).expect("Something went wrong");
269222
let sender = sender.clone();
270223
self.thread_pool.as_ref().unwrap().execute(move || {
271224
let chunk = chunk.write().unwrap();
@@ -276,7 +229,7 @@ impl World {
276229
})
277230
}
278231

279-
for _ in indices_to_remove.iter() {
232+
for _ in keys_to_remove.iter() {
280233
receiver.recv().unwrap();
281234
}
282235

@@ -306,19 +259,20 @@ impl World {
306259

307260
for _ in 0..chunks_added {
308261
let chunk = receiver.recv().unwrap();
309-
self.chunks.push(Arc::new(RwLock::new(chunk)));
262+
self.chunks
263+
.insert((chunk.x, chunk.y), Arc::new(RwLock::new(chunk)));
310264
}
311265
self.handle_outside_blocks();
312-
self.render_chunks(&self.chunks[self.chunks.len() - chunks_added..]);
313266
// Re-render only the last inserted chunks
267+
self.render_chunks(new_chunks_positions);
314268
}
315269

316270
player_write.current_chunk = current_chunk;
317271
std::mem::drop(player_write);
318272
// Update visible chunks based on player position and direction
319273
{
320274
let (sender, receiver) = mpsc::channel();
321-
for chunk in self.chunks.iter() {
275+
for chunk in self.chunks.values() {
322276
let chunk = Arc::clone(&chunk);
323277
let sender = sender.clone();
324278
let player = Arc::clone(&player);
@@ -338,7 +292,7 @@ impl World {
338292
}
339293

340294
pub fn save_state(&self) {
341-
for chunk in self.chunks.iter() {
295+
for chunk in self.chunks.values() {
342296
let chunkbrw = chunk.read().unwrap();
343297
if chunkbrw.modified {
344298
chunkbrw.save().expect("failed to save");
@@ -349,7 +303,6 @@ impl World {
349303
let (sender, receiver) = mpsc::channel();
350304
let player = player.read().unwrap();
351305

352-
let mut chunks = vec![];
353306
for chunk_x in LB + player.current_chunk.0..=UB + player.current_chunk.0 {
354307
for chunk_y in LB + player.current_chunk.1..=UB + player.current_chunk.1 {
355308
let sender = sender.clone();
@@ -373,30 +326,36 @@ impl World {
373326

374327
for _ in 0..CHUNKS_PER_ROW * CHUNKS_PER_ROW {
375328
let chunk = receiver.recv().expect("Some chunks are missing");
376-
chunks.push(Arc::new(RwLock::new(chunk)));
329+
self.chunks
330+
.insert((chunk.x, chunk.y), Arc::new(RwLock::new(chunk)));
377331
}
378-
self.chunks.append(&mut chunks); // Add chunks to self
379332

380333
self.handle_outside_blocks();
381-
self.render_chunks(&self.chunks);
334+
// this is kinda slow
335+
self.render_chunks(self.chunks.keys().collect::<Vec<_>>());
382336
}
383337
// chunks: slice containing the chunk to re-render
384-
fn render_chunks(&self, chunks: &[WorldChunk]) {
338+
fn render_chunks<I>(&self, chunk_keys: Vec<I>)
339+
where
340+
I: Borrow<(i32, i32)>,
341+
{
385342
let (sender, receiver) = mpsc::channel();
386343

387-
for chunk in chunks.iter() {
388-
let sender = sender.clone();
389-
let other = self.get_other_chunks(chunk.clone());
390-
let chunk = chunk.clone();
391-
392-
self.thread_pool.as_ref().unwrap().execute(move || {
393-
let chunk_ptr = chunk.clone();
394-
let chunk = chunk.read().unwrap();
395-
let res = chunk.build_mesh(other);
396-
sender.send((res, chunk_ptr)).unwrap();
397-
});
344+
for key in chunk_keys.iter() {
345+
if let Some(chunk) = self.chunks.get(key.borrow()) {
346+
let sender = sender.clone();
347+
let other = self.get_other_chunks(chunk.clone());
348+
let chunk = chunk.clone();
349+
350+
self.thread_pool.as_ref().unwrap().execute(move || {
351+
let chunk_ptr = chunk.clone();
352+
let chunk = chunk.read().unwrap();
353+
let res = chunk.build_mesh(other);
354+
sender.send((res, chunk_ptr)).unwrap();
355+
});
356+
}
398357
}
399-
for _ in chunks.iter() {
358+
for _ in chunk_keys.iter() {
400359
let (
401360
(
402361
indices,
@@ -419,7 +378,7 @@ impl World {
419378
}
420379
fn handle_outside_blocks(&mut self) {
421380
let mut blocks_to_add = vec![];
422-
for chunk in self.chunks.iter() {
381+
for chunk in self.chunks.values() {
423382
let mut chunkbrw = chunk.write().unwrap();
424383
blocks_to_add.append(&mut chunkbrw.outside_blocks);
425384
}
@@ -428,10 +387,7 @@ impl World {
428387

429388
for block in blocks_to_add.iter() {
430389
let chunk_coords = block.read().unwrap().get_chunk_coords();
431-
if let Some(chunkptr) = self.chunks.iter().find(|c| {
432-
let c = c.read().unwrap();
433-
c.x == chunk_coords.0 && c.y == chunk_coords.1
434-
}) {
390+
if let Some(chunkptr) = self.chunks.get(&chunk_coords) {
435391
let mut chunkbrw = chunkptr.write().unwrap();
436392
chunkbrw.add_block(block.clone(), false);
437393
if let None = chunks_to_rerender.iter().find(|c| Arc::ptr_eq(c, chunkptr)) {
@@ -453,7 +409,7 @@ impl World {
453409

454410
World {
455411
chunk_data_layout,
456-
chunks: vec![],
412+
chunks: HashMap::new(),
457413
noise_data,
458414
device,
459415
queue,

0 commit comments

Comments
 (0)