diff --git a/src/game/world/block.rs b/src/game/world/block.rs index d28146f..6c48524 100644 --- a/src/game/world/block.rs +++ b/src/game/world/block.rs @@ -6,13 +6,13 @@ pub const SIZE_QB: usize = SIZE*SIZE*SIZE; #[derive(Clone)] pub struct WorldBlock { - pub materials: [u8;SIZE_QB] + pub materials: Box<[u8;SIZE_QB]> } impl WorldBlock { pub fn new() -> Self { Self { - materials: [0_u8; SIZE_QB] + materials: Box::new([0_u8; SIZE_QB]) } } diff --git a/src/game/world/chunk.rs b/src/game/world/chunk.rs index d5ff836..6529df1 100644 --- a/src/game/world/chunk.rs +++ b/src/game/world/chunk.rs @@ -1,3 +1,7 @@ +use std::sync::Arc; +use std::time::Instant; +use std::thread; +use std::sync::mpsc; use crate::game::RendererView; use byteorder::LittleEndian; use byteorder::ByteOrder; @@ -9,6 +13,8 @@ pub const SIZE: usize = 32; const SIZE_SQ: usize = SIZE*SIZE; const SIZE_QB: usize = SIZE*SIZE*SIZE; +const NUM_WORKERS: usize = 8; + // 1 chunk times on i7-5930K // alg | size | compr | decom // raw 32.89kB 0.06s 1.19s @@ -47,16 +53,39 @@ impl WorldChunk { } // Blocks + let timer = Instant::now(); let mut block_bytes = vec![0_u8; num_blocks*SIZE_QB]; lz4::decompress(&block_bytes_compressed, &mut block_bytes[0..num_blocks*SIZE_QB]).unwrap(); + let block_bytes = Arc::new(block_bytes); - for i in 0..num_blocks { - let mut block = WorldBlock::new(); - let idx = i * block::SIZE_QB; - block.materials.clone_from_slice(&block_bytes[idx..idx+block::SIZE_QB]); - instance.blocks.push(block); + // Spawn workers + let (tx, rx) = mpsc::channel(); + let per_worker = num_blocks / NUM_WORKERS; + let mut workers = vec![]; + for t in 0..NUM_WORKERS { + let by = block_bytes.clone(); + let tx = tx.clone(); + + // Each worker will process their part + workers.push(thread::spawn(move || { + for i in t*per_worker..(t+1)*per_worker { + let mut block = WorldBlock::new(); + let idx = i * block::SIZE_QB; + block.materials.clone_from_slice(&by[idx..idx+block::SIZE_QB]); + tx.send((i, block)).unwrap(); + } + })); } + // Wait for workers to finish. + for handle in workers { handle.join().unwrap(); } + let mut blocks: Vec<(usize, WorldBlock)> = rx.try_iter().collect(); + + // Sort and add result blocks to chunk + blocks.sort_by(|a, b| (*a).0.cmp(&(*b).0)); + for b in blocks { instance.blocks.push(b.1); } + + println!("Blocks: {} ms, {}", timer.elapsed().as_millis(), instance.blocks.len()); instance } @@ -76,7 +105,7 @@ impl WorldChunk { // Blocks let mut buf = Vec::new(); for block in self.blocks.iter() { - buf.extend(&block.materials); + buf.extend(&block.materials[..]); } lz4::compress_to_vec(&buf, &mut bytes, lz4::ACC_LEVEL_DEFAULT).unwrap(); diff --git a/src/renderer/buffers/content.rs b/src/renderer/buffers/content.rs index 9f73575..493301e 100644 --- a/src/renderer/buffers/content.rs +++ b/src/renderer/buffers/content.rs @@ -127,7 +127,7 @@ impl Content { let block_origin = wgpu::Origin3d{ x: (x*BLOCK_SIZE) as u32, y: (y*BLOCK_SIZE) as u32, z: (z*BLOCK_SIZE) as u32 }; let block_size = wgpu::Extent3d{ width: BLOCK_SIZE as u32, height: BLOCK_SIZE as u32, depth: BLOCK_SIZE as u32 }; - let block_bytes : [u8;BLOCK_SIZE*BLOCK_SIZE*BLOCK_SIZE] = block.materials.try_into().unwrap(); + let block_bytes : [u8;BLOCK_SIZE*BLOCK_SIZE*BLOCK_SIZE] = block.materials[..].try_into().unwrap(); //println!("Y: {} Z: {}", y, z); diff --git a/src/renderer/renderer_view.rs b/src/renderer/renderer_view.rs index 9553ef4..3d6f2d9 100644 --- a/src/renderer/renderer_view.rs +++ b/src/renderer/renderer_view.rs @@ -19,9 +19,9 @@ impl RendererView for Renderer { } fn shift(&mut self, offset: &Vector3) { - self.buffers.content.shift(offset); - self.world_offset += *offset; - println!("World shifted by {:?}. World offset is now {:?}", offset, self.world_offset); + //self.buffers.content.shift(offset); + //self.world_offset += *offset; + //println!("World shifted by {:?}. World offset is now {:?}", offset, self.world_offset); } fn get_camera_transform(&mut self) -> &mut dyn CameraTransform {