diff --git a/src/renderer/buffers/content.rs b/src/renderer/buffers/content.rs index 70d7c14..eb14f10 100644 --- a/src/renderer/buffers/content.rs +++ b/src/renderer/buffers/content.rs @@ -2,7 +2,6 @@ use std::time::Instant; use byteorder::{ByteOrder, LittleEndian}; use std::convert::TryInto; use cgmath::Vector3; -use std::cmp::{min, max}; use crate::game::world::block::WorldBlock; use super::nodes::{Nodes, NODE_TEX_SIZE, NODE_TEX_SIZE_QB}; @@ -144,7 +143,9 @@ impl Content { ); } - pub fn shift(&mut self, offset: &Vector3) { + pub fn shift(&mut self, offset: &Vector3) -> bool { + self.nodes.shift(offset) + // let timer = Instant::now(); // let mut result = vec![0_u32; self.node_buffer.len()].into_boxed_slice(); // let (ox, oy, oz) = (offset.x, offset.y, offset.z); @@ -169,8 +170,6 @@ impl Content { // println!("Shifted node buffer by {:?} in {} ms", offset, timer.elapsed().as_millis()); } - - pub fn update(&mut self, queue: &wgpu::Queue) { self.nodes.update(queue, &self.node_texture); } diff --git a/src/renderer/buffers/nodes.rs b/src/renderer/buffers/nodes.rs index ef30676..a9d7cc9 100644 --- a/src/renderer/buffers/nodes.rs +++ b/src/renderer/buffers/nodes.rs @@ -1,3 +1,10 @@ +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use std::thread::JoinHandle; +use std::sync::Mutex; +use std::thread; +use std::cmp::{min, max}; +use cgmath::Vector3; use byteorder::{LittleEndian, ByteOrder}; pub const NODE_TEX_SIZE: usize = 128; // 32x32x32 nodes in texture @@ -6,35 +13,68 @@ pub const NODE_TEX_SIZE_QB: usize = NODE_TEX_SIZE*NODE_TEX_SIZE*NODE_TEX_SIZE; pub struct Nodes { - node_buffer_a: Box<[u32]>, - node_buffer_b: Box<[u32]>, + node_buffer_a: Mutex>, + node_buffer_b: Mutex>, active_buffer: u8, - modified: bool + busy: Arc, + modified: bool, } impl Nodes { pub fn new() -> Self { Self { - node_buffer_a: vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice(), - node_buffer_b: vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice(), + node_buffer_a: Mutex::new(vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice()), + node_buffer_b: Mutex::new(vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice()), active_buffer: 0, - modified: false + busy: Arc::new(AtomicBool::new(false)), + modified: false, } } pub fn get_node(&self, index: usize) -> u32 { - if self.active_buffer == 0 { self.node_buffer_a[index] } - else { self.node_buffer_b[index] } + if self.active_buffer == 0 { self.node_buffer_a.lock().unwrap()[index] } + else { self.node_buffer_b.lock().unwrap()[index] } } pub fn set_node(&mut self, index: usize, value: u32) { - if self.active_buffer == 0 { self.node_buffer_a[index] = value; } - else { self.node_buffer_b[index] = value; } + if self.active_buffer == 0 { self.node_buffer_a.lock().unwrap()[index] = value; } + else { self.node_buffer_b.lock().unwrap()[index] = value; } self.modified = true; } + pub fn shift(&mut self, offset: &Vector3) -> bool { + // Prevent shifting if busy + if self.busy.load(Ordering::Relaxed) { + return false; + } + + // Perform shift + self.busy.store(true, Ordering::Relaxed); + + let from = if self.active_buffer == 0 { self.node_buffer_a.lock().unwrap() } else { self.node_buffer_b.lock().unwrap() }; + let mut to = if self.active_buffer == 0 { self.node_buffer_b.lock().unwrap() } else { self.node_buffer_a.lock().unwrap() }; + let (ox, oy, oz) = (offset.x, offset.y, offset.z); + let size = NODE_TEX_SIZE as i32; + + 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)); + to[idx1 as usize] = from[idx0 as usize]; + } + } + } + + self.active_buffer = !self.active_buffer; + self.modified = true; + self.busy.store(false, Ordering::Relaxed); + + true + } + pub fn update(&mut self, queue: &wgpu::Queue, texture: &wgpu::Texture) { - if self.modified { + if self.modified && !self.busy.load(Ordering::Relaxed) { self.modified = false; // Select target node buffer @@ -50,7 +90,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(&node_buffer[offset..offset+NODE_TEX_SIZE_SQ], &mut node_bytes); + LittleEndian::write_u32_into(&node_buffer.lock().unwrap()[offset..offset+NODE_TEX_SIZE_SQ], &mut node_bytes); // Write nodes queue.write_texture(