diff options
Diffstat (limited to 'client/src')
-rw-r--r-- | client/src/download.rs | 45 | ||||
-rw-r--r-- | client/src/renderer.rs | 31 | ||||
-rw-r--r-- | client/src/scene_prepare.rs | 46 | ||||
-rw-r--r-- | client/src/scene_render.rs | 2 | ||||
-rw-r--r-- | client/src/state.rs | 45 |
5 files changed, 114 insertions, 55 deletions
diff --git a/client/src/download.rs b/client/src/download.rs index 24dbe15..bc3de09 100644 --- a/client/src/download.rs +++ b/client/src/download.rs @@ -17,7 +17,7 @@ use crate::network::Network; use anyhow::Result; use log::debug; -use std::{collections::HashSet, marker::PhantomData}; +use std::{collections::HashSet, marker::PhantomData, sync::RwLock}; use weareshared::{ helper::ReadWrite, packets::{Packet, Resource}, @@ -25,6 +25,9 @@ use weareshared::{ }; pub struct Downloader { + inner: RwLock<DownloaderState>, +} +struct DownloaderState { have: HashSet<Resource>, need: HashSet<Resource>, pending: HashSet<Resource>, @@ -34,33 +37,38 @@ pub struct Downloader { impl Downloader { pub fn new(store: ResourceStore) -> Self { Self { - have: HashSet::new(), - need: HashSet::new(), - pending: HashSet::new(), - store, + inner: DownloaderState { + have: HashSet::new(), + need: HashSet::new(), + pending: HashSet::new(), + store, + } + .into(), } } - pub fn try_get<T: ReadWrite>(&mut self, hash: Resource<T>) -> Result<Option<T>> { + pub fn try_get<T: ReadWrite>(&self, hash: Resource<T>) -> Result<Option<T>> { self.try_get_raw(Resource(hash.0, PhantomData))? .map(|x| T::read(&mut x.as_slice())) .transpose() } - pub fn try_get_raw(&mut self, hash: Resource) -> Result<Option<Vec<u8>>> { - if self.have.contains(&hash) { - self.store.get_raw(hash) + pub fn try_get_raw(&self, hash: Resource) -> Result<Option<Vec<u8>>> { + let mut state = self.inner.write().unwrap(); + if state.have.contains(&hash) { + state.store.get_raw(hash) } else { - self.need.insert(hash); + state.need.insert(hash); Ok(None) } } - pub fn packet(&mut self, p: &Packet) -> Result<()> { + pub fn packet(&self, p: &Packet) -> Result<()> { + let mut state = self.inner.write().unwrap(); match p { Packet::RespondResource(d) => { let key = Resource(sha256(&d.0), PhantomData); - self.store.set_raw(&d.0)?; - self.need.remove(&key); - self.pending.remove(&key); - if self.have.insert(key) { + state.store.set_raw(&d.0)?; + state.need.remove(&key); + state.pending.remove(&key); + if state.have.insert(key) { debug!("have {key}"); } } @@ -68,9 +76,10 @@ impl Downloader { } Ok(()) } - pub fn update(&mut self, network: &mut Network) -> Result<()> { + pub fn update(&self, network: &Network) -> Result<()> { + let mut state = self.inner.write().unwrap(); let mut new_pending = Vec::new(); - for n in self.need.difference(&self.pending) { + for n in state.need.difference(&state.pending) { network .packet_send .send(Packet::RequestResource(*n)) @@ -78,7 +87,7 @@ impl Downloader { debug!("need {n}"); new_pending.push(*n); } - self.pending.extend(new_pending); + state.pending.extend(new_pending); Ok(()) } } diff --git a/client/src/renderer.rs b/client/src/renderer.rs index bb87b6c..a9a2332 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -15,12 +15,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ use crate::{ - camera::Camera, scene_prepare::ScenePreparer, scene_render::ScenePipeline, ui::UiRenderer, + camera::Camera, download::Downloader, scene_prepare::ScenePreparer, + scene_render::ScenePipeline, ui::UiRenderer, }; use anyhow::{Result, anyhow}; use log::{info, warn}; use pollster::FutureExt; -use std::sync::Arc; +use std::{ + sync::Arc, + thread::{sleep, spawn}, + time::Duration, +}; use weareshared::tree::SceneTree; use wgpu::{ Backends, CommandEncoderDescriptor, Device, DeviceDescriptor, Extent3d, Features, Instance, @@ -37,12 +42,12 @@ pub struct Renderer<'a> { surface_configuration: SurfaceConfiguration, scene_pipeline: ScenePipeline, pub ui_renderer: UiRenderer, - pub scene_prepare: ScenePreparer, + pub scene_prepare: Arc<ScenePreparer>, surface_needs_reconfigure: bool, depth: TextureView, } impl<'a> Renderer<'a> { - pub fn new(window: &'a Window) -> Result<Self> { + pub fn new(window: &'a Window, downloader: Arc<Downloader>) -> Result<Self> { info!("wgpu init"); let instance = Instance::new(InstanceDescriptor { backends: Backends::all(), @@ -85,7 +90,11 @@ impl<'a> Renderer<'a> { let (scene_pipeline, texture_bgl) = ScenePipeline::new(&device, surface_configuration.format); - let scene_prepare = ScenePreparer::new(device.clone(), queue.clone(), texture_bgl); + let scene_prepare = Arc::new(ScenePreparer::new( + device.clone(), + queue.clone(), + texture_bgl, + )); let ui_renderer = UiRenderer::new(device.clone(), queue.clone(), surface_configuration.format); @@ -106,6 +115,16 @@ impl<'a> Renderer<'a> { }); let depth = depth.create_view(&TextureViewDescriptor::default()); + { + let scene_prepare = scene_prepare.clone(); + spawn(move || { + loop { + scene_prepare.update(&downloader).unwrap(); + sleep(Duration::from_millis(50)); + } + }); + } + Ok(Self { scene_pipeline, scene_prepare, @@ -170,7 +189,7 @@ impl<'a> Renderer<'a> { &target_view, &self.depth, scene, - &mut self.scene_prepare.prefabs, + &self.scene_prepare.prefabs, projection, ); diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index f74277c..ae7e599 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -22,7 +22,7 @@ use std::{ collections::{HashMap, HashSet}, hash::Hash, io::Cursor, - sync::Arc, + sync::{Arc, RwLock}, }; use weareshared::{ Affine3A, @@ -37,25 +37,36 @@ use wgpu::{ }; pub struct DemandMap<K, V> { + inner: RwLock<DemandMapState<K, V>>, +} +struct DemandMapState<K, V> { values: HashMap<K, V>, needed: HashSet<K>, } -impl<K: Hash + Eq, V: Clone> DemandMap<K, V> { +impl<K: Hash + Eq + Clone, V: Clone> DemandMap<K, V> { pub fn new() -> Self { Self { - needed: HashSet::new(), - values: HashMap::new(), + inner: DemandMapState { + needed: HashSet::new(), + values: HashMap::new(), + } + .into(), } } - pub fn insert(&mut self, key: K, value: V) { - self.needed.remove(&key); - self.values.insert(key, value); + pub fn needed(&self) -> Vec<K> { + self.inner.read().unwrap().needed.iter().cloned().collect() + } + pub fn insert(&self, key: K, value: V) { + let mut s = self.inner.write().unwrap(); + s.needed.remove(&key); + s.values.insert(key, value); } - pub fn try_get(&mut self, key: K) -> Option<V> { - if let Some(k) = self.values.get(&key) { + pub fn try_get(&self, key: K) -> Option<V> { + let mut s = self.inner.write().unwrap(); + if let Some(k) = s.values.get(&key) { Some(k.to_owned()) } else { - self.needed.insert(key); + s.needed.insert(key); None } } @@ -100,8 +111,8 @@ impl ScenePreparer { queue, } } - pub fn update(&mut self, dls: &mut Downloader) -> Result<()> { - for pres in self.prefabs.needed.clone() { + pub fn update(&self, dls: &Downloader) -> Result<()> { + for pres in self.prefabs.needed() { if let Some(prefab) = dls.try_get(pres.clone())? { let mut rprefab = RPrefab(Vec::new()); for (aff, partres) in &prefab.mesh { @@ -115,7 +126,7 @@ impl ScenePreparer { } } } - for pres in self.index_buffers.needed.clone() { + for pres in self.index_buffers.needed() { if let Some(buf) = dls.try_get(pres.clone())? { let buf = buf .0 @@ -133,7 +144,7 @@ impl ScenePreparer { debug!("index buffer created (len={}) {pres}", buf.len() / 2); } } - for pres in self.vertex_buffers.needed.clone() { + for pres in self.vertex_buffers.needed() { if let Some(buf) = dls.try_get(pres.clone())? { let buf = buf .0 @@ -154,7 +165,7 @@ impl ScenePreparer { ); } } - for pres in self.textures.needed.clone() { + for pres in self.textures.needed() { if let Some(buf) = dls.try_get(pres.clone())? { let image = ImageReader::new(Cursor::new(buf.0)).with_guessed_format()?; let image = image.decode()?; @@ -171,7 +182,7 @@ impl ScenePreparer { self.textures.insert(pres.clone(), tex_bg); } } - for pres in self.placeholder_textures.needed.clone() { + for pres in self.placeholder_textures.needed() { let tex_bg = create_texture( &self.device, &self.queue, @@ -182,12 +193,11 @@ impl ScenePreparer { ); self.placeholder_textures.insert(pres, tex_bg); } - for pres in self.mesh_parts.needed.clone() { + for pres in self.mesh_parts.needed() { if let Some(part) = dls.try_get(pres.clone())? { if let (Some(indexres), Some(positionres)) = (part.index, part.va_position) { let Some((index, index_count)) = self.index_buffers.try_get(indexres.clone()) else { - self.index_buffers.needed.insert(indexres); continue; }; let mut position = Vec::new(); diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs index 9aceaef..047cee4 100644 --- a/client/src/scene_render.rs +++ b/client/src/scene_render.rs @@ -128,7 +128,7 @@ impl ScenePipeline { target: &TextureView, depth: &TextureView, scene: &SceneTree, - prefabs: &mut DemandMap<Resource<Prefab>, Arc<RPrefab>>, + prefabs: &DemandMap<Resource<Prefab>, Arc<RPrefab>>, projection: Mat4, ) { let mut rpass = commands.begin_render_pass(&RenderPassDescriptor { diff --git a/client/src/state.rs b/client/src/state.rs index 00a8c0b..cd11d4a 100644 --- a/client/src/state.rs +++ b/client/src/state.rs @@ -18,17 +18,26 @@ use crate::{camera::Camera, download::Downloader, network::Network, renderer::Re use anyhow::{Context, Result}; use glam::{Vec2, Vec3}; use log::{info, warn}; -use std::{net::TcpStream, time::Instant}; -use weareshared::{store::ResourceStore, tree::SceneTree}; +use std::{net::TcpStream, sync::Arc, time::Instant}; +use weareshared::{ + packets::{Packet, Resource}, + resources::PrefabIndex, + store::ResourceStore, + tree::SceneTree, +}; use winit::event::MouseButton; pub struct State<'a> { - pub network: Network, - pub downloader: Downloader, + pub network: Arc<Network>, + pub downloader: Arc<Downloader>, pub renderer: Renderer<'a>, pub tree: SceneTree, pub camera: Camera, pub delta: DeltaState, + + pub prefab_index: PrefabIndex, + pub prefab_index_res_loaded: Option<Resource<PrefabIndex>>, + pub prefab_index_res: Option<Resource<PrefabIndex>>, } pub struct DeltaState { @@ -41,18 +50,22 @@ pub struct DeltaState { impl<'a> State<'a> { pub fn new(conn: TcpStream, window: &'a winit::window::Window) -> Result<State<'a>> { info!("new state"); + let downloader = Arc::new(Downloader::new(ResourceStore::new_memory())); Ok(Self { camera: Camera::new(), - network: Network::new(conn), + network: Network::new(conn).into(), tree: SceneTree::default(), - renderer: Renderer::new(window)?, - downloader: Downloader::new(ResourceStore::new_memory()), + renderer: Renderer::new(window, downloader.clone())?, + downloader, delta: DeltaState { time: Instant::now(), move_dir: Vec3::ZERO, mouse_acc: Vec2::ZERO, cursor_pos: Vec2::ZERO, }, + prefab_index_res: None, + prefab_index_res_loaded: None, + prefab_index: PrefabIndex::default(), }) } pub fn draw(&mut self) { @@ -92,15 +105,23 @@ impl<'a> State<'a> { for p in self.network.packet_recv.try_iter() { self.downloader.packet(&p)?; self.tree.packet(&p); + if let Packet::PrefabIndex(res) = &p { + self.prefab_index_res = Some(res.to_owned()); + } } self.downloader - .update(&mut self.network) + .update(&self.network) .context("downloader state")?; - self.renderer - .scene_prepare - .update(&mut self.downloader) - .context("scene preparation")?; + if self.prefab_index_res != self.prefab_index_res_loaded { + if let Some(res) = &self.prefab_index_res { + if let Some(index) = self.downloader.try_get(res.to_owned())? { + info!("prefab index loaded"); + self.prefab_index = index; + self.prefab_index_res_loaded = Some(res.to_owned()); + } + } + } Ok(()) } } |