diff options
-rw-r--r-- | client/src/main.rs | 1 | ||||
-rw-r--r-- | client/src/renderer.rs | 28 | ||||
-rw-r--r-- | client/src/scene_prepare.rs | 111 | ||||
-rw-r--r-- | client/src/scene_render.rs | 30 | ||||
-rw-r--r-- | client/src/shader.wgsl | 33 | ||||
-rw-r--r-- | server/src/main.rs | 6 | ||||
-rw-r--r-- | server/src/network.rs | 4 | ||||
-rw-r--r-- | shared/src/resources.rs | 10 | ||||
-rw-r--r-- | world/src/main.rs | 29 |
9 files changed, 169 insertions, 83 deletions
diff --git a/client/src/main.rs b/client/src/main.rs index cfbd052..1b615d1 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,3 +1,4 @@ +#![feature(iter_array_chunks)] pub mod download; pub mod network; pub mod renderer; diff --git a/client/src/renderer.rs b/client/src/renderer.rs index 7116a20..34450b2 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -1,7 +1,8 @@ -use crate::{download::Downloader, scene_prepare::ScenePreparer, scene_render::ScenePipeline}; -use anyhow::{Context, Result, anyhow}; +use crate::{scene_prepare::ScenePreparer, scene_render::ScenePipeline}; +use anyhow::{Result, anyhow}; use log::{info, warn}; use pollster::FutureExt; +use std::sync::Arc; use weareshared::tree::SceneTree; use wgpu::{ Backends, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, Instance, @@ -13,10 +14,11 @@ use winit::window::Window; pub struct Renderer<'a> { surface: Surface<'a>, queue: Queue, - device: Device, + device: Arc<Device>, surface_configuration: SurfaceConfiguration, scene_pipeline: ScenePipeline, pub scene_prepare: ScenePreparer, + surface_needs_reconfigure: bool, } impl<'a> Renderer<'a> { pub fn new(window: &'a Window) -> Result<Self> { @@ -39,8 +41,11 @@ impl<'a> Renderer<'a> { let (device, queue) = adapter .request_device( &DeviceDescriptor { - required_features: Features::default(), - required_limits: Limits::downlevel_defaults(), + required_features: Features::PUSH_CONSTANTS, + required_limits: Limits { + max_push_constant_size: 48, + ..Limits::default() + }, ..Default::default() }, None, @@ -53,13 +58,16 @@ impl<'a> Renderer<'a> { surface.configure(&device, &surface_configuration); + let device = Arc::new(device); + Ok(Self { scene_pipeline: ScenePipeline::new(&device, surface_configuration.format), - scene_prepare: ScenePreparer::new(), + scene_prepare: ScenePreparer::new(device.clone()), surface, device, queue, surface_configuration, + surface_needs_reconfigure: false, }) } @@ -71,9 +79,15 @@ impl<'a> Renderer<'a> { } pub fn draw(&mut self, scene: &SceneTree) -> Result<()> { + if self.surface_needs_reconfigure { + self.surface + .configure(&self.device, &self.surface_configuration); + self.surface_needs_reconfigure = false + } let target = self.surface.get_current_texture()?; if target.suboptimal { - warn!("suboptimal swapchain texture") + warn!("suboptimal swapchain texture"); + self.surface_needs_reconfigure = true; } let target_view = target .texture diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index 8d50fc3..47f168d 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -1,5 +1,6 @@ use crate::download::Downloader; use anyhow::{Context, Result}; +use log::{debug, info}; use std::{ collections::{HashMap, HashSet}, sync::Arc, @@ -8,8 +9,12 @@ use weareshared::{ Affine3A, packets::{ReadWrite, Resource}, resources::{Attribute, Part, Prefab}, + store::sha256, +}; +use wgpu::{ + Buffer, BufferUsages, Device, + util::{BufferInitDescriptor, DeviceExt}, }; -use wgpu::Buffer; pub struct ScenePreparer { index_buffers: HashMap<Resource, (Arc<Buffer>, u32)>, @@ -20,6 +25,8 @@ pub struct ScenePreparer { parts_needed: HashSet<Resource>, pub prefabs: HashMap<Resource, RPrefab>, pub prefabs_needed: HashSet<Resource>, + + device: Arc<Device>, } pub struct RPrefab(pub Vec<(Affine3A, Arc<RPart>)>); @@ -32,7 +39,7 @@ pub struct RPart { } impl ScenePreparer { - pub fn new() -> Self { + pub fn new(device: Arc<Device>) -> Self { Self { index_buffers: HashMap::new(), vertex_buffers: HashMap::new(), @@ -42,6 +49,7 @@ impl ScenePreparer { prefabs: HashMap::new(), prefabs_needed: HashSet::new(), index_buffers_needed: HashSet::new(), + device, } } pub fn update(&mut self, dls: &mut Downloader) -> Result<()> { @@ -59,12 +67,45 @@ impl ScenePreparer { } if rprefab.0.len() == prefab.0.len() { self.prefabs.insert(*pres, rprefab); + debug!("prefab created ({pres})"); done.push(*pres); } } } for pres in &self.index_buffers_needed { - if let Some(buf) = dls.try_get(*pres)? {} + if let Some(buf) = dls.try_get(*pres)? { + let buffer = self.device.create_buffer_init(&BufferInitDescriptor { + contents: &buf, + label: None, + usage: BufferUsages::INDEX | BufferUsages::COPY_DST, + }); + self.index_buffers + .insert(*pres, (Arc::new(buffer), buf.len() as u32 / 2)); + debug!("index buffer created (len={}) {pres}", buf.len() / 6); + done.push(*pres); + } + } + for pres in &self.vertex_buffers_needed { + if let Some(buf) = dls.try_get(*pres)? { + let buf = buf + .into_iter() + .array_chunks::<4>() + .map(f32::from_be_bytes) + .map(f32::to_le_bytes) + .flatten() + .collect::<Vec<_>>(); + let buffer = self.device.create_buffer_init(&BufferInitDescriptor { + contents: &buf, + label: None, + usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, + }); + self.vertex_buffers.insert(*pres, Arc::new(buffer)); + debug!( + "vertex attribute buffer created (len={}) {pres}", + buf.len() / 4 + ); + done.push(*pres); + } } for pres in &self.parts_needed { if let Some(buf) = dls.try_get(*pres)? { @@ -80,64 +121,72 @@ impl ScenePreparer { self.index_buffers_needed.insert(indexres); continue; }; - let mut positions = Vec::new(); + let mut position = Vec::new(); for vr in positionres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { - let Some(vertex) = self.vertex_buffers.get(&resource).cloned() - else { - self.vertex_buffers_needed.insert(indexres); - continue; + if let Some(vertex) = self.vertex_buffers.get(&resource).cloned() { + position.push(vertex); + } else { + self.vertex_buffers_needed.insert(resource); }; - positions.push(vertex); } Attribute::Texture(_resource) => todo!(), } } - let mut normals = Vec::new(); + let mut normal = Vec::new(); for vr in normalres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { - let Some(vertex) = self.vertex_buffers.get(&resource).cloned() - else { - self.vertex_buffers_needed.insert(indexres); - continue; + if let Some(vertex) = self.vertex_buffers.get(&resource).cloned() { + normal.push(vertex); + } else { + self.vertex_buffers_needed.insert(resource); }; - normals.push(vertex); } Attribute::Texture(_resource) => todo!(), } } - let mut texcoords = Vec::new(); + let mut texcoord = Vec::new(); for vr in texcoordres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { - let Some(vertex) = self.vertex_buffers.get(&resource).cloned() - else { - self.vertex_buffers_needed.insert(indexres); - continue; + if let Some(vertex) = self.vertex_buffers.get(&resource).cloned() { + texcoord.push(vertex); + } else { + self.vertex_buffers_needed.insert(resource); }; - texcoords.push(vertex); } Attribute::Texture(_resource) => todo!(), } } - self.parts.insert( - *pres, - Arc::new(RPart { - index_count, - index, - texcoord: texcoords.try_into().unwrap(), - normal: normals.try_into().unwrap(), - position: positions.try_into().unwrap(), - }), - ); + if texcoord.len() == 2 && normal.len() == 3 && position.len() == 3 { + debug!("part created ({pres})"); + self.parts.insert( + *pres, + Arc::new(RPart { + index_count, + index, + texcoord: texcoord.try_into().unwrap(), + normal: normal.try_into().unwrap(), + position: position.try_into().unwrap(), + }), + ); + done.push(*pres); + } } } } + + for d in done { + self.parts_needed.remove(&d); + self.prefabs_needed.remove(&d); + self.index_buffers_needed.remove(&d); + self.vertex_buffers_needed.remove(&d); + } Ok(()) } } diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs index 366b956..b2cd915 100644 --- a/client/src/scene_render.rs +++ b/client/src/scene_render.rs @@ -4,7 +4,7 @@ use wgpu::{ BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Color, ColorTargetState, ColorWrites, CommandEncoder, Device, FragmentState, FrontFace, IndexFormat, LoadOp, MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor, - PolygonMode, PrimitiveState, PrimitiveTopology, RenderPassColorAttachment, + PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange, RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, ShaderStages, StoreOp, TextureFormat, TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, include_wgsl, @@ -33,7 +33,10 @@ impl ScenePipeline { let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - push_constant_ranges: &[], + push_constant_ranges: &[PushConstantRange { + range: 0..(12 * 4), + stages: ShaderStages::VERTEX, + }], }); let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { label: None, @@ -53,19 +56,12 @@ impl ScenePipeline { entry_point: Some("vs_main"), buffers: &[VertexBufferLayout { step_mode: VertexStepMode::Vertex, - array_stride: 2 * 4 * 3, - attributes: &[ - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 0, - shader_location: 0, - }, - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 3 * 4, - shader_location: 1, - }, - ], + array_stride: 4, + attributes: &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(|i| VertexAttribute { + format: VertexFormat::Float32, + offset: 0, + shader_location: i, + }), }], compilation_options: PipelineCompilationOptions::default(), }, @@ -111,13 +107,13 @@ impl ScenePipeline { })], ..Default::default() }); - rpass.set_bind_group(0, &self.bind_group, &[]); - rpass.set_pipeline(&self.pipeline); for ob in scene.objects.values() { if let Some(prefab) = prefabs.get(&ob.res) { for (affine, part) in &prefab.0 { let affine = affine.to_cols_array().map(|v| v.to_le_bytes()); + rpass.set_bind_group(0, &self.bind_group, &[]); + rpass.set_pipeline(&self.pipeline); rpass.set_push_constants(ShaderStages::VERTEX, 0, affine.as_flattened()); rpass.set_index_buffer(part.index.slice(..), IndexFormat::Uint16); rpass.set_vertex_buffer(0, part.position[0].slice(..)); diff --git a/client/src/shader.wgsl b/client/src/shader.wgsl index 41c21d9..68bd93d 100644 --- a/client/src/shader.wgsl +++ b/client/src/shader.wgsl @@ -1,11 +1,30 @@ -@vertex -fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> { - let x = f32(i32(in_vertex_index) % 2); - let y = f32(i32(in_vertex_index & 1u) * 2 - 1); - return vec4<f32>(x, y, 0.0, 1.0); + +struct VertexIn { + @location(0) x: f32, + @location(1) y: f32, + @location(2) z: f32, + @location(3) nx: f32, + @location(4) ny: f32, + @location(5) nz: f32, + @location(6) u: f32, + @location(7) v: f32, +} +struct VertexOut { + @builtin(position) clip: vec4<f32>, + @location(0) normal: vec3<f32>, + @location(1) uv: vec2<f32>, } +@vertex +fn vs_main(vi: VertexIn) -> VertexOut { + let vo = VertexOut( + vec4(vi.x * 0.1, vi.y * 0.1, 0., 1.), + vec3(vi.nx, vi.ny, vi.nz), + vec2(vi.u, vi.v), + ); + return vo; +} @fragment -fn fs_main() -> @location(0) vec4<f32> { - return vec4<f32>(1.0, 0.0, 0.0, 1.0); +fn fs_main(vo: VertexOut) -> @location(0) vec4<f32> { + return vec4<f32>(vo.normal, 1.0); } diff --git a/server/src/main.rs b/server/src/main.rs index 58c3cb2..5216b41 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -13,7 +13,7 @@ use weareshared::{ #[derive(Parser, Debug)] struct Args { - #[arg(short, long, default_value = "::0")] + #[arg(short, long, default_value = "::")] bind_addr: IpAddr, #[arg(short, long, default_value = "28555")] port: u16, @@ -76,10 +76,10 @@ impl State { net.broadcast(Packet::Remove(object), true); } Packet::Position(object, pos, rot) => { - net.broadcast(Packet::Position(object, pos, rot), true); + net.broadcast(Packet::Position(object, pos, rot), false); } Packet::Pose(object, vec) => { - net.broadcast(Packet::Pose(object, vec), true); + net.broadcast(Packet::Pose(object, vec), false); } Packet::Parent(parent, child) => { net.broadcast(Packet::Parent(parent, child), true); diff --git a/server/src/network.rs b/server/src/network.rs index 211d0bc..64bcf63 100644 --- a/server/src/network.rs +++ b/server/src/network.rs @@ -73,7 +73,7 @@ impl ServerNetwork { } }; spawn(move || { - if let Err(e) = handle_conn_write(conn, sock2, send_rx) { + if let Err(e) = handle_conn_write(sock2, send_rx) { warn!("client outbound error: {e}"); } }); @@ -183,7 +183,7 @@ fn handle_conn_read(conn: u128, sock: TcpStream, tx: Sender<(u128, Packet)>) -> tx.send((conn, packet)).unwrap(); } } -fn handle_conn_write(conn: u128, sock: TcpStream, rx: Receiver<Arc<Vec<u8>>>) -> Result<()> { +fn handle_conn_write(sock: TcpStream, rx: Receiver<Arc<Vec<u8>>>) -> Result<()> { let mut sock = BufWriter::new(sock); for packet in rx { sock.write_all(&packet)?; diff --git a/shared/src/resources.rs b/shared/src/resources.rs index f93de65..042dff3 100644 --- a/shared/src/resources.rs +++ b/shared/src/resources.rs @@ -2,7 +2,10 @@ use crate::packets::{ReadWrite, Resource}; use anyhow::{Result, bail}; use glam::{Affine3A, Vec3A}; use log::warn; -use std::io::{Read, Write}; +use std::{ + fs::File, + io::{Read, Write}, +}; #[derive(Debug, Default, Clone)] pub struct Prefab(pub Vec<(Affine3A, Resource)>); @@ -134,7 +137,8 @@ impl ReadWrite for Part { Ok(s) } } -fn read_kv(r: &mut dyn Read) -> Result<(Vec<u8>, Vec<u8>)> { + +fn read_kv(r: &mut &[u8]) -> Result<(Vec<u8>, Vec<u8>)> { let mut key_size = [0; 2]; let mut value_size = [0; 2]; r.read_exact(&mut key_size)?; @@ -143,8 +147,8 @@ fn read_kv(r: &mut dyn Read) -> Result<(Vec<u8>, Vec<u8>)> { let value_size = u16::from_be_bytes(value_size); let mut key = vec![0; key_size as usize]; let mut value = vec![0; value_size as usize]; - r.read_exact(&mut value)?; r.read_exact(&mut key)?; + r.read_exact(&mut value)?; Ok((key, value)) } diff --git a/world/src/main.rs b/world/src/main.rs index d7272fe..2823540 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -23,6 +23,8 @@ struct Args { scene: PathBuf, #[arg(short, long)] push: bool, + #[arg(short, long)] + spin: bool, } fn main() -> Result<()> { @@ -99,7 +101,6 @@ fn main() -> Result<()> { } .write_alloc(), )?; - let mat = node.transform().matrix(); let aff = Affine3A::from_cols_array_2d(&[ [mat[0][0], mat[0][1], mat[0][2]], @@ -115,18 +116,20 @@ fn main() -> Result<()> { let ob = Object::new(); Packet::Add(ob, store.set(&prefab.write_alloc())?).write(&mut sock)?; - // let mut sock2 = sock.try_clone().unwrap(); - // thread::spawn(move || { - // let mut x = 0.; - // loop { - // Packet::Position(ob, Vec3A::ZERO, vec3a(x, x * 0.3, x * 0.1)) - // .write(&mut sock2) - // .unwrap(); - // sock2.flush().unwrap(); - // x += 0.1; - // sleep(Duration::from_millis(50)); - // } - // }); + if args.spin { + let mut sock2 = sock.try_clone().unwrap(); + thread::spawn(move || { + let mut x = 0.; + loop { + Packet::Position(ob, Vec3A::ZERO, vec3a(x, x * 0.3, x * 0.1)) + .write(&mut sock2) + .unwrap(); + sock2.flush().unwrap(); + x += 0.1; + sleep(Duration::from_millis(50)); + } + }); + } if args.push { store.iter(|d| { |