From 10182730a595dc1e14dfbe4bf39477d3112a5f89 Mon Sep 17 00:00:00 2001 From: Piotrek Date: Tue, 18 May 2021 16:27:23 +0200 Subject: [PATCH] cpu shifting nodes in a separate thread, very bugged --- src/game/mod.rs | 2 +- src/renderer/buffers/content.rs | 5 +- src/renderer/buffers/nodes.rs | 121 +++++++++++++++++--------------- src/renderer/renderer_view.rs | 5 ++ 4 files changed, 73 insertions(+), 60 deletions(-) diff --git a/src/game/mod.rs b/src/game/mod.rs index 52ff04d..81880ca 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -119,7 +119,7 @@ impl Game { self.world.update(); // Send dirty chunks to renderer - if chunk_pos == self.prev_chunk_pos.unwrap_or(chunk_pos) { + if !renderer.is_busy() && chunk_pos == self.prev_chunk_pos.unwrap_or(chunk_pos) { for (pos, chunk) in self.world.all_chunks() { if chunk.dirty { renderer.write_chunk(pos, chunk); diff --git a/src/renderer/buffers/content.rs b/src/renderer/buffers/content.rs index da85821..e4b5fc5 100644 --- a/src/renderer/buffers/content.rs +++ b/src/renderer/buffers/content.rs @@ -82,7 +82,6 @@ impl Content { // Done let nodes = Nodes::new(); let block_freeidx = 0; - let node_dirty = false; let block_freed = Vec::new(); Self { nodes, block_freed, node_texture, block_freeidx, block_texture, bind_layout, bind_group } } @@ -172,6 +171,10 @@ impl Content { ); } + pub fn is_busy(&self) -> bool { + self.nodes.is_busy() + } + pub fn get_world_offset(&self) -> Vector3 { self.nodes.get_world_offset() } diff --git a/src/renderer/buffers/nodes.rs b/src/renderer/buffers/nodes.rs index 34024e4..130c51b 100644 --- a/src/renderer/buffers/nodes.rs +++ b/src/renderer/buffers/nodes.rs @@ -4,96 +4,101 @@ use std::cmp::{min, max}; use std::time::Instant; use cgmath::Vector3; use std::thread; +use std::sync::{mpsc, mpsc::Receiver, mpsc::Sender}; use byteorder::{LittleEndian, ByteOrder}; pub const NODE_TEX_SIZE: usize = 128; // 32x32x32 nodes in texture pub const NODE_TEX_SIZE_SQ: usize = NODE_TEX_SIZE*NODE_TEX_SIZE; pub const NODE_TEX_SIZE_QB: usize = NODE_TEX_SIZE*NODE_TEX_SIZE*NODE_TEX_SIZE; -struct ShiftResult { - offset: Vector3, - active_buffer: usize -} +type NodeBuffer = (Vector3, Box<[u32]>); pub struct Nodes { - // Realtime variables - node_buffer: Arc; 2]>>, - world_offset: Vector3, - active_buffer: usize, + buffer: Box<[u32]>, + offset: Vector3, dirty: bool, - // Threaded work - busy: i32, + busy: bool, + queue: Vec>, + channel: (Sender, Receiver) } impl Nodes { pub fn new() -> Self { Self { - // Realtime variables - node_buffer: Arc::new(Mutex::new([vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice(), vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice()])), - world_offset: Vector3{x:0,y:0,z:0}, - active_buffer: 0, + // Present + buffer: vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice(), + offset: Vector3{x:0,y:0,z:0}, dirty: false, - // Threaded work - busy: 0, + busy: false, + queue: Vec::new(), + channel: mpsc::channel() } } pub fn get_world_offset(&self) -> Vector3 { - self.world_offset + self.offset } pub fn get_node(&self, index: usize) -> u32 { - self.node_buffer.lock().unwrap()[self.active_buffer][index] + self.buffer[index] + } + + pub fn is_busy(&self) -> bool { + self.busy } pub fn set_node(&mut self, index: usize, value: u32) { - self.node_buffer.lock().unwrap()[self.active_buffer][index] = value; + self.buffer[index] = value; self.dirty = true; } pub fn shift(&mut self, offset: &Vector3) { - - let a = if self.active_buffer == 0 { 0 } else { 1 }; - let b = if self.active_buffer == 0 { 1 } else { 0 }; - let (ox, oy, oz) = (offset.x, offset.y, offset.z); - let node_buffer = Arc::clone(&self.node_buffer); - - self.busy += 1; - - - let t = thread::spawn(move || { - // Prepare variables - let mut node_buffer = node_buffer.lock().unwrap(); - let size = NODE_TEX_SIZE as i32; - - // Clear target buffer - for i in node_buffer[b].iter_mut() { - *i = 0; - } - - // Copy slice of source buffer into target buffer - for x in max(0, -ox)..min(size-ox, size) { - for y in max(0, -oy)..min(size-oy, size) { - for z in max(0, -oz)..min(size-oz, size) { - let idx0 = x + size * (y + size * z); - let idx1 = (x+ox) + size * ((y+oy) + size * (z+oz)); - node_buffer[b][idx1 as usize] = node_buffer[a][idx0 as usize]; - } - } - } - }); - - // DEBUG - t.join().unwrap(); - - self.world_offset += *offset; - self.active_buffer = b; - self.dirty = true; - self.busy -= 1; + self.queue.push(*offset); } pub fn update(&mut self, queue: &wgpu::Queue, texture: &wgpu::Texture) { + // Receive work + while let Ok(result) = self.channel.1.try_recv() { + self.offset += result.0; + self.buffer = result.1; + self.busy = false; + self.dirty = true; + } + + // Check if there is some more work + if !self.busy { + if let Some(offset) = self.queue.pop() { + self.busy = true; + self.dirty = false; + let source = self.buffer.clone(); + let tx = self.channel.0.clone(); + + // Spawn worker + thread::spawn(move || { + println!("shift worker start: {:?}", offset); + + let size = NODE_TEX_SIZE as i32; + let mut target = vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice(); + let (ox, oy, oz) = (offset.x, offset.y, offset.z); + + // Copy slice of source buffer into target buffer + for x in max(0, -ox)..min(size-ox, size) { + for y in max(0, -oy)..min(size-oy, size) { + for z in max(0, -oz)..min(size-oz, size) { + let idx0 = x + size * (y + size * z); + let idx1 = (x+ox) + size * ((y+oy) + size * (z+oz)); + target[idx1 as usize] = source[idx0 as usize]; + } + } + } + + // Send result + tx.send((offset, target)).unwrap(); + println!("shift worker done: {:?}", offset); + }); + } + } if self.dirty { self.dirty = false; @@ -106,7 +111,7 @@ impl Nodes { let node_size = wgpu::Extent3d { width: NODE_TEX_SIZE as u32, height: NODE_TEX_SIZE as u32, depth: 1 }; let mut node_bytes = [0_u8; NODE_TEX_SIZE_SQ*4]; let offset = NODE_TEX_SIZE_SQ*z; - LittleEndian::write_u32_into(&self.node_buffer.lock().unwrap()[self.active_buffer][offset..offset+NODE_TEX_SIZE_SQ], &mut node_bytes); + LittleEndian::write_u32_into(&self.buffer[offset..offset+NODE_TEX_SIZE_SQ], &mut node_bytes); // Write nodes queue.write_texture( diff --git a/src/renderer/renderer_view.rs b/src/renderer/renderer_view.rs index 7e0c61b..f3bb461 100644 --- a/src/renderer/renderer_view.rs +++ b/src/renderer/renderer_view.rs @@ -10,6 +10,7 @@ pub trait RendererView { fn get_camera_transform(&mut self) -> &mut dyn CameraTransform; fn get_ui(&mut self) -> &mut UserInterface; fn free_chunk(&mut self, chunk_pos: Vector3); + fn is_busy(&self) -> bool; } impl RendererView for Renderer { @@ -59,4 +60,8 @@ impl RendererView for Renderer { fn get_ui(&mut self) -> &mut UserInterface { &mut self.ui } + + fn is_busy(&self) -> bool { + self.buffers.content.is_busy() + } } \ No newline at end of file