diff --git a/Cargo.toml b/Cargo.toml index 90fc87e346..f68dd5d321 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,11 +95,6 @@ incremental = true inherits = 'release' debug = 1 -[patch.crates-io] -# macos CI fix isn't merged yet -winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } -vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } - [workspace.metadata.nix] systems = ["x86_64-linux"] @@ -110,3 +105,13 @@ key = "veloren-nix.cachix.org-1:zokfKJqVsNV6kI/oJdLF6TYBdNPYGSb+diMVQPn/5Rc=" [workspace.metadata.nix.crateOverride.veloren-network] buildInputs = ["openssl"] nativeBuildInputs = ["pkg-config"] + +[patch.crates-io] +# macos CI fix isn't merged yet +winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" } +vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" } +# see https://github.com/rustwasm/wasm-bindgen/issues/2371 +wasm-bindgen = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" } +wasm-bindgen-futures = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" } +web-sys = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" } +js-sys = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" } diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 87d7cd49df..2e18b0ca1d 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -45,7 +45,7 @@ i18n = {package = "veloren-i18n", path = "i18n"} # Graphics winit = {version = "0.24.0", features = ["serde"]} -wgpu = { git="https://github.com/gfx-rs/wgpu-rs.git", rev= "ab8b0e3766558d541206da2790dfd63f15b13bc4" } +wgpu = { git="https://github.com/Imberflur/wgpu-rs.git" } bytemuck = { version="1.4", features=["derive"] } shaderc = "0.6.2" diff --git a/voxygen/src/render/buffer.rs b/voxygen/src/render/buffer.rs index 5f1ad7058a..8d128d486f 100644 --- a/voxygen/src/render/buffer.rs +++ b/voxygen/src/render/buffer.rs @@ -3,44 +3,60 @@ use wgpu::util::DeviceExt; pub struct Buffer { pub buf: wgpu::Buffer, - // bytes - count: usize, + // Size in number of elements + // TODO: determine if this is a good name + len: usize, phantom_data: std::marker::PhantomData, } impl Buffer { - pub fn new(device: &wgpu::Device, cap: u64, usage: wgpu::BufferUsage) -> Self { - Self { - buf: device.create_buffer(&wgpu::BufferDescriptor { - label: None, - mapped_at_creation: false, - size: cap, - usage: usage | wgpu::BufferUsage::MAP_WRITE, - }), - count: 0, - phantom_data: std::marker::PhantomData, - } - } - - pub fn new_with_data(device: &wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self { + pub fn new(device: &wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self { let contents = bytemuck::cast_slice(data); Self { buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: None, contents, - usage: usage | wgpu::BufferUsage::MAP_WRITE, + usage, }), - count: data.len(), + len: data.len(), phantom_data: std::marker::PhantomData, } } - pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) { - if !vals.is_empty() { - queue.write_buffer(&self.buf, offset, bytemuck::cast_slice(vals)) - } + pub fn len(&self) -> usize { self.len } +} + +pub struct DynamicBuffer(Buffer); + +impl DynamicBuffer { + pub fn new(device: &wgpu::Device, len: usize, usage: wgpu::BufferUsage) -> Self { + let buffer = Buffer { + buf: device.create_buffer(&wgpu::BufferDescriptor { + label: None, + mapped_at_creation: false, + size: (len / std::mem::size_of::()) as u64, + usage: usage | wgpu::BufferUsage::COPY_DST, + }), + len, + phantom_data: std::marker::PhantomData, + }; + Self(buffer) } - pub fn count(&self) -> usize { self.count } + pub fn update(&self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: usize) { + if !vals.is_empty() { + queue.write_buffer( + &self.buf, + (offset / std::mem::size_of::()) as u64, + bytemuck::cast_slice(vals), + ) + } + } +} + +impl std::ops::Deref for DynamicBuffer { + type Target = Buffer; + + fn deref(&self) -> &Self::Target { &self.0 } } diff --git a/voxygen/src/render/consts.rs b/voxygen/src/render/consts.rs index e1c28b7e43..c1b348f457 100644 --- a/voxygen/src/render/consts.rs +++ b/voxygen/src/render/consts.rs @@ -1,23 +1,30 @@ -use super::buffer::Buffer; +use super::buffer::DynamicBuffer; use bytemuck::Pod; /// A handle to a series of constants sitting on the GPU. This is used to hold /// information used in the rendering process that does not change throughout a /// single render pass. pub struct Consts { - buf: Buffer, + buf: DynamicBuffer, } impl Consts { /// Create a new `Const`. - pub fn new(device: &wgpu::Device, len: u64) -> Self { + pub fn new(device: &wgpu::Device, len: usize) -> Self { Self { - buf: Buffer::new(device, len, wgpu::BufferUsage::UNIFORM), + // TODO: examine if all our consts need to be updateable + buf: DynamicBuffer::new(device, len, wgpu::BufferUsage::UNIFORM), } } /// Update the GPU-side value represented by this constant handle. - pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) { + pub fn update( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + vals: &[T], + offset: usize, + ) { self.buf.update(device, queue, vals, offset) } diff --git a/voxygen/src/render/error.rs b/voxygen/src/render/error.rs index 874965e9b0..eb71fcb083 100644 --- a/voxygen/src/render/error.rs +++ b/voxygen/src/render/error.rs @@ -1,6 +1,5 @@ /// Used to represent one of many possible errors that may be omitted by the /// rendering subsystem. -#[derive(Debug)] pub enum RenderError { RequestDeviceError(wgpu::RequestDeviceError), MappingError(wgpu::BufferAsyncError), @@ -11,6 +10,23 @@ pub enum RenderError { ShaderError(shaderc::Error), } +use std::fmt; +impl fmt::Debug for RenderError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::RequestDeviceError(err) => { + f.debug_tuple("RequestDeviceError").field(err).finish() + }, + Self::MappingError(err) => f.debug_tuple("MappingError").field(err).finish(), + Self::SwapChainError(err) => f.debug_tuple("SwapChainError").field(err).finish(), + Self::CustomError(err) => f.debug_tuple("CustomError").field(err).finish(), + Self::CouldNotFindAdapter => f.debug_tuple("CouldNotFindAdapter").finish(), + Self::ErrorInitializingCompiler => f.debug_tuple("ErrorInitializingCompiler").finish(), + Self::ShaderError(err) => write!(f, "{}", err), + } + } +} + impl From for RenderError { fn from(err: wgpu::RequestDeviceError) -> Self { Self::RequestDeviceError(err) } } diff --git a/voxygen/src/render/instances.rs b/voxygen/src/render/instances.rs index a178b44f71..6ea03dd577 100644 --- a/voxygen/src/render/instances.rs +++ b/voxygen/src/render/instances.rs @@ -1,21 +1,30 @@ -use super::buffer::Buffer; +use super::buffer::DynamicBuffer; use bytemuck::Pod; /// Represents a mesh that has been sent to the GPU. pub struct Instances { - buf: Buffer, + buf: DynamicBuffer, } impl Instances { - pub fn new(device: &wgpu::Device, len: u64) -> Self { + pub fn new(device: &wgpu::Device, len: usize) -> Self { Self { - buf: Buffer::new(device, len, wgpu::BufferUsage::VERTEX), + // TODO: examine if we have Intances that are not updated and if there would be any + // gains from separating those out + buf: DynamicBuffer::new(device, len, wgpu::BufferUsage::VERTEX), } } - pub fn count(&self) -> usize { self.buf.count() } + // TODO: count vs len naming scheme?? + pub fn count(&self) -> usize { self.buf.len() } - pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) { + pub fn update( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + vals: &[T], + offset: usize, + ) { self.buf.update(device, queue, vals, offset) } diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index a8fed89da6..15b2d144af 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -15,7 +15,7 @@ pub use self::{ error::RenderError, instances::Instances, mesh::{Mesh, Quad, Tri}, - model::{Model, SubModel}, + model::{DynamicModel, Model, SubModel}, pipelines::{ clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals}, figure::{ diff --git a/voxygen/src/render/model.rs b/voxygen/src/render/model.rs index 3657de15df..771ef9d50e 100644 --- a/voxygen/src/render/model.rs +++ b/voxygen/src/render/model.rs @@ -1,4 +1,8 @@ -use super::{buffer::Buffer, mesh::Mesh, Vertex}; +use super::{ + buffer::{Buffer, DynamicBuffer}, + mesh::Mesh, + Vertex, +}; use std::ops::Range; /// Represents a mesh that has been sent to the GPU. @@ -20,13 +24,7 @@ pub struct Model { impl Model { pub fn new(device: &wgpu::Device, mesh: &Mesh) -> Self { Self { - vbuf: Buffer::new_with_data(device, wgpu::BufferUsage::VERTEX, mesh.vertices()), - } - } - - pub fn new_dynamic(device: &wgpu::Device, size: u64) -> Self { - Self { - vbuf: Buffer::new(device, size, wgpu::BufferUsage::VERTEX), + vbuf: Buffer::new(device, wgpu::BufferUsage::VERTEX, mesh.vertices()), } } @@ -40,15 +38,44 @@ impl Model { } } + pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } + + pub fn len(&self) -> usize { self.vbuf.len() } +} + +/// Represents a mesh that has been sent to the GPU. +pub struct DynamicModel { + vbuf: DynamicBuffer, +} + +impl DynamicModel { + pub fn new(device: &wgpu::Device, size: usize) -> Self { + Self { + vbuf: DynamicBuffer::new(device, size, wgpu::BufferUsage::VERTEX), + } + } + pub fn update( - &mut self, + &self, device: &wgpu::Device, queue: &wgpu::Queue, mesh: &Mesh, - offset: u64, + offset: usize, ) { self.vbuf.update(device, queue, mesh.vertices(), offset) } + /// Create a model with a slice of a portion of this model to send to the + /// renderer. + pub fn submodel(&self, vertex_range: Range) -> SubModel { + SubModel { + vertex_range, + buf: self.buf(), + phantom_data: std::marker::PhantomData, + } + } + pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf } + + pub fn len(&self) -> usize { self.vbuf.len() } } diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 6dd6a65c5b..03448edbc2 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -209,6 +209,7 @@ impl FigurePipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index 1ab92a6306..568af09c9d 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -33,14 +33,12 @@ impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = + wgpu::vertex_attr_array![0 => Uint]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &[wgpu::VertexAttributeDescriptor { - offset: 0, - shader_location: 0, - format: wgpu::VertexFormat::Uint, - }], + attributes: &ATTRIBUTES, } } } @@ -121,6 +119,7 @@ impl FluidPipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::None, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 946ffa2f83..a46f32f27c 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -17,14 +17,12 @@ impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = + wgpu::vertex_attr_array![0 => Float2]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &[wgpu::VertexAttributeDescriptor { - offset: 0, - shader_location: 0, - format: wgpu::VertexFormat::Float2, - }], + attributes: &ATTRIBUTES, } } } @@ -87,7 +85,6 @@ impl LodData { &texture_info, &view_info, &sampler_info, - map_size.x * 4, bytemuck::cast_slice(lod_base), ); texture_info.format = wgpu::TextureFormat::Rg16Uint; @@ -96,7 +93,6 @@ impl LodData { &texture_info, &view_info, &sampler_info, - map_size.x * 4, bytemuck::cast_slice(lod_base), ); texture_info.format = wgpu::TextureFormat::Rgba8Unorm; @@ -105,7 +101,6 @@ impl LodData { &texture_info, &view_info, &sampler_info, - map_size.x * 4, bytemuck::cast_slice(lod_base), ); @@ -198,6 +193,7 @@ impl LodTerrainPipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index eeebc7d1dd..a1e311c089 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -33,10 +33,12 @@ impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 2] = + wgpu::vertex_attr_array![0 => Float3, 1 => Uint]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Uint], + attributes: &ATTRIBUTES, } } } @@ -150,10 +152,12 @@ impl Instance { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 5] = + wgpu::vertex_attr_array![0 => Float, 1 => Float, 2 => Float, 3 => Int, 4 => Float3]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, - attributes: &wgpu::vertex_attr_array![0 => Float, 1 => Float, 2 => Float, 3 => Int, 4 => Float3], + attributes: &ATTRIBUTES, } } } @@ -205,6 +209,7 @@ impl ParticlePipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 71ff04b601..0c4a87a0c9 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -31,14 +31,12 @@ pub struct Vertex { impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = + wgpu::vertex_attr_array![0 => Float2]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &[wgpu::VertexAttributeDescriptor { - offset: 0, - shader_location: 0, - format: wgpu::VertexFormat::Float2, - }], + attributes: &ATTRIBUTES, } } } @@ -139,6 +137,7 @@ impl PostProcessPipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index cd2be9f80a..7867cd9eb2 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -95,7 +95,6 @@ pub fn create_col_lights( &texture_info, &view_info, &sampler_info, - col_lights_size.x * 4, bytemuck::cast_slice(&col_lights), ) } @@ -149,6 +148,7 @@ impl ShadowFigurePipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, @@ -231,6 +231,7 @@ impl ShadowPipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/skybox.rs b/voxygen/src/render/pipelines/skybox.rs index 712de2619a..0e58c403ec 100644 --- a/voxygen/src/render/pipelines/skybox.rs +++ b/voxygen/src/render/pipelines/skybox.rs @@ -65,6 +65,7 @@ impl SkyboxPipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, @@ -103,6 +104,7 @@ impl SkyboxPipeline { } } +// TODO: generate mesh in vertex shader pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index c7ad1582e8..8ae972c10a 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -61,10 +61,12 @@ impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 3] = + wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint], + attributes: &ATTRIBUTES, } } } @@ -109,10 +111,11 @@ impl Instance { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 6] = wgpu::vertex_attr_array![0 => Uint, 1 => Float4,2 => Float4, 3 => Float4,4 => Float4, 5 => Float]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Instance, - attributes: &wgpu::vertex_attr_array![0 => Uint, 1 => Float4,2 => Float4, 3 => Float4,4 => Float4,5 => Float], + attributes: &ATTRIBUTES, } } } @@ -253,6 +256,7 @@ impl SpritePipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 7a397aef4a..2e8954f98c 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -120,20 +120,23 @@ impl Vertex { pub fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 2] = + wgpu::vertex_attr_array![0 => Uint,1 => Uint]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &wgpu::vertex_attr_array![0 => Uint,1 => Uint], + attributes: &ATTRIBUTES, } } } #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] +// TODO: new function and private fields?? pub struct Locals { - model_offs: [f32; 3], - load_time: f32, - atlas_offs: [i32; 4], + pub model_offs: [f32; 3], + pub load_time: f32, + pub atlas_offs: [i32; 4], } impl Locals { @@ -233,6 +236,7 @@ impl TerrainPipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index e8f5b73458..9fe36a018c 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -15,10 +15,12 @@ pub struct Vertex { impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; + const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 5] = + wgpu::vertex_attr_array![0 => Float2, 1 => Float2, 2 => Float4, 3 => Float2, 4 => Uint]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &wgpu::vertex_attr_array![0 => Float2, 1 => Float2, 2 => Float4, 3 => Float2, 4 => Uint], + attributes: &ATTRIBUTES, } } } @@ -165,6 +167,7 @@ impl UIPipeline { rasterization_state: Some(wgpu::RasterizationStateDescriptor { front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 6c0bc30424..601dc2cfb9 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -2,7 +2,7 @@ use super::{ consts::Consts, instances::Instances, mesh::Mesh, - model::Model, + model::{DynamicModel, Model}, pipelines::{ clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, GlobalsLayouts, @@ -177,9 +177,9 @@ pub struct Layouts { /// rendering subsystem and contains any state necessary to interact with the /// GPU, along with pipeline state objects (PSOs) needed to renderer different /// kinds of models to the screen. -pub struct Renderer<'a> { - window: &'a winit::window::Window, - +pub struct Renderer { + // TODO: why???? + //window: &'a winit::window::Window, device: wgpu::Device, queue: wgpu::Queue, swap_chain: wgpu::SwapChain, @@ -216,12 +216,14 @@ pub struct Renderer<'a> { noise_tex: Texture, mode: RenderMode, + + resolution: Vec2, } -impl<'a> Renderer<'a> { +impl Renderer { /// Create a new `Renderer` from a variety of backend-specific components /// and the window targets. - pub fn new(window: &'a winit::window::Window, mode: RenderMode) -> Result { + pub fn new(window: &winit::window::Window, mode: RenderMode) -> Result { // Enable seamless cubemaps globally, where available--they are essentially a // strict improvement on regular cube maps. // @@ -231,7 +233,9 @@ impl<'a> Renderer<'a> { let dims = window.inner_size(); - let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY | wgpu::BackendBit::SECONDARY); + let instance = wgpu::Instance::new( + wgpu::BackendBit::PRIMARY, /* | wgpu::BackendBit::SECONDARY */ + ); // This is unsafe because the window handle must be valid, if you find a way to // have an invalid winit::Window then you have bigger issues @@ -251,6 +255,7 @@ impl<'a> Renderer<'a> { let (device, queue) = futures::executor::block_on(adapter.request_device( &wgpu::DeviceDescriptor { // TODO + label: None, features: Features::DEPTH_CLAMPING | Features::ADDRESS_MODE_CLAMP_TO_BORDER, limits: Limits::default(), shader_validation: true, @@ -269,7 +274,7 @@ impl<'a> Renderer<'a> { ); let sc_desc = wgpu::SwapChainDescriptor { - usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, + usage: wgpu::TextureUsage::RENDER_ATTACHMENT, format: wgpu::TextureFormat::Bgra8UnormSrgb, width: dims.width, height: dims.height, @@ -387,8 +392,6 @@ impl<'a> Renderer<'a> { )?; Ok(Self { - window, - device, queue, swap_chain, @@ -423,6 +426,8 @@ impl<'a> Renderer<'a> { noise_tex, mode, + + resolution: Vec2::new(dims.width, dims.height), }) } @@ -443,7 +448,7 @@ impl<'a> Renderer<'a> { self.mode = mode; // Recreate render target - self.on_resize()?; + self.on_resize(self.resolution)?; // Recreate pipelines with the new AA mode self.recreate_pipelines(); @@ -455,13 +460,11 @@ impl<'a> Renderer<'a> { pub fn render_mode(&self) -> &RenderMode { &self.mode } /// Resize internal render targets to match window render target dimensions. - pub fn on_resize(&mut self) -> Result<(), RenderError> { - let dims = self.window.inner_size(); - + pub fn on_resize(&mut self, dims: Vec2) -> Result<(), RenderError> { // Avoid panics when creating texture with w,h of 0,0. - if dims.width != 0 && dims.height != 0 { + if dims.x != 0 && dims.y != 0 { let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) = - Self::create_rt_views(&mut self.device, (dims.width, dims.height), &self.mode)?; + Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?; self.win_depth_view = win_depth_view; self.tgt_color_view = tgt_color_view; self.tgt_depth_stencil_view = tgt_depth_stencil_view; @@ -469,8 +472,7 @@ impl<'a> Renderer<'a> { if let (Some(shadow_map), ShadowMode::Map(mode)) = (self.shadow_map.as_mut(), self.mode.shadow) { - match Self::create_shadow_views(&mut self.device, (dims.width, dims.height), &mode) - { + match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) { Ok((point_depth_stencil, directed_depth_stencil)) => { shadow_map.point_depth_stencil = point_depth_stencil; shadow_map.directed_depth_stencil = directed_depth_stencil; @@ -480,6 +482,8 @@ impl<'a> Renderer<'a> { }, } } + + self.resolution = dims; } Ok(()) @@ -523,7 +527,7 @@ impl<'a> Renderer<'a> { sample_count, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }); tex.create_view(&wgpu::TextureViewDescriptor { @@ -553,7 +557,7 @@ impl<'a> Renderer<'a> { sample_count, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Depth24Plus, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }); let tgt_depth_stencil_view = tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor { @@ -578,7 +582,7 @@ impl<'a> Renderer<'a> { sample_count, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Depth24Plus, - usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, + usage: wgpu::TextureUsage::RENDER_ATTACHMENT, }); let win_depth_view = tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor { label: None, @@ -667,7 +671,19 @@ impl<'a> Renderer<'a> { sample_count: 1, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Depth24Plus, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, + }; + + //TODO: (0, levels - 1), ?? from master + let mut point_shadow_view = wgpu::TextureViewDescriptor { + label: None, + format: Some(wgpu::TextureFormat::Depth24Plus), + dimension: Some(wgpu::TextureViewDimension::Cube), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: None, + base_array_layer: 0, + array_layer_count: None, }; let directed_shadow_tex = wgpu::TextureDescriptor { @@ -681,10 +697,10 @@ impl<'a> Renderer<'a> { sample_count: 1, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Depth24Plus, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, }; - let mut view_info = wgpu::TextureViewDescriptor { + let directed_shadow_view = wgpu::TextureViewDescriptor { label: None, format: Some(wgpu::TextureFormat::Depth24Plus), dimension: Some(wgpu::TextureViewDimension::D2), @@ -707,30 +723,27 @@ impl<'a> Renderer<'a> { ..Default::default() }; - let point_tgt_shadow = - Texture::new_raw(device, &point_shadow_tex, &view_info, &sampler_info); - view_info.dimension = Some(wgpu::TextureViewDimension::Cube); - let directed_shadow_tex = - Texture::new_raw(device, &directed_shadow_tex, &view_info, &sampler_info); + let point_shadow_tex = + Texture::new_raw(device, &point_shadow_tex, &point_shadow_view, &sampler_info); + let directed_shadow_tex = Texture::new_raw( + device, + &directed_shadow_tex, + &directed_shadow_view, + &sampler_info, + ); - Ok((point_tgt_shadow, directed_shadow_tex)) + Ok((point_shadow_tex, directed_shadow_tex)) } /// Get the resolution of the render target. - pub fn get_resolution(&self) -> Vec2 { - let dims = self.window.inner_size(); - - Vec2::new(dims.width, dims.height) - } + pub fn resolution(&self) -> Vec2 { self.resolution } /// Get the resolution of the shadow render target. pub fn get_shadow_resolution(&self) -> (Vec2, Vec2) { if let Some(shadow_map) = &self.shadow_map { - let point_dims = shadow_map.point_depth_stencil.get_dimensions(); - let directed_dims = shadow_map.directed_depth_stencil.get_dimensions(); ( - Vec2::new(point_dims.width, point_dims.height), - Vec2::new(directed_dims.width, directed_dims.height), + shadow_map.point_depth_stencil.get_dimensions().xy(), + shadow_map.directed_depth_stencil.get_dimensions().xy(), ) } else { (Vec2::new(1, 1), Vec2::new(1, 1)) @@ -882,7 +895,7 @@ impl<'a> Renderer<'a> { &mut self, vals: &[T], ) -> Result, RenderError> { - let mut consts = Consts::new(&self.device, vals.len() as u64); + let mut consts = Consts::new(&self.device, vals.len()); consts.update(&self.device, &self.queue, vals, 0); Ok(consts) } @@ -897,7 +910,7 @@ impl<'a> Renderer<'a> { &mut self, vals: &[T], ) -> Result, RenderError> { - let mut instances = Instances::new(&self.device, vals.len() as u64); + let mut instances = Instances::new(&self.device, vals.len()); instances.update(&self.device, &self.queue, vals, 0); Ok(instances) } @@ -908,12 +921,12 @@ impl<'a> Renderer<'a> { } /// Create a new dynamic model with the specified size. - pub fn create_dynamic_model(&mut self, size: u64) -> Model { - Model::new_dynamic(&self.device, size) + pub fn create_dynamic_model(&mut self, size: usize) -> DynamicModel { + DynamicModel::new(&self.device, size) } /// Update a dynamic model with a mesh and a offset. - pub fn update_model(&mut self, model: &Model, mesh: &Mesh, offset: u64) { + pub fn update_model(&self, model: &DynamicModel, mesh: &Mesh, offset: usize) { model.update(&self.device, &self.queue, mesh, offset) } @@ -933,7 +946,6 @@ impl<'a> Renderer<'a> { texture_info: &wgpu::TextureDescriptor, view_info: &wgpu::TextureViewDescriptor, sampler_info: &wgpu::SamplerDescriptor, - bytes_per_row: u32, data: &[u8], ) -> Texture { let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info); @@ -944,7 +956,6 @@ impl<'a> Renderer<'a> { [0; 2], [texture_info.size.width, texture_info.size.height], data, - bytes_per_row, ); tex @@ -1004,7 +1015,6 @@ impl<'a> Renderer<'a> { // Copy, { // texture.update(&mut self.encoder, offset, size, data) data: &[[u8; 4]], - bytes_per_row: u32, ) { texture.update( &self.device, @@ -1012,7 +1022,6 @@ impl<'a> Renderer<'a> { offset, size, bytemuck::cast_slice(data), - bytes_per_row, ) } @@ -1882,16 +1891,16 @@ fn create_pipelines( Ok(ResolvedInclude { resolved_name: name.to_string(), content: match name { - "constants.glsl" => constants, - "globals.glsl" => *globals, - "shadows.glsl" => *shadows, - "sky.glsl" => *sky, - "light.glsl" => *light, - "srgb.glsl" => *srgb, - "random.glsl" => *random, - "lod.glsl" => *lod, - "anti-aliasing.glsl" => *anti_alias, - "cloud.glsl" => *cloud, + "constants.glsl" => constants.clone(), + "globals.glsl" => globals.as_ref().clone(), + "shadows.glsl" => shadows.as_ref().clone(), + "sky.glsl" => sky.as_ref().clone(), + "light.glsl" => light.as_ref().clone(), + "srgb.glsl" => srgb.as_ref().clone(), + "random.glsl" => random.as_ref().clone(), + "lod.glsl" => lod.as_ref().clone(), + "anti-aliasing.glsl" => anti_alias.as_ref().clone(), + "cloud.glsl" => cloud.as_ref().clone(), other => return Err(format!("Include {} is not defined", other)), }, }) @@ -2298,7 +2307,7 @@ fn create_pipelines( )) } -pub fn create_shader_module( +fn create_shader_module( device: &wgpu::Device, compiler: &mut shaderc::Compiler, source: &str, diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 375015f9ed..990d55547e 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -18,7 +18,7 @@ impl Texture { filter_method: Option, address_mode: Option, ) -> Result { - // TODO: Actualy handle images that aren't in rgba format properly. + // TODO: Actually handle images that aren't in rgba format properly. let buffer = image.as_flat_samples_u8().ok_or_else(|| { RenderError::CustomError( "We currently do not support color formats using more than 4 bytes / pixel.".into(), @@ -38,7 +38,7 @@ impl Texture { sample_count: 1, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, }); let mut command_encoder = @@ -107,7 +107,8 @@ impl Texture { sample_count: 1, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, + // TODO: nondynamic version doesn't seeem to have different usage, unify code? + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, }; let sampler_info = wgpu::SamplerDescriptor { @@ -161,8 +162,10 @@ impl Texture { offset: [u32; 2], size: [u32; 2], data: &[u8], - bytes_per_row: u32, ) { + // Note: we only accept 4 bytes per pixel + // (enforce this is API?) + debug_assert_eq!(data.len(), size[0] as usize * size[1] as usize * 4); // TODO: Only works for 2D images queue.write_texture( wgpu::TextureCopyViewBase { @@ -177,8 +180,8 @@ impl Texture { data, wgpu::TextureDataLayout { offset: 0, - bytes_per_row, - rows_per_image: self.size.height, + bytes_per_row: size[0] * 4, + rows_per_image: size[1], }, wgpu::Extent3d { width: size[0], @@ -189,5 +192,7 @@ impl Texture { } /// Get dimensions of the represented image. - pub fn get_dimensions(&self) -> Extent3d { self.size } + pub fn get_dimensions(&self) -> vek::Vec3 { + vek::Vec3::new(self.size.width, self.size.height, self.size.depth) + } } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index c36f9da229..6d5902a34a 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -8,7 +8,7 @@ use crate::{ ecs::comp::Interpolated, render::{ pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, - Mesh, RenderError, Renderer, TerrainVertex, Texture, + Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture, }, scene::{ camera::{Camera, CameraMode, Dependents}, @@ -63,7 +63,7 @@ pub type CameraData<'a> = (&'a Camera, f32); pub type FigureModelRef<'a> = ( &'a Consts, &'a Consts, - &'a FigureModel, + SubModel<'a, TerrainVertex>, &'a Texture, /* */ ); @@ -81,9 +81,19 @@ pub struct FigureModelEntry { /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different * LOD levels. */ col_lights: Texture, /* */ - /// Models stored in this figure entry; there may be several for one figure, - /// because of LOD models. - pub models: [FigureModel; N], + /// Vertex ranges stored in this figure entry; there may be several for one + /// figure, because of LOD models. + lod_vertex_ranges: [Range; N], + model: FigureModel, +} + +impl FigureModelEntry { + pub fn lod_model(&self, lod: usize) -> SubModel { + // Note: Range doesn't impl Copy even for trivially Cloneable things + self.model + .opaque + .submodel(self.lod_vertex_ranges[lod].clone()) + } } struct FigureMgrStates { @@ -4734,13 +4744,14 @@ impl FigureMgr { figure_lod_render_distance * scale.map_or(1.0, |s| s.0), |state| state.can_shadow_sun(), ) { - renderer.render_figure_shadow_directed( - model, - global, - locals, - bone_consts, - &global.shadow_mats, - ); + // TODO + //renderer.render_figure_shadow_directed( + // model, + // global, + // locals, + // bone_consts, + // &global.shadow_mats, + //); } }); } @@ -4791,7 +4802,8 @@ impl FigureMgr { figure_lod_render_distance * scale.map_or(1.0, |s| s.0), |state| state.visible(), ) { - renderer.render_figure(model, &col_lights, global, locals, bone_consts, lod); + // renderer.render_figure(model, &col_lights, global, + // locals, bone_consts, lod); } } } @@ -4839,15 +4851,16 @@ impl FigureMgr { figure_lod_render_distance, |state| state.visible(), ) { - renderer.render_player(model, &col_lights, global, locals, bone_consts, lod); - renderer.render_player_shadow( + //renderer.render_player(model, &col_lights, global, locals, + // bone_consts, lod); + /*renderer.render_player_shadow( model, &col_lights, global, bone_consts, lod, &global.shadow_mats, - ); + );*/ } } } @@ -5175,11 +5188,11 @@ impl FigureMgr { let figure_mid_detail_distance = figure_lod_render_distance * 0.5; let model = if pos.distance_squared(cam_pos) > figure_low_detail_distance.powi(2) { - &model_entry.models[2] + model_entry.lod_model(2) } else if pos.distance_squared(cam_pos) > figure_mid_detail_distance.powi(2) { - &model_entry.models[1] + model_entry.lod_model(1) } else { - &model_entry.models[0] + model_entry.lod_model(0) }; Some((locals, bone_consts, model, col_lights_.texture(model_entry))) @@ -5225,7 +5238,7 @@ impl FigureColLights { renderer: &mut Renderer, (tex, tex_size): ColLightInfo, (opaque, bounds): (Mesh, math::Aabb), - vertex_range: [Range; N], + vertex_ranges: [Range; N], ) -> Result, RenderError> { span!(_guard, "create_figure", "FigureColLights::create_figure"); let atlas = &mut self.atlas; @@ -5237,22 +5250,22 @@ impl FigureColLights { .expect("The model size for this figure does not fit in a u32!"); let model = renderer.create_model(&opaque)?; + vertex_ranges.iter().for_each(|range| { + assert!( + range.start <= range.end && range.end <= model_len, + "The provided vertex range for figure mesh {:?} does not fit in the model, which \ + is of size {:?}!", + range, + model_len + ); + }); + Ok(FigureModelEntry { _bounds: bounds, - models: vertex_range.map(|range| { - assert!( - range.start <= range.end && range.end <= model_len, - "The provided vertex range for figure mesh {:?} does not fit in the model, \ - which is of size {:?}!", - range, - model_len - ); - FigureModel { - opaque: model.submodel(range), - } - }), - col_lights, allocation, + col_lights, + lod_vertex_ranges: vertex_ranges, + model: FigureModel { opaque: model }, }) } diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index ab190e340d..17bfd64907 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -61,7 +61,8 @@ impl Lod { pub fn render(&self, renderer: &mut Renderer, global: &GlobalModel) { if let Some((_, model)) = self.model.as_ref() { - renderer.render_lod_terrain(&model, global, &self.locals, &self.data); + //renderer.render_lod_terrain(&model, global, &self.locals, + // &self.data); } } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 9aad8e2216..7e26f83397 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -271,7 +271,7 @@ impl Scene { client: &Client, settings: &Settings, ) -> Self { - let resolution = renderer.get_resolution().map(|e| e as f32); + let resolution = renderer.resolution().map(|e| e as f32); let sprite_render_context = lazy_init(renderer); Self { @@ -642,7 +642,7 @@ impl Scene { self.map_bounds, time_of_day, scene_data.state.get_time(), - renderer.get_resolution().as_(), + renderer.resolution().as_(), Vec2::new(SHADOW_NEAR, SHADOW_FAR), lights.len(), shadows.len(), @@ -1061,7 +1061,7 @@ impl Scene { self.lod.render(renderer, global); // Render the skybox. - renderer.render_skybox(&self.skybox.model, global, &self.skybox.locals, lod); + // TODO: renderer.render_skybox(&self.skybox.model, global, lod); self.terrain.render_translucent( renderer, @@ -1075,19 +1075,20 @@ impl Scene { // Render particle effects. self.particle_mgr.render(renderer, scene_data, global, lod); - // Render clouds (a post-processing effect) - renderer.render_clouds( - &self.clouds.model, - &global.globals, - &self.clouds.locals, - self.lod.get_data(), - ); + // TODO: + // // Render clouds (a post-processing effect) + // renderer.render_clouds( + // &self.clouds.model, + // &global.globals, + // &self.clouds.locals, + // self.lod.get_data(), + // ); - renderer.render_post_process( - &self.postprocess.model, - &global.globals, - &self.postprocess.locals, - self.lod.get_data(), - ); + // renderer.render_post_process( + // &self.postprocess.model, + // &global.globals, + // &self.postprocess.locals, + // self.lod.get_data(), + // ); } } diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 008b215729..63675fb048 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -1192,7 +1192,8 @@ impl ParticleMgr { .get(DEFAULT_MODEL_KEY) .expect("Expected particle model in cache"); - renderer.render_particles(model, global, &self.instances, lod); + /* renderer.render_particles(model, global, &self.instances, + * lod); */ } } diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 2033e035b5..7f045eca8f 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -30,7 +30,6 @@ use common::{ terrain::BlockKind, vol::{BaseVol, ReadVol}, }; -use tracing::error; use vek::*; use winit::event::MouseButton; @@ -104,7 +103,7 @@ pub struct SceneData<'a> { impl Scene { pub fn new(renderer: &mut Renderer, backdrop: Option<&str>, client: &Client) -> Self { let start_angle = 90.0f32.to_radians(); - let resolution = renderer.get_resolution().map(|e| e as f32); + let resolution = renderer.resolution().map(|e| e as f32); let map_bounds = Vec2::new( client.world_data().min_chunk_alt(), @@ -278,7 +277,7 @@ impl Scene { self.map_bounds, TIME, scene_data.time, - renderer.get_resolution().as_(), + renderer.resolution().as_(), Vec2::new(SHADOW_NEAR, SHADOW_FAR), 0, 0, @@ -380,12 +379,12 @@ impl Scene { body: Option, inventory: Option<&Inventory>, ) { - renderer.render_skybox( + /*renderer.render_skybox( &self.skybox.model, &self.data, &self.skybox.locals, &self.lod, - ); + );*/ if let Some(body) = body { let model = &self.figure_model_cache.get_model( @@ -398,40 +397,40 @@ impl Scene { ); if let Some(model) = model { - renderer.render_figure( - &model.models[0], - &self.col_lights.texture(model), - &self.data, - self.figure_state.locals(), - self.figure_state.bone_consts(), - &self.lod, - ); + // renderer.render_figure( + // &model.models[0], + // &self.col_lights.texture(model), + // &self.data, + // self.figure_state.locals(), + // self.figure_state.bone_consts(), + // &self.lod, + // ); } } if let Some((model, state)) = &self.backdrop { - renderer.render_figure( + /*renderer.render_figure( &model.models[0], &self.col_lights.texture(model), &self.data, state.locals(), state.bone_consts(), &self.lod, - ); + );*/ } - renderer.render_clouds( - &self.clouds.model, - &self.data.globals, - &self.clouds.locals, - &self.lod, - ); + // renderer.render_clouds( + // &self.clouds.model, + // &self.data.globals, + // &self.clouds.locals, + // &self.lod, + // ); - renderer.render_post_process( - &self.postprocess.model, - &self.data.globals, - &self.postprocess.locals, - &self.lod, - ); + // renderer.render_post_process( + // &self.postprocess.model, + // &self.data.globals, + // &self.postprocess.locals, + // &self.lod, + // ); } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 8e12e4423c..02b367a119 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1429,12 +1429,12 @@ impl Terrain { .chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk)) .for_each(|chunk| { // Directed light shadows. - renderer.render_terrain_shadow_directed( + /*renderer.render_terrain_shadow_directed( &chunk.opaque_model, global, &chunk.locals, &global.shadow_mats, - ); + );*/ }); } @@ -1445,12 +1445,12 @@ impl Terrain { light_data.iter().take(1).for_each(|_light| { chunk_iter.clone().for_each(|chunk| { if chunk.can_shadow_point { - renderer.render_shadow_point( + /*renderer.render_shadow_point( &chunk.opaque_model, global, &chunk.locals, &global.shadow_mats, - ); + );*/ } }); }); @@ -1477,13 +1477,13 @@ impl Terrain { for (_, chunk) in chunk_iter { if chunk.visible.is_visible() { - renderer.render_terrain_chunk( + /* renderer.render_terrain_chunk( &chunk.opaque_model, &chunk.texture, global, &chunk.locals, lod, - ); + );*/ } } } @@ -1558,7 +1558,7 @@ impl Terrain { } else { &self.sprite_data[&kind][4] }; - renderer.render_sprites( + /*renderer.render_sprites( model, &self.sprite_col_lights, global, @@ -1566,7 +1566,7 @@ impl Terrain { locals, &instances, lod, - ); + );*/ } } } @@ -1587,13 +1587,13 @@ impl Terrain { .into_iter() .rev() // Render back-to-front .for_each(|(model, locals)| { - renderer.render_fluid_chunk( + /*renderer.render_fluid_chunk( model, global, locals, lod, &self.waves, - ) + )*/ }); } } diff --git a/voxygen/src/ui/cache.rs b/voxygen/src/ui/cache.rs index ab057ffedc..7d5fba7bbc 100644 --- a/voxygen/src/ui/cache.rs +++ b/voxygen/src/ui/cache.rs @@ -8,7 +8,7 @@ use hashbrown::HashMap; use vek::*; // Multiplied by current window size -const GLYPH_CACHE_SIZE: u16 = 1; +const GLYPH_CACHE_SIZE: u32 = 1; // Glyph cache tolerances const SCALE_TOLERANCE: f32 = 0.5; const POSITION_TOLERANCE: f32 = 0.5; @@ -26,7 +26,7 @@ pub struct Cache { // TODO: Should functions be returning UiError instead of Error? impl Cache { pub fn new(renderer: &mut Renderer) -> Result { - let (w, h) = renderer.get_resolution().into_tuple(); + let (w, h) = renderer.resolution().into_tuple(); let max_texture_size = renderer.max_texture_size(); @@ -36,11 +36,11 @@ impl Cache { Ok(Self { text_cache: Default::default(), glyph_cache: GlyphCache::builder() - .dimensions(glyph_cache_dims.x as u32, glyph_cache_dims.y as u32) + .dimensions(glyph_cache_dims.x, glyph_cache_dims.y) .scale_tolerance(SCALE_TOLERANCE) .position_tolerance(POSITION_TOLERANCE) .build(), - glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims.map(|e| e as u16))?, + glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims), graphic_cache: GraphicCache::new(renderer), }) } @@ -82,14 +82,14 @@ impl Cache { self.text_cache.clear(); let max_texture_size = renderer.max_texture_size(); let cache_dims = renderer - .get_resolution() + .resolution() .map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512)); self.glyph_cache = GlyphCache::builder() - .dimensions(cache_dims.x as u32, cache_dims.y as u32) + .dimensions(cache_dims.x, cache_dims.y) .scale_tolerance(SCALE_TOLERANCE) .position_tolerance(POSITION_TOLERANCE) .build(); - self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims.map(|e| e as u16))?; + self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims); Ok(()) } } diff --git a/voxygen/src/ui/graphic/mod.rs b/voxygen/src/ui/graphic/mod.rs index f114b46486..461e7b8e87 100644 --- a/voxygen/src/ui/graphic/mod.rs +++ b/voxygen/src/ui/graphic/mod.rs @@ -48,7 +48,7 @@ pub enum Rotation { /// Fraction of the total graphic cache size const ATLAS_CUTOFF_FRAC: f32 = 0.2; /// Multiplied by current window size -const GRAPHIC_CACHE_RELATIVE_SIZE: u16 = 1; +const GRAPHIC_CACHE_RELATIVE_SIZE: u32 = 1; #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] pub struct Id(u32); @@ -303,7 +303,7 @@ impl GraphicCache { // Graphics over a particular size are sent to their own textures let location = if let Some(border_color) = border_color { // Create a new immutable texture. - let texture = create_image(renderer, image, border_color).unwrap(); + let texture = create_image(renderer, image, border_color); // NOTE: All mutations happen only after the upload succeeds! let index = textures.len(); textures.push(texture); @@ -354,7 +354,7 @@ impl GraphicCache { } } else { // Create a texture just for this - let texture = renderer.create_dynamic_texture(dims).unwrap(); + let texture = renderer.create_dynamic_texture(dims.map(|e| e as u32)); // NOTE: All mutations happen only after the texture creation succeeds! let index = textures.len(); textures.push(texture); @@ -409,10 +409,10 @@ fn draw_graphic( } } -fn atlas_size(renderer: &Renderer) -> Vec2 { +fn atlas_size(renderer: &Renderer) -> Vec2 { let max_texture_size = renderer.max_texture_size(); - renderer.get_resolution().map(|e| { + renderer.resolution().map(|e| { (e * GRAPHIC_CACHE_RELATIVE_SIZE) .max(512) .min(max_texture_size) @@ -421,8 +421,9 @@ fn atlas_size(renderer: &Renderer) -> Vec2 { fn create_atlas_texture(renderer: &mut Renderer) -> (SimpleAtlasAllocator, Texture) { let size = atlas_size(renderer); - let atlas = SimpleAtlasAllocator::new(size2(i32::from(size.x), i32::from(size.y))); - let texture = renderer.create_dynamic_texture(size).unwrap(); + // Note: here we assume the atlas size is under i32::MAX + let atlas = SimpleAtlasAllocator::new(size2(size.x as i32, size.y as i32)); + let texture = renderer.create_dynamic_texture(size); (atlas, texture) } @@ -435,25 +436,27 @@ fn aabr_from_alloc_rect(rect: guillotiere::Rectangle) -> Aabr { } fn upload_image(renderer: &mut Renderer, aabr: Aabr, tex: &Texture, image: &RgbaImage) { + let aabr = aabr.map(|e| e as u32); let offset = aabr.min.into_array(); let size = aabr.size().into_array(); - if let Err(e) = renderer.update_texture( + renderer.update_texture( tex, offset, size, // NOTE: Rgba texture, so each pixel is 4 bytes, ergo this cannot fail. // We make the cast parameters explicit for clarity. bytemuck::cast_slice::(&image), - ) { - warn!(?e, "Failed to update texture"); - } + ); } -fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba) { - renderer.create_texture( - &DynamicImage::ImageRgba8(image), - None, - Some(wgpu::AddressMode::ClampToBorder), - Some(border_color.into_array().into()), - ) +fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba) -> Texture { + renderer + .create_texture( + &DynamicImage::ImageRgba8(image), + None, + //TODO: either use the desktop only border color or just emulate this + // Some(border_color.into_array().into()), + Some(wgpu::AddressMode::ClampToBorder), + ) + .expect("create_texture only panics is non ImageRbga8 is passed") } diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 7066e649f2..c5fa5e1c6c 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -25,7 +25,7 @@ pub use widgets::{ use crate::{ render::{ - create_ui_quad, create_ui_tri, Consts, Globals, Mesh, Model, RenderError, Renderer, + create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, UIVertex, UiLocals, UiMode, }, window::Window, @@ -109,7 +109,7 @@ pub struct Ui { // during redrawing. mesh: Mesh, // Model for drawing the ui - model: Model, + model: DynamicModel, // Consts for default ui drawing position (ie the interface) interface_locals: Consts, default_globals: Consts, @@ -162,7 +162,7 @@ impl Ui { cache: Cache::new(renderer)?, draw_commands: Vec::new(), mesh: Mesh::new(), - model: renderer.create_dynamic_model(100)?, + model: renderer.create_dynamic_model(100), interface_locals: renderer.create_consts(&[UiLocals::default()])?, default_globals: renderer.create_consts(&[Globals::default()])?, ingame_locals: Vec::new(), @@ -334,7 +334,7 @@ impl Ui { // Avoid resetting cache if window size didn't change // Somewhat inefficient for elements that won't change size after a window // resize - let res = renderer.get_resolution(); + let res = renderer.resolution(); res.x > 0 && res.y > 0 && !(old_w == w && old_h == h) } else { false @@ -381,7 +381,7 @@ impl Ui { }; let (half_res, x_align, y_align) = { - let res = renderer.get_resolution(); + let res = renderer.resolution(); ( res.map(|e| e as f32 / 2.0), (res.x & 1) as f32 * 0.5, @@ -560,23 +560,15 @@ impl Ui { tracing::debug!("Updating glyphs and clearing text cache."); if let Err(err) = glyph_cache.cache_queued(|rect, data| { - let offset = [rect.min.x as u16, rect.min.y as u16]; - let size = [rect.width() as u16, rect.height() as u16]; + let offset = [rect.min.x as u32, rect.min.y as u32]; + let size = [rect.width() as u32, rect.height() as u32]; let new_data = data .iter() .map(|x| [255, 255, 255, *x]) .collect::>(); - if let Err(err) = renderer.update_texture( - cache_tex, - offset, - size, - &new_data, - rect.width() * 4, - ) { - warn!("Failed to update texture: {:?}", err); - } + renderer.update_texture(cache_tex, offset, size, &new_data); }) { // FIXME: If we actually hit this error, it's still possible we could salvage // things in various ways (for instance, the current queue might have extra @@ -821,6 +813,7 @@ impl Ui { let cache_dims = graphic_cache .get_tex(tex_id) .get_dimensions() + .xy() .map(|e| e as f32); let min = Vec2::new(aabr.min.x as f32, aabr.max.y as f32) / cache_dims; let max = Vec2::new(aabr.max.x as f32, aabr.min.y as f32) / cache_dims; @@ -954,12 +947,10 @@ impl Ui { // Push new position command let world_pos = Vec4::from_point(parameters.pos); if self.ingame_locals.len() > ingame_local_index { - renderer - .update_consts( - &mut self.ingame_locals[ingame_local_index], - &[world_pos.into()], - ) - .unwrap(); + renderer.update_consts( + &mut self.ingame_locals[ingame_local_index], + &[world_pos.into()], + ) } else { self.ingame_locals .push(renderer.create_consts(&[world_pos.into()]).unwrap()); @@ -1007,13 +998,11 @@ impl Ui { // Create a larger dynamic model if the mesh is larger than the current model // size. - if self.model.vbuf.len() < self.mesh.vertices().len() { - self.model = renderer - .create_dynamic_model(self.mesh.vertices().len() * 4 / 3) - .unwrap(); + if self.model.len() < self.mesh.vertices().len() { + self.model = renderer.create_dynamic_model(self.mesh.vertices().len() * 4 / 3); } // Update model with new mesh. - renderer.update_model(&self.model, &self.mesh, 0).unwrap(); + renderer.update_model(&self.model, &self.mesh, 0); } pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts>) { @@ -1035,7 +1024,9 @@ impl Ui { DrawKind::Plain => self.cache.glyph_cache_tex(), }; let model = self.model.submodel(verts.clone()); - renderer.render_ui_element(model, tex, scissor, globals, locals); + // TODO + //renderer.render_ui_element(model, tex, scissor, globals, + // locals); }, } } @@ -1043,12 +1034,12 @@ impl Ui { } fn default_scissor(renderer: &Renderer) -> Aabr { - let (screen_w, screen_h) = renderer.get_resolution().into_tuple(); + let (screen_w, screen_h) = renderer.resolution().into_tuple(); Aabr { min: Vec2 { x: 0, y: 0 }, max: Vec2 { - x: screen_w, - y: screen_h, + x: screen_w as u16, + y: screen_h as u16, }, } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 6d00e107ab..9158100725 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -518,7 +518,7 @@ impl KeyMouse { } pub struct Window { - renderer: Renderer<'static>, + renderer: Renderer, window: winit::window::Window, cursor_grabbed: bool, pub pan_sensitivity: u32, @@ -658,7 +658,7 @@ impl Window { pub fn renderer(&self) -> &Renderer { &self.renderer } - pub fn renderer_mut(&mut self) -> &mut Renderer<'static> { &mut self.renderer } + pub fn renderer_mut(&mut self) -> &mut Renderer { &mut self.renderer } pub fn resolve_deduplicated_events(&mut self, settings: &mut Settings) { // Handle screenshots and toggling fullscreen @@ -941,7 +941,9 @@ impl Window { // let (mut color_view, mut depth_view) = self.renderer.win_views_mut(); // self.window.resize(physical); // self.window.update_gfx(&mut color_view, &mut depth_view); - self.renderer.on_resize().unwrap(); + self.renderer + .on_resize(Vec2::new(physical.width, physical.height)) + .unwrap(); // TODO: update users of this event with the fact that it is now the physical // size let winit::dpi::PhysicalSize { width, height } = physical;